UNPKG

@thermopylae/lib.cache

Version:
91 lines (90 loc) 2.58 kB
import { EventEmitter } from 'events'; import { NOT_FOUND_VALUE } from "../constants.js"; class PolicyBasedCache extends EventEmitter { backend; policies; constructor(backend, policies) { super(); this.backend = backend; this.policies = policies || []; for (const policy of this.policies) { policy.setDeleter(this.internalDelete); } } get size() { return this.backend.size; } get(key) { const entry = this.backend.get(key); if (entry === NOT_FOUND_VALUE) { for (const policy of this.policies) { policy.onMiss(key); } return entry; } for (const policy of this.policies) { if (policy.onHit(entry) === 0 ) { return NOT_FOUND_VALUE; } } return entry.value; } has(key) { return this.backend.has(key); } set(key, value, argsBundle) { let entry = this.backend.get(key); if (entry === NOT_FOUND_VALUE) { entry = this.backend.set(key, value); let policyIndex = 0; try { for (; policyIndex < this.policies.length; policyIndex++) { this.policies[policyIndex].onSet(entry, argsBundle); } this.emit("insert" , key, value); return; } catch (e) { for (let i = 0; i < policyIndex; i++) { this.policies[i].onDelete(entry); } this.backend.del(entry); throw e; } } entry.value = value; for (const policy of this.policies) { policy.onUpdate(entry, argsBundle); } this.emit("update" , key, value); } del(key) { const entry = this.backend.get(key); if (!entry) { return false; } this.internalDelete(entry); return true; } keys() { return Array.from(this.backend.keys()); } clear() { for (const policy of this.policies) { policy.onClear(); } this.backend.clear(); this.emit("flush" ); } on(event, listener) { return super.on(event, listener); } internalDelete = (entry) => { for (const policy of this.policies) { policy.onDelete(entry); } this.emit("delete" , entry.key, entry.value); this.backend.del(entry); }; } export { PolicyBasedCache };