UNPKG

tilestrata-mapnik

Version:

A TileStrata plugin for rendering tiles with mapnik

77 lines (66 loc) 2 kB
module.exports = LockingCache; function LockingCache(generate, timeout) { this.callbacks = {}; this.timeouts = {}; this.results = {}; // When there's no generator function, you this.generate = generate || function() {}; // Timeout cached objects after 1 minute by default. // A value of 0 will cause it to not cache at all beyond, just return the result to // all locked requests. this.timeout = (typeof timeout === "undefined") ? 60000 : timeout; } LockingCache.prototype.get = function(id, callback) { if (!this.callbacks[id]) this.callbacks[id] = []; this.callbacks[id].push(callback); if (this.results[id]) { this.trigger(id); } else { var ids = this.generate.call(this, id); if (!ids || ids.indexOf(id) < 0) { this.put(id, new Error("Generator didn't generate this item")); } else ids.forEach(function(id) { this.results[id] = this.results[id] || true; }, this); } }; LockingCache.prototype.del = function(id) { delete this.results[id]; delete this.callbacks[id]; if (this.timeouts[id]) { clearTimeout(this.timeouts[id]); delete this.timeouts[id]; } }; LockingCache.prototype.put = function(id) { if (this.timeout > 0) { this.timeouts[id] = setTimeout(this.del.bind(this, id), this.timeout); } this.results[id] = Array.prototype.slice.call(arguments, 1); if (this.callbacks[id] && this.callbacks[id].length) { this.trigger(id); } }; LockingCache.prototype.clear = function() { for (var id in this.timeouts) { this.del(id); } }; LockingCache.prototype.trigger = function(id) { if (this.results[id] && this.results[id] !== true) { process.nextTick(function() { var data = this.results[id]; var callbacks = this.callbacks[id] || []; if (this.timeout === 0) { // instant purge with the first put() for a key // clears timeouts and results this.del(id); } else { delete this.callbacks[id]; } callbacks.forEach(function(callback) { callback.apply(callback, data); }); }.bind(this)); } };