Last active
October 26, 2017 10:38
-
-
Save o0101/d17eca7e68506590fda8c2e26a6dd887 to your computer and use it in GitHub Desktop.
key-value-datastore
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** see a live demo here: https://runkit.io/dosyago-coder-0/kvdb/branches/master **/ | |
const express = require("express"); | |
const bodyParser = require("body-parser"); | |
const db = new Map(); | |
const page = () => ` | |
<!DOCTYPE html> | |
<meta charset=utf-8> | |
<title>kvdb</title> | |
<style> | |
:root { | |
background: #af1; | |
} | |
body { | |
text-align: center; | |
} | |
article { | |
display: inline-flex; | |
margin: 0 auto; | |
} | |
iframe { | |
border-width: 0px; | |
} | |
footer ul li { | |
display: inline-block; | |
text-align: center; | |
margin: 0 0.5rem; | |
} | |
</style> | |
<main> | |
<header> | |
<h1>key-value-database console</h1> | |
</header> | |
<article> | |
<form action="set" method=GET target="setresult"> | |
<fieldset><legend>Set a key</legend> | |
<p> | |
<input required type=text | |
placeholder=key name=key value="" maxlength=63> | |
<p> | |
<textarea name=value placeholder=value | |
rows=6 cols=23 | |
maxlength=2046 value=""></textarea> | |
<p> | |
<button>Set</button> | |
</fieldset> | |
<fieldset><legend>Set result</legend> | |
<iframe name=setresult src=about:blank | |
width=100% height=64px></iframe> | |
</fieldset> | |
</form> | |
<form action="get" method=GET target="getresult"> | |
<fieldset><legend>Get a key</legend> | |
<p> | |
<input required type=text | |
placeholder=key name=key value="" maxlength=63> | |
<p> | |
<button>Get</button> | |
</fieldset> | |
<fieldset><legend>Get result</legend> | |
<iframe name=getresult src=about:blank | |
width=100% height=128px></iframe> | |
</fieldset> | |
</form> | |
</article> | |
<footer> | |
<ul> | |
<li> <a rel=alternate type=text/javascript | |
target=_blank | |
href=https://gist.github.com/dosyago-coder-0/d17eca7e68506590fda8c2e26a6dd887>the Gist</a> | |
<li> <a rel=alternate type=application/zip | |
download | |
href=https://gist.github.com/dosyago-coder-0/d17eca7e68506590fda8c2e26a6dd887/archive/b2bc1c4415dc98ec4229c27a96f80c3fda7abf83.zip>download the Gist (zip)</a> | |
<li> <a rel=alternate type=text/javascript | |
target=_blank | |
href=https://runkit.com/dosyago-coder-0/kvdb>the RunKit</a> | |
<li> <a rel=alternate type=application/javascript | |
target=_blank | |
href=https://runkit.io/dosyago-coder-0/kvdb/branches/master>the RunKit endpoint (live demo)</a> | |
</ul> | |
</footer> | |
</main> | |
`; | |
const setresult = ({status,key,date}={}) => ` | |
<!DOCTYPE html> | |
<meta charset=utf-8> | |
<title>kvdb set result</title> | |
<style> | |
:root { | |
background: #c0ffee; | |
} | |
.keyname { | |
font-weight: bold; | |
} | |
.statustext { | |
font-variant: italic; | |
} | |
.timestamp { | |
font-size: 0.75rem; | |
font-family: monospace; | |
color: grey; | |
} | |
</style> | |
<p> | |
Key <span class=keyname>${key}</span> is <span class=statustext>${ | |
status ? 'set' : 'not set' | |
}</span> @ <time value="${date}" class=timestamp>${date.toLocaleTimeString()}</time>. | |
</p> | |
`; | |
const getresult = ({status,key,value,date}={}) => ` | |
<!DOCTYPE html> | |
<meta charset=utf-8> | |
<title>kvdb get result</title> | |
<style> | |
:root { | |
background: #c0ffee; | |
} | |
.keyname { | |
font-weight: bold; | |
} | |
.statustext { | |
font-variant: italic; | |
} | |
.valuetext { | |
white-space: pre-wrap; | |
font-family: monospace; | |
} | |
.timestamp { | |
font-size: 0.75rem; | |
font-family: monospace; | |
color: grey; | |
} | |
</style> | |
<p> | |
Key <span class=keyname>${key}</span> is <span class=statustext>${ | |
status ? 'retrieved' : 'not found' | |
}</span> @ <time value="${date}" class=timestamp>${date.toLocaleTimeString()}</time>. | |
</p> | |
<dl> | |
<dt><span class=keyname>${key}</span> | |
<dd> | |
<p class=valuetext>${value}</p> | |
</dd> | |
</dl> | |
`; | |
const app = express(); | |
/** | |
app.use(bodyParser.json() ); // to support JSON-encoded bodies | |
app.use(bodyParser.urlencoded({ // to support URL-encoded bodies | |
extended: true | |
})); | |
**/ | |
app.get("/", async (req,res,next) => { | |
res.type('html'); | |
res.end(page()); | |
}); | |
app.get("/set", async (req,res,next) => { | |
res.type('html'); | |
const {key,value} = req.query; | |
const date = new Date; | |
let status = false; | |
if ( !! key ) { | |
db.set(key,value); | |
status = true; | |
} | |
res.end(setresult({key,status,date})); | |
}); | |
app.get("/get", async (req,res,next) => { | |
res.type('html'); | |
const {key} = req.query; | |
const date = new Date; | |
const status = db.has( key ); | |
let value; | |
if ( status ) { | |
value = db.get(key); | |
} | |
res.end(getresult({key,status,value,date})); | |
}); | |
app.get("/:anything", async (req,res,next) => { | |
res.type('html'); | |
res.status(404); | |
res.end('404 Not found'); | |
}); | |
app.listen(4000, () => console.log(`Server up @ ${new Date}`)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "kvdb", | |
"version": "1.0.0", | |
"description": "key-value-database", | |
"main": "kvdb.js", | |
"dependencies": { | |
"express": "^4.16.2" | |
}, | |
"devDependencies": {}, | |
"scripts": { | |
"test": "node kvdb.js" | |
}, | |
"repository": { | |
"type": "git", | |
"url": "https://gist.github.com/dosyago-coder-0/d17eca7e68506590fda8c2e26a6dd887/edit" | |
}, | |
"keywords": [ | |
"key-value", | |
"simple", | |
"database", | |
"store" | |
], | |
"author": "Cris <writetocris@outlook.com>", | |
"license": "MIT" | |
} |
Just trying to quickly study up on file system API. I am not familiar with it.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I'm thinking about this.
I like simple, append only, flat file.
That means we have DB history, and everything else.
The issue is startup where we read in and process the events ( one event per line ). But that's fine.
We shall not be touching a memory limit in this implementation anyway.
And there's nothing wrong with putting your table into memory. Advice for SQL is to put the entirety of your biggest table in memory. So that's fine.
I like the idea of "event" database. Since insertion is easy, even if we are not querying.
Also I want to make each line base 64 encoded.
The file itself needs to query information.
Index is built in memory.
What sort of index ?
Index on keys. Obviously.
Index on values. Reverse index. Okay.
Index on functions of keys or values. Such as key prefix or value prefix, or key chunks or value chunks. Things like that.
We can make a general "index builder function" that takes two parameters, slot, which can be "key" or "value", and transform function,
which transforms a single k,v into an index. In otherwords, transform takes an index, and a k,v and adds that k,v to that index.
Simple.
Indexes need a simple format, such as to be a class that accepts a query function call.