From 87b04ce80aaf80c4bb7fbc265c9bb9f16a56932f Mon Sep 17 00:00:00 2001 From: javi Date: Thu, 20 Oct 2011 18:52:11 +0200 Subject: [PATCH] added last-modified header to tiler --- config/environments/test.js | 2 +- lib/cartodb/tile_cache.js | 21 ++++++++++++++++---- test/acceptance/cache.js | 38 +++++++++++++++++++++++++++++-------- test/prepare_db.sh | 8 ++++---- test/windshaft.test.sql | 6 ++++-- 5 files changed, 56 insertions(+), 19 deletions(-) diff --git a/config/environments/test.js b/config/environments/test.js index b680d0aa..86b9e524 100644 --- a/config/environments/test.js +++ b/config/environments/test.js @@ -5,6 +5,6 @@ module.exports.redis = {host: '127.0.0.1', idleTimeoutMillis: 1, reapIntervalMillis: 1}; module.exports.windshaft_port = 8080; -module.exports.lru_cache = false; +module.exports.lru_cache = true; module.exports.lru_cache_size = 10000; module.exports.enable_cors = true; diff --git a/lib/cartodb/tile_cache.js b/lib/cartodb/tile_cache.js index b4c3a3f5..c2c0072e 100644 --- a/lib/cartodb/tile_cache.js +++ b/lib/cartodb/tile_cache.js @@ -38,6 +38,7 @@ function GenericCache (cache_policy, cache_validator) { cache_validator: cache_validator, cache_hits: 0, cache_misses: 0, + cache_not_modified: 0, current_items: 0, cache_invalidated: 0, max_items: 0 @@ -61,17 +62,29 @@ function GenericCache (cache_policy, cache_validator) { if(tile) { // validate the cache me.cache_validator.getTimestamp(req.params.dbname, req.params.table, function(err, t) { - if(t != null && tile.timestamp < t) { + if(t !== null && tile.timestamp < t) { me.cache_misses++; me.cache_invalidated++; callback(null); } else { + // stats me.cache_hits++; var timestamp = new Date().getTime(); var delta = timestamp - req.windshaft_start; tile.cache_time = delta/1000.0; tile.hits++; res.header('X-Cache-hit', 'true'); + res.header('Last-Modified', new Date(tile.timestamp*1000).toGMTString()); + // check 304 + var modified_since = req.header('if-modified-since'); + if (modified_since) { + modified_since = Date.parse(modified_since); + if(modified_since && modified_since <= timestamp*1000) { + me.cache_not_modified++; + res.send(304); + return; + } + } res.send(tile.tile, tile.headers, 200); } }); @@ -87,7 +100,7 @@ function GenericCache (cache_policy, cache_validator) { me.cache.put(cache_key(req), { tile: tile, headers: headers, - timestamp: timestamp, + timestamp: timestamp/1000.0, render_time: delta/1000.0, hits: 0}); update_items(me.cache.size || 0); @@ -95,7 +108,6 @@ function GenericCache (cache_policy, cache_validator) { } me.afterStateChange = function(req, data, callback) { - console.log("invalidating", req.params.dbname,", ", req.params.table); me.cache_validator.setTimestamp(req.params.dbname, req.params.table, new Date().getTime()/1000.0, function(err, t) { callback(err, data); }); @@ -123,7 +135,6 @@ function GenericCache (cache_policy, cache_validator) { }); } }); - console.log(sort_by); sort_by = sort_by || 'hits'; tile_info.sort(function(a, b) { return b[sort_by] - a[sort_by]; @@ -131,6 +142,8 @@ function GenericCache (cache_policy, cache_validator) { return { cache_hits: me.cache_hits, cache_misses: me.cache_misses, + cache_invalidated: me.cache_invalidated, + cache_not_modified: me.cache_not_modified, current_items: me.current_items, max_items: me.max_items, memory: mem, diff --git a/test/acceptance/cache.js b/test/acceptance/cache.js index 008b5dcb..05c6b09d 100644 --- a/test/acceptance/cache.js +++ b/test/acceptance/cache.js @@ -16,7 +16,7 @@ var cached_server = new CartodbWindshaft(serverOptions); tests["first time a tile is request should not be cached"] = function() { assert.response(cached_server, { - url: '/tiles/test_table_2/6/31/24.png?geom_type=polygon', + url: '/tiles/test_table_3/6/31/24.png?geom_type=polygon', headers: {host: 'vizzuality.localhost.lan'}, method: 'GET' },{ @@ -113,23 +113,25 @@ tests["LRU tile should be removed"] = function() { tests["cache should be invalidated"] = function() { var url = '/tiles/test_table_2/6/29/27.png'; + var cached_server2 = new CartodbWindshaft(serverOptions); var cache = CacheValidator(global.environment.redis); - assert.response(cached_server, { + assert.response(cached_server2, { url: url, headers: {host: 'vizzuality.localhost.lan'}, method: 'GET' },{ status: 200 }, function(res) { - cache.setTimestamp('windshaft_test', 'test_table_2', (new Date().getTime()/1000.0)+100, function() { - assert.response(cached_server, { + cache.setTimestamp('cartodb_test_user_1_db', 'test_table_2', (new Date().getTime()/1000.0)+100, function() { + assert.response(cached_server2, { url: url, headers: {host: 'vizzuality.localhost.lan'}, method: 'GET' },{ status: 200 - }, function(res) { - assert.ok(res.header('X-Cache-hit') === undefined); + }, function(r) { + console.log('hiy', r.header('X-Cache-hit')); + assert.ok(r.header('X-Cache-hit') === undefined); }); }); }); @@ -138,7 +140,7 @@ tests["cache should be invalidated"] = function() { tests["Last-Modified header should be sent"] = function() { var cached_server2 = new CartodbWindshaft(serverOptions); - var url= '/tiles/test_table_2/6/31/24.png'; + var url= '/tiles/test_table/6/31/22.png'; assert.response(cached_server2, { url: url, headers: {host: 'vizzuality.localhost.lan'}, @@ -146,6 +148,26 @@ tests["Last-Modified header should be sent"] = function() { },{ status: 200 }, function(res) { - assert.ok(res.header('Last-Modified') !== undefined); + assert.response(cached_server2, { + url: url, + headers: {host: 'vizzuality.localhost.lan'}, + method: 'GET' + },{ + status: 200 + }, function(res) { + assert.ok(res.header('X-Cache-hit') !== undefined); + var last_modified = res.header('Last-Modified'); + assert.ok(last_modified !== undefined); + assert.response(cached_server2, { + url: url, + headers: { + host: 'vizzuality.localhost.lan', + 'if-modified-since': last_modified + }, + method: 'GET' + }, { + status: 304 + }); + }); }); } diff --git a/test/prepare_db.sh b/test/prepare_db.sh index c0d1a9e0..e094a934 100755 --- a/test/prepare_db.sh +++ b/test/prepare_db.sh @@ -4,12 +4,12 @@ echo "preparing redis..." echo "HSET rails:users:vizzuality id 1" | redis-cli -n 5 -echo "HSET rails:users:vizzuality database_name windshaft" | redis-cli -n 5 +echo "HSET rails:users:vizzuality database_name cartodb_test_user_1_db" | redis-cli -n 5 echo "preparing postgres..." -dropdb -Upostgres -hlocalhost whindshaft_test -createdb -Upostgres -hlocalhost -Ttemplate_postgis -Opostgres -EUTF8 whindshaft_test -psql -Upostgres -hlocalhost whindshaft_test < test.sql +dropdb -Upostgres -hlocalhost cartodb_test_user_1_db +createdb -Upostgres -hlocalhost -Ttemplate_postgis -Opostgres -EUTF8 cartodb_test_user_1_db +psql -Upostgres -hlocalhost cartodb_test_user_1_db < windshaft.test.sql echo "ok, you can run test now" diff --git a/test/windshaft.test.sql b/test/windshaft.test.sql index cdc88a76..180534e7 100644 --- a/test/windshaft.test.sql +++ b/test/windshaft.test.sql @@ -63,6 +63,7 @@ CREATE INDEX test_table_the_geom_idx ON test_table USING gist (the_geom); CREATE INDEX test_table_the_geom_webmercator_idx ON test_table USING gist (the_geom_webmercator); GRANT ALL ON TABLE test_table TO postgres; +GRANT ALL ON TABLE test_table TO tileuser; -- second table CREATE TABLE test_table_2 ( @@ -105,7 +106,7 @@ ALTER TABLE ONLY test_table_2 ADD CONSTRAINT test_table_2_pkey PRIMARY KEY (cart CREATE INDEX test_table_2_the_geom_idx ON test_table_2 USING gist (the_geom); CREATE INDEX test_table_2_the_geom_webmercator_idx ON test_table_2 USING gist (the_geom_webmercator); -GRANT ALL ON TABLE test_table_2 TO postgres; +GRANT ALL ON TABLE test_table_2 TO tileuser; -- third table CREATE TABLE test_table_3 ( @@ -148,4 +149,5 @@ ALTER TABLE ONLY test_table_3 ADD CONSTRAINT test_table_3_pkey PRIMARY KEY (cart CREATE INDEX test_table_3_the_geom_idx ON test_table_3 USING gist (the_geom); CREATE INDEX test_table_3_the_geom_webmercator_idx ON test_table_3 USING gist (the_geom_webmercator); -GRANT ALL ON TABLE test_table_3 TO postgres; \ No newline at end of file +GRANT ALL ON TABLE test_table_3 TO postgres; +GRANT ALL ON TABLE test_table_3 TO tileuser;