From f0b8c29b035cb6688624c204a2972d4493197086 Mon Sep 17 00:00:00 2001 From: javi Date: Fri, 21 Oct 2011 16:33:35 +0200 Subject: [PATCH] added ttl --- lib/cartodb/tile_cache.js | 24 ++++++++++++++--- lib/cartodb/ttl.js | 47 ++++++++++++++++++++++++++++++++ test/unit/cartodb/ttl.test.js | 50 +++++++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+), 4 deletions(-) create mode 100644 lib/cartodb/ttl.js create mode 100644 test/unit/cartodb/ttl.test.js diff --git a/lib/cartodb/tile_cache.js b/lib/cartodb/tile_cache.js index c2c0072e..bc7b85ef 100644 --- a/lib/cartodb/tile_cache.js +++ b/lib/cartodb/tile_cache.js @@ -4,7 +4,8 @@ // 'lru' implements a LRU cache var LRUCache = require('./lru'), - CacheValidator = require('./cache_validator') + CacheValidator = require('./cache_validator'), + TTL = require('./TTL'); var BLANK_TILE_SIZE = 334; // totally transparent tile size in bytes @@ -31,7 +32,7 @@ module.exports.LRUcache = function(max_items, redis_opts) { // implements a generic cache for tile // cache_policy should implement set and get methods and optionally getStats -function GenericCache (cache_policy, cache_validator) { +function GenericCache (cache_policy, cache_validator, ttl_timeout) { var me = { cache: cache_policy, @@ -40,9 +41,16 @@ function GenericCache (cache_policy, cache_validator) { cache_misses: 0, cache_not_modified: 0, current_items: 0, + expired: 0, cache_invalidated: 0, max_items: 0 - } + }; + + // enable ttl + var ttl = TTL(function(key) { + me.remove(key); + me.expired++; + }, ttl_timeout || 60); function cache_key(req) { return req.url; @@ -55,6 +63,12 @@ function GenericCache (cache_policy, cache_validator) { } } + me.remove = function(key) { + ttl.remove(key); + me.cache.remove(key); + update_items(me.cache.size || 0); + } + me.beforeTileRender = function(req, res, callback) { req.windshaft_start = new Date().getTime(); var key = cache_key(req); @@ -97,12 +111,14 @@ function GenericCache (cache_policy, cache_validator) { me.afterTileRender = function(req, res, tile, headers, callback) { var timestamp = new Date().getTime(); var delta = timestamp - req.windshaft_start; - me.cache.put(cache_key(req), { + var key = cache_key(req); + me.cache.put(key, { tile: tile, headers: headers, timestamp: timestamp/1000.0, render_time: delta/1000.0, hits: 0}); + ttl.start(key); update_items(me.cache.size || 0); callback(null, tile, headers); } diff --git a/lib/cartodb/ttl.js b/lib/cartodb/ttl.js new file mode 100644 index 00000000..443911ba --- /dev/null +++ b/lib/cartodb/ttl.js @@ -0,0 +1,47 @@ + +/* + ========================================================== + manages timeouts + * timeout in seconds + * on_delete will be called when time expired with the key as first param + + usage: + ttl = TTL(function(key) { + console.log("10 seconds expired on " + key"); + }, 10); + ========================================================== +*/ +function TTL(on_delete, timeout) { + + var me = { + timeouts: {}, + on_delete: on_delete, + timeout: timeout*1000 + }; + + me.start = function(key) { + var t = me.timeouts[key]; + if (t) { + clearTimeout(t); + } + me.timeouts[key] = setTimeout( + (function(k) { + return function() { + me.on_delete(k); + }; + })(key), + me.timeout); + } + + me.remove = function(key) { + var t = me.timeouts[key]; + if (t) { + clearTimeout(t); + delete me.timeouts[key]; + } + } + + return me; +} + +module.exports = TTL; diff --git a/test/unit/cartodb/ttl.test.js b/test/unit/cartodb/ttl.test.js new file mode 100644 index 00000000..d094924a --- /dev/null +++ b/test/unit/cartodb/ttl.test.js @@ -0,0 +1,50 @@ + +var assert = require('assert') + , _ = require('underscore') + , TTL = require('../../../lib/cartodb/ttl') + , tests = module.exports = {}; + + +tests['all ok'] = function() { + assert.ok(true, "ok"); +} + +tests['should timeout'] = function() { + var called = false; + var ttl = TTL(function() { + called = true; + }, 0.1); + ttl.start('test'); + setTimeout(function() { + assert.ok(called === true, "called"); + }, 200); +} + +tests['should remove timeout'] = function() { + var called = false; + var ttl = TTL(function() { + called = true; + }, 0.1); + ttl.start('test'); + ttl.remove('test'); + setTimeout(function() { + assert.ok(called === false, "removed"); + }, 200); +} + +tests['should renew timeout time'] = function() { + var called = false; + var ttl = TTL(function() { + called = true; + }, 0.3); + ttl.start('test'); + setTimeout(function() { + ttl.start('test'); + }, 0.5); + setTimeout(function() { + assert.ok(called === false, "removed"); + }, 300); + setTimeout(function() { + assert.ok(called === true, "removed"); + }, 600); +}