diff --git a/endpraesi/website/src/index.ts b/endpraesi/website/src/index.ts index 822d2208..2857d56f 100644 --- a/endpraesi/website/src/index.ts +++ b/endpraesi/website/src/index.ts @@ -10,13 +10,6 @@ const arangoKv = arango.collection("kv"); type Timing = { op: string; key: string; ms: number }; -type Adapter = { - timings: Timing[]; - getObject: (key: string) => Promise; - getField: (key: string, field: string) => Promise; - getIds: (key: string) => Promise; -}; - function stringifyObj(o: any) { if (!o) return null; const out: any = {}; @@ -24,74 +17,104 @@ function stringifyObj(o: any) { return out; } -function redisAdapter(): Adapter { +function getRedisAdapter() { const timings: Timing[] = []; - const track = async (op: string, key: string, fn: () => Promise): Promise => { - const start = performance.now(); - const res = await fn(); - timings.push({ op, key, ms: performance.now() - start }); - return res; - }; return { timings, - getObject: (key) => - track("hgetall", key, async () => { - const o = await redis.hgetall(key); - return o && Object.keys(o).length ? o : null; - }), - getField: (key, field) => track("hget", key, () => redis.hget(key, field)), - getIds: (key) => track("smembers", key, async () => (await redis.smembers(key)) || []), + async getObject(key: string) { + const start = performance.now(); + const o = await redis.hgetall(key); + timings.push({ op: "hgetall", key, ms: performance.now() - start }); + return o && Object.keys(o).length ? o : null; + }, + async getField(key: string, field: string) { + const start = performance.now(); + const res = await redis.hget(key, field); + timings.push({ op: "hget", key, ms: performance.now() - start }); + return res; + }, + async getIds(key: string) { + const start = performance.now(); + const res = await redis.smembers(key); + timings.push({ op: "smembers", key, ms: performance.now() - start }); + return res || []; + } }; } -function memcachedAdapter(): Adapter { +function getMemcachedAdapter() { const timings: Timing[] = []; - const getJson = async (key: string) => { + + async function getJson(key: string) { const { value } = await memcached.get(key); return value ? JSON.parse(value.toString()) : null; - }; - const track = async (op: string, key: string, fn: () => Promise): Promise => { - const start = performance.now(); - const res = await fn(); - timings.push({ op, key, ms: performance.now() - start }); - return res; - }; + } + return { timings, - getObject: (key) => track("get", key, async () => stringifyObj(await getJson(key))), - getField: (key, field) => track("get", key, async () => (await getJson(key))?.[field] ?? null), - getIds: (key) => track("get", key, async () => ((await getJson(key)) || []).map(String)), + async getObject(key: string) { + const start = performance.now(); + const res = await getJson(key); + timings.push({ op: "get", key, ms: performance.now() - start }); + return stringifyObj(res); + }, + async getField(key: string, field: string) { + const start = performance.now(); + const res = await getJson(key); + timings.push({ op: "get", key, ms: performance.now() - start }); + return res ? res[field] : null; + }, + async getIds(key: string) { + const start = performance.now(); + const res = await getJson(key); + timings.push({ op: "get", key, ms: performance.now() - start }); + return res ? res.map(String) : []; + } }; } -function arangoAdapter(): Adapter { +function getArangoAdapter() { const timings: Timing[] = []; - const getVal = async (key: string) => { + + async function getVal(key: string) { const doc = await arangoKv.document(key, { graceful: true }); return doc ? doc.value : null; - }; - const track = async (op: string, key: string, fn: () => Promise): Promise => { - const start = performance.now(); - const res = await fn(); - timings.push({ op, key, ms: performance.now() - start }); - return res; - }; + } + return { timings, - getObject: (key) => track("document", key, async () => stringifyObj(await getVal(key))), - getField: (key, field) => track("document", key, async () => (await getVal(key))?.[field] ?? null), - getIds: (key) => track("document", key, async () => ((await getVal(key)) || []).map(String)), + async getObject(key: string) { + const start = performance.now(); + const res = await getVal(key); + timings.push({ op: "document", key, ms: performance.now() - start }); + return stringifyObj(res); + }, + async getField(key: string, field: string) { + const start = performance.now(); + const res = await getVal(key); + timings.push({ op: "document", key, ms: performance.now() - start }); + return res ? res[field] : null; + }, + async getIds(key: string) { + const start = performance.now(); + const res = await getVal(key); + timings.push({ op: "document", key, ms: performance.now() - start }); + return res ? res.map(String) : []; + } }; } -function getAdapter(db: string): Adapter { - if (db === "memcached") return memcachedAdapter(); - if (db === "arangodb") return arangoAdapter(); - return redisAdapter(); +function getAdapter(db: string) { + if (db === "memcached") return getMemcachedAdapter(); + if (db === "arangodb") return getArangoAdapter(); + return getRedisAdapter(); } function timingSummary(timings: Timing[]) { - const total = timings.reduce((s, t) => s + t.ms, 0); + let total = 0; + for (const t of timings) { + total += t.ms; + } return { count: timings.length, total, ops: timings }; }