diff --git a/README.md b/README.md index ea2c393..0fb64af 100644 --- a/README.md +++ b/README.md @@ -132,6 +132,11 @@ Immediately remove a key from the cache. ###`#expire(key, [ms=0])` Update the expire time for a key. You can also use any valid [ms](https://github.com/rauchg/ms.js) string for a timeout. +###`#on('expiration', function)` +Add a callback for handling expiration events. The handler will be passed a single parameter, +the key name that was just expired. Note, the handler is called AFTER the key has been removed +from the Receptacle. + ###`#clear()` Remove all keys from the cache. diff --git a/index.d.ts b/index.d.ts index 9921d49..0ce3199 100644 --- a/index.d.ts +++ b/index.d.ts @@ -29,6 +29,12 @@ namespace Receptacle { key: string; value: T; } + + export Handler(key: string) : void + + export enum Events { + eviction, + } } class Receptacle { @@ -37,6 +43,7 @@ class Receptacle { public max: number; public items: Receptacle.Items[]; public size: number; + public on(event: Receptacle.Event, handler: Receptacle.Handler): void; public has(key: string): boolean; public get(key: string): T|null; public meta(key: string): X|undefined; diff --git a/index.js b/index.js index 5b780d0..6bf0939 100644 --- a/index.js +++ b/index.js @@ -3,7 +3,9 @@ module.exports = Receptacle var toMS = require('ms') var cache = Receptacle.prototype +console.dir(cache) var counter = new Date() % 1e9 +var EventEmitter = require('events') function getUID () { return (Math.random() * 1e9 >>> 0) + (counter++) } @@ -21,6 +23,7 @@ function Receptacle (options) { this.max = options.max || Infinity this.items = options.items || [] this._lookup = {} + this._events = new EventEmitter() this.size = this.items.length this.lastModified = new Date(options.lastModified || new Date()) @@ -34,6 +37,17 @@ function Receptacle (options) { } } +/** + * Currently only the evict type is supported. + * + * @param {String} event - the event name. + * @param {Receptacle.Event} handler - the event handler + * @return {Boolean} + */ +cache.on = function (event, handler) { + return this._events.on(event, handler.bind(this)) +} + /** * Tests if a key is currently in the cache. * Does not check if slot is empty. @@ -144,7 +158,10 @@ cache.expire = function (key, ttl) { if (typeof ms === 'string') ms = toMS(ttl) if (typeof ms !== 'number') throw new TypeError('Expiration time must be a string or number.') clearTimeout(record.timeout) - record.timeout = setTimeout(this.delete.bind(this, record.key), ms) + record.timeout = setTimeout(function () { + this.delete(record.key) + this._events.emit('eviction', record.key) + }.bind(this), ms) record.expires = Number(new Date()) + ms return this } diff --git a/package-lock.json b/package-lock.json index 773b512..d61ae67 100644 --- a/package-lock.json +++ b/package-lock.json @@ -84,6 +84,7 @@ "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, + "optional": true, "requires": { "kind-of": "^3.0.2", "longest": "^1.0.1", @@ -2368,6 +2369,7 @@ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.1.0.tgz", "integrity": "sha1-R11pil5J/15T0U4+cyQp3Iv0z0c=", "dev": true, + "optional": true, "requires": { "is-buffer": "^1.0.2" } @@ -2475,7 +2477,8 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true + "dev": true, + "optional": true }, "loose-envify": { "version": "1.3.1", @@ -3176,7 +3179,8 @@ "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true + "dev": true, + "optional": true }, "request": { "version": "2.87.0", diff --git a/test/main.test.js b/test/main.test.js index 47ab1ea..423d33e 100644 --- a/test/main.test.js +++ b/test/main.test.js @@ -34,6 +34,17 @@ describe('Receptacle', function () { }) }) + describe('#on', function () { + it('should emit an expiration event', function (done) { + var cache = new Receptacle() + cache.on('eviction', function (key) { + console.log('evicted: ' + key) + done() + }) + cache.set('a', 1, { ttl: 200 }) + }) + }) + describe('#meta', function () { it('should return a set key', function () { var cache = new Receptacle()