mirror of
https://github.com/wukko/cobalt.git
synced 2025-03-24 18:24:46 +01:00
72 lines
1.9 KiB
JavaScript
72 lines
1.9 KiB
JavaScript
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();
|
|
}
|
|
}
|