Last active
December 12, 2021 13:41
-
-
Save oitee/ed396afeba5b122349be3d4cda1bd90f to your computer and use it in GitHub Desktop.
Database server that stores key-value pairs
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
export default class KVStore { | |
#data; | |
constructor() { | |
this.#data = new Map(); | |
} | |
/** | |
* Given a key, returns its value | |
* @param {any} key | |
* @returns {any} | |
*/ | |
get(key) { | |
return this.#data.get(key); | |
} | |
/** | |
* Updates/Inserts a given key-value pair | |
* @param {any} key | |
* @param {any} value | |
*/ | |
set(key, value) { | |
this.#data.set(key, value); | |
} | |
/** | |
* Returns all keys in the store | |
* @returns array | |
*/ | |
getAllKeys() { | |
return this.#data.keys(); | |
} | |
} |
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
import launchServer from "./server.js"; | |
launchServer(4000); |
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": "penguin", | |
"version": "1.0.0", | |
"description": "", | |
"main": "src/launcher.js", | |
"directories": { | |
"test": "test" | |
}, | |
"scripts": { | |
"test": "NODE_OPTIONS=--experimental-vm-modules jest --coverage=true -i", | |
"start": "node src/launcher.js" | |
}, | |
"repository": { | |
"type": "git", | |
"url": "git+https://github.com/oitee/penguin.git" | |
}, | |
"author": "", | |
"license": "ISC", | |
"bugs": { | |
"url": "https://github.com/oitee/penguin/issues" | |
}, | |
"homepage": "https://github.com/oitee/penguin#readme", | |
"devDependencies": { | |
"jest": "^27.4.4", | |
"node-fetch": "^3.1.0" | |
}, | |
"jest": { | |
"testMatch": [ | |
"**/test/**.js" | |
], | |
"testTimeout": 60000, | |
"modulePathIgnorePatterns": [], | |
"setupFilesAfterEnv": [] | |
}, | |
"type": "module" | |
} |
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
import KVStore from "./kv_store.js"; | |
import http from "http"; | |
import url from "url"; | |
/** | |
* Handler for setting keys in the store | |
* @param {KVStore} store | |
* @param {Object} response | |
* @param {Object} queryParameters | |
* @returns Object | |
*/ | |
function setKeys(store, response, queryParameters) { | |
if (!queryParameters || Object.keys(queryParameters).length <= 0) { | |
return buildResponse( | |
response, | |
400, | |
`Invalid request: Query parameters empty` | |
); | |
} | |
for (let key in queryParameters) { | |
store.set(key, queryParameters[key]); | |
} | |
return buildResponse( | |
response, | |
200, | |
`Inserted the following keys: ${Object.keys(queryParameters)}` | |
); | |
} | |
/** | |
* Handler for getting value of a given key | |
* @param {KVStore} store | |
* @param {Object} response | |
* @param {Object} queryParameters | |
* @returns Object | |
*/ | |
function getKey(store, response, queryParameters) { | |
if (!queryParameters || !queryParameters.key) { | |
return buildResponse(response, 400, `Invalid request: Key cannot be empty`); | |
} | |
const result = store.get(queryParameters.key); | |
if (typeof result === "string") { | |
return buildResponse(response, 200, `The value is: ${result}`); | |
} | |
return buildResponse( | |
response, | |
404, | |
`The key "${queryParameters.key}" does not exist` | |
); | |
} | |
/** | |
* Creates a new store and returns a corresponding | |
* server handler that encapsulates the store | |
* @returns function | |
*/ | |
function generateServerHandler() { | |
const store = new KVStore(); | |
return (request, response) => { | |
let requestUrl = url.parse(request.url, true); | |
let urlPath = requestUrl.pathname; | |
switch (urlPath) { | |
case "/set": | |
return setKeys(store, response, requestUrl.query); | |
case "/get": | |
return getKey(store, response, requestUrl.query); | |
default: | |
return buildResponse( | |
response, | |
404, | |
`Invalid Request: Route not defined` | |
); | |
} | |
}; | |
} | |
/** | |
* Given a status and a message, adds a json-ified content to the | |
* response object and ends the response | |
* @param {Object} response | |
* @param {number} statusCode | |
* @param {string} message | |
* @returns Object | |
*/ | |
function buildResponse(response, statusCode, message) { | |
const responseBody = { status: statusCode === 200 }; | |
if (message) { | |
responseBody.message = message; | |
} | |
response.statusCode = statusCode; | |
response.setHeader("Content-Type", "application/json"); | |
return response.end(JSON.stringify(responseBody)); | |
} | |
/** | |
* Given a port, creates an http server | |
* @param {number} port | |
* @returns Object | |
*/ | |
export default function launchServer(port) { | |
const serverHandler = generateServerHandler(); | |
const server = http.createServer(serverHandler); | |
return server.listen(port, () => console.log(`Listening on port: ${port}...`)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment