tilestrata-mapnik
Version:
A TileStrata plugin for rendering tiles with mapnik
77 lines (66 loc) • 2 kB
JavaScript
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));
}
};