69 lines
1.9 KiB
TypeScript
69 lines
1.9 KiB
TypeScript
import { logger } from '../logging.ts';
|
|
import type { CacheDb } from './classes.cachedb.ts';
|
|
|
|
// deno-lint-ignore no-explicit-any
|
|
type DocumentClass = { getInstances: (filter: any) => Promise<{ delete: () => Promise<void> }[]> };
|
|
|
|
const DEFAULT_INTERVAL_MS = 60 * 60 * 1000; // 1 hour
|
|
|
|
/**
|
|
* Periodically cleans up expired cached documents.
|
|
*/
|
|
export class CacheCleaner {
|
|
private intervalId: number | null = null;
|
|
private intervalMs: number;
|
|
private documentClasses: DocumentClass[] = [];
|
|
private cacheDb: CacheDb;
|
|
|
|
constructor(cacheDb: CacheDb, intervalMs = DEFAULT_INTERVAL_MS) {
|
|
this.cacheDb = cacheDb;
|
|
this.intervalMs = intervalMs;
|
|
}
|
|
|
|
/** Register a document class for cleanup */
|
|
registerClass(cls: DocumentClass): void {
|
|
this.documentClasses.push(cls);
|
|
}
|
|
|
|
start(): void {
|
|
if (this.intervalId !== null) return;
|
|
this.intervalId = setInterval(() => {
|
|
this.clean().catch((err) => {
|
|
logger.error(`CacheCleaner error: ${err}`);
|
|
});
|
|
}, this.intervalMs);
|
|
// Unref so the interval doesn't prevent process exit
|
|
Deno.unrefTimer(this.intervalId);
|
|
logger.debug(`CacheCleaner started (interval: ${this.intervalMs}ms)`);
|
|
}
|
|
|
|
stop(): void {
|
|
if (this.intervalId !== null) {
|
|
clearInterval(this.intervalId);
|
|
this.intervalId = null;
|
|
logger.debug('CacheCleaner stopped');
|
|
}
|
|
}
|
|
|
|
/** Run a single cleanup pass */
|
|
async clean(): Promise<number> {
|
|
const now = Date.now();
|
|
let totalDeleted = 0;
|
|
for (const cls of this.documentClasses) {
|
|
try {
|
|
const expired = await cls.getInstances({ expiresAt: { $lt: now } });
|
|
for (const doc of expired) {
|
|
await doc.delete();
|
|
totalDeleted++;
|
|
}
|
|
} catch (err) {
|
|
logger.error(`CacheCleaner: failed to clean class: ${err}`);
|
|
}
|
|
}
|
|
if (totalDeleted > 0) {
|
|
logger.debug(`CacheCleaner: deleted ${totalDeleted} expired document(s)`);
|
|
}
|
|
return totalDeleted;
|
|
}
|
|
}
|