Studentify database clients and website API adapters
This commit is contained in:
parent
9c719b96b3
commit
a35e6a99cb
@ -10,13 +10,6 @@ const arangoKv = arango.collection("kv");
|
|||||||
|
|
||||||
type Timing = { op: string; key: string; ms: number };
|
type Timing = { op: string; key: string; ms: number };
|
||||||
|
|
||||||
type Adapter = {
|
|
||||||
timings: Timing[];
|
|
||||||
getObject: (key: string) => Promise<any>;
|
|
||||||
getField: (key: string, field: string) => Promise<any>;
|
|
||||||
getIds: (key: string) => Promise<string[]>;
|
|
||||||
};
|
|
||||||
|
|
||||||
function stringifyObj(o: any) {
|
function stringifyObj(o: any) {
|
||||||
if (!o) return null;
|
if (!o) return null;
|
||||||
const out: any = {};
|
const out: any = {};
|
||||||
@ -24,74 +17,104 @@ function stringifyObj(o: any) {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
function redisAdapter(): Adapter {
|
function getRedisAdapter() {
|
||||||
const timings: Timing[] = [];
|
const timings: Timing[] = [];
|
||||||
const track = async <T>(op: string, key: string, fn: () => Promise<T>): Promise<T> => {
|
|
||||||
const start = performance.now();
|
|
||||||
const res = await fn();
|
|
||||||
timings.push({ op, key, ms: performance.now() - start });
|
|
||||||
return res;
|
|
||||||
};
|
|
||||||
return {
|
return {
|
||||||
timings,
|
timings,
|
||||||
getObject: (key) =>
|
async getObject(key: string) {
|
||||||
track("hgetall", key, async () => {
|
const start = performance.now();
|
||||||
const o = await redis.hgetall(key);
|
const o = await redis.hgetall(key);
|
||||||
return o && Object.keys(o).length ? o : null;
|
timings.push({ op: "hgetall", key, ms: performance.now() - start });
|
||||||
}),
|
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 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 timings: Timing[] = [];
|
||||||
const getJson = async (key: string) => {
|
|
||||||
|
async function getJson(key: string) {
|
||||||
const { value } = await memcached.get(key);
|
const { value } = await memcached.get(key);
|
||||||
return value ? JSON.parse(value.toString()) : null;
|
return value ? JSON.parse(value.toString()) : null;
|
||||||
};
|
}
|
||||||
const track = async <T>(op: string, key: string, fn: () => Promise<T>): Promise<T> => {
|
|
||||||
const start = performance.now();
|
|
||||||
const res = await fn();
|
|
||||||
timings.push({ op, key, ms: performance.now() - start });
|
|
||||||
return res;
|
|
||||||
};
|
|
||||||
return {
|
return {
|
||||||
timings,
|
timings,
|
||||||
getObject: (key) => track("get", key, async () => stringifyObj(await getJson(key))),
|
async getObject(key: string) {
|
||||||
getField: (key, field) => track("get", key, async () => (await getJson(key))?.[field] ?? null),
|
const start = performance.now();
|
||||||
getIds: (key) => track("get", key, async () => ((await getJson(key)) || []).map(String)),
|
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 timings: Timing[] = [];
|
||||||
const getVal = async (key: string) => {
|
|
||||||
|
async function getVal(key: string) {
|
||||||
const doc = await arangoKv.document(key, { graceful: true });
|
const doc = await arangoKv.document(key, { graceful: true });
|
||||||
return doc ? doc.value : null;
|
return doc ? doc.value : null;
|
||||||
};
|
}
|
||||||
const track = async <T>(op: string, key: string, fn: () => Promise<T>): Promise<T> => {
|
|
||||||
const start = performance.now();
|
|
||||||
const res = await fn();
|
|
||||||
timings.push({ op, key, ms: performance.now() - start });
|
|
||||||
return res;
|
|
||||||
};
|
|
||||||
return {
|
return {
|
||||||
timings,
|
timings,
|
||||||
getObject: (key) => track("document", key, async () => stringifyObj(await getVal(key))),
|
async getObject(key: string) {
|
||||||
getField: (key, field) => track("document", key, async () => (await getVal(key))?.[field] ?? null),
|
const start = performance.now();
|
||||||
getIds: (key) => track("document", key, async () => ((await getVal(key)) || []).map(String)),
|
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 {
|
function getAdapter(db: string) {
|
||||||
if (db === "memcached") return memcachedAdapter();
|
if (db === "memcached") return getMemcachedAdapter();
|
||||||
if (db === "arangodb") return arangoAdapter();
|
if (db === "arangodb") return getArangoAdapter();
|
||||||
return redisAdapter();
|
return getRedisAdapter();
|
||||||
}
|
}
|
||||||
|
|
||||||
function timingSummary(timings: Timing[]) {
|
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 };
|
return { count: timings.length, total, ops: timings };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user