@thermopylae/lib.cache
Version:
85 lines (84 loc) • 2.85 kB
JavaScript
import { chrono } from '@thermopylae/lib.utils';
import { EXPIRES_AT_SYM } from "../constants.js";
class IntervalGarbageCollector {
options;
getNextCacheEntry;
iterateTimeoutId;
entryExpiredCb;
constructor(options) {
this.options = IntervalGarbageCollector.fillWithDefaults(options);
this.getNextCacheEntry = IntervalGarbageCollector.createCacheEntriesCircularIterator(this.options.iterableBackend);
this.iterateTimeoutId = null;
}
get idle() {
return this.iterateTimeoutId == null;
}
get size() {
return this.options.iterableBackend.size;
}
manage() {
if (this.idle) {
this.iterateTimeoutId = setTimeout(this.evictExpiredEntries, this.options.checkInterval);
}
}
update() {
if (this.idle) {
this.iterateTimeoutId = setTimeout(this.evictExpiredEntries, this.options.checkInterval);
}
}
leave() {
return undefined;
}
clear() {
clearTimeout(this.iterateTimeoutId);
this.iterateTimeoutId = null;
}
setEntryExpiredCallback(cb) {
this.entryExpiredCb = cb;
}
evictExpiredEntries = () => {
const startingEntry = this.getNextCacheEntry();
if (startingEntry == null) {
this.iterateTimeoutId = null;
return;
}
let currentEntry = startingEntry;
let iteratedEntries = 0;
do {
if (currentEntry[EXPIRES_AT_SYM] <= chrono.unixTime()) {
this.entryExpiredCb(currentEntry);
}
if (++iteratedEntries < this.options.iterateCount) {
currentEntry = this.getNextCacheEntry();
continue;
}
break;
} while (currentEntry != startingEntry && this.options.iterableBackend.size);
if (this.options.iterableBackend.size) {
this.iterateTimeoutId = setTimeout(this.evictExpiredEntries, this.options.checkInterval);
return;
}
this.iterateTimeoutId = null;
};
static fillWithDefaults(options) {
options = { ...options };
options.checkInterval = chrono.secondsToMilliseconds(options.checkInterval || 15);
options.iterateCount = options.iterateCount || 100;
return options;
}
static createCacheEntriesCircularIterator(backend) {
let iterator = backend.values();
return function nextCacheEntry() {
let iterResult = iterator.next();
if (iterResult.done) {
iterator = backend.values();
iterResult = iterator.next();
if (iterResult.done) {
return null;
}
}
return iterResult.value;
};
}
}
export { IntervalGarbageCollector };