api: implement redis/memory store for cache
This commit is contained in:
72
api/src/store/memory-store.js
Normal file
72
api/src/store/memory-store.js
Normal file
@@ -0,0 +1,72 @@
|
||||
import { MinPriorityQueue } from '@datastructures-js/priority-queue'
|
||||
import { Store } from './base-store.js';
|
||||
|
||||
// minimum delay between sweeps to avoid repeatedly
|
||||
// sweeping entries close in proximity one by one.
|
||||
const MIN_THRESHOLD_MS = 2500;
|
||||
|
||||
export default class MemoryStore extends Store {
|
||||
#store = new Map();
|
||||
#timeouts = new MinPriorityQueue/*<{ t: number, k: unknown }>*/((obj) => obj.t);
|
||||
#nextSweep = { id: null, t: null };
|
||||
|
||||
constructor(name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
async _get(key) {
|
||||
const val = this.#store.get(key);
|
||||
|
||||
return val === undefined ? null : val;
|
||||
}
|
||||
|
||||
async _set(key, val, exp_sec = -1) {
|
||||
if (this.#store.has(key)) {
|
||||
this.#timeouts.remove(o => o.k === key);
|
||||
}
|
||||
|
||||
if (exp_sec > 0) {
|
||||
const exp = 1000 * exp_sec;
|
||||
const timeout_at = +new Date() + exp;
|
||||
|
||||
this.#timeouts.enqueue({ k: key, t: timeout_at });
|
||||
}
|
||||
|
||||
this.#store.set(key, val);
|
||||
this.#reschedule();
|
||||
}
|
||||
|
||||
#reschedule() {
|
||||
const current_time = new Date().getTime();
|
||||
const time = this.#timeouts.front()?.t;
|
||||
if (!time) {
|
||||
return;
|
||||
} else if (time < current_time) {
|
||||
return this.#sweepNow();
|
||||
}
|
||||
|
||||
const sweep = this.#nextSweep;
|
||||
if (sweep.id === null || sweep.t > time) {
|
||||
if (sweep.id) {
|
||||
clearTimeout(sweep.id);
|
||||
}
|
||||
|
||||
sweep.t = time;
|
||||
sweep.id = setTimeout(
|
||||
() => this.#sweepNow(),
|
||||
Math.max(MIN_THRESHOLD_MS, time - current_time)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#sweepNow() {
|
||||
while (this.#timeouts.front()?.t < new Date().getTime()) {
|
||||
const item = this.#timeouts.dequeue();
|
||||
this.#store.delete(item.k);
|
||||
}
|
||||
|
||||
this.#nextSweep.id = null;
|
||||
this.#nextSweep.t = null;
|
||||
this.#reschedule();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user