From 5e2a20fbe03fe074301971c65c3df013bb8120bc Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 13 Jul 2015 16:15:34 +0200 Subject: [PATCH] Tags layergroup instantiation with surrogate keys per affected tables --- .../cache/model/database_tables_entry.js | 20 ++++++++++++++ lib/cartodb/cache/surrogate_keys_cache.js | 14 +++++++++- lib/cartodb/controllers/map.js | 27 ++++++++++--------- 3 files changed, 48 insertions(+), 13 deletions(-) create mode 100644 lib/cartodb/cache/model/database_tables_entry.js diff --git a/lib/cartodb/cache/model/database_tables_entry.js b/lib/cartodb/cache/model/database_tables_entry.js new file mode 100644 index 00000000..9bdb6e3d --- /dev/null +++ b/lib/cartodb/cache/model/database_tables_entry.js @@ -0,0 +1,20 @@ +var crypto = require('crypto'); + +function DatabaseTables(dbName, tableNames) { + this.namespace = 't'; + this.dbName = dbName; + this.tableNames = tableNames; +} + +module.exports = DatabaseTables; + + +DatabaseTables.prototype.key = function() { + return this.tableNames.map(function(tableName) { + return this.namespace + ':' + shortHashKey(this.dbName + ':' + tableName); + }.bind(this)); +}; + +function shortHashKey(target) { + return crypto.createHash('sha256').update(target).digest('base64').substring(0,6); +} diff --git a/lib/cartodb/cache/surrogate_keys_cache.js b/lib/cartodb/cache/surrogate_keys_cache.js index 77147917..237ac906 100644 --- a/lib/cartodb/cache/surrogate_keys_cache.js +++ b/lib/cartodb/cache/surrogate_keys_cache.js @@ -16,9 +16,21 @@ module.exports = SurrogateKeysCache; * @param cacheObject should respond to `key() -> String` method */ SurrogateKeysCache.prototype.tag = function(response, cacheObject) { - response.header('Surrogate-Key', cacheObject.key()); + var newKey = cacheObject.key(); + response.header('Surrogate-Key', appendSurrogateKey( + response.header('Surrogate-Key'), + Array.isArray(newKey) ? cacheObject.key().join(' ') : newKey + )); + }; +function appendSurrogateKey(currentKey, newKey) { + if (!!currentKey) { + newKey = currentKey + ' ' + newKey; + } + return newKey; +} + /** * @param cacheObject should respond to `key() -> String` method * @param {Function} callback diff --git a/lib/cartodb/controllers/map.js b/lib/cartodb/controllers/map.js index d5b43425..9e6fcf44 100644 --- a/lib/cartodb/controllers/map.js +++ b/lib/cartodb/controllers/map.js @@ -9,6 +9,7 @@ var MapConfig = windshaft.model.MapConfig; var Datasource = windshaft.model.Datasource; var NamedMapsCacheEntry = require('../cache/model/named_maps_entry'); +var TablesCacheEntry = require('../cache/model/database_tables_entry'); var MapConfigNamedLayersAdapter = require('../models/mapconfig_named_layers_adapter'); var NamedMapMapConfigProvider = require('../models/mapconfig/named_map_provider'); @@ -147,13 +148,14 @@ MapController.prototype.create = function(req, res, prepareConfigFn) { }, function afterLayergroupCreate(err, layergroup) { assert.ifError(err); - self.afterLayergroupCreate(req, mapConfig, layergroup, this); + self.afterLayergroupCreate(req, res, mapConfig, layergroup, this); }, function finish(err, layergroup) { if (err) { var statusCode = self.app.findStatusCode(err); self.app.sendError(res, { errors: [ err.message ] }, statusCode, 'ANONYMOUS LAYERGROUP', err); } else { + res.header('X-Layergroup-Id', layergroup.layergroupid); self.app.sendResponse(res, [layergroup, 200]); } } @@ -169,6 +171,9 @@ MapController.prototype.instantiateTemplate = function(req, res, prepareParamsFn var mapConfig; step( + function setupParams(){ + self.app.req2params(req, this); + }, function getTemplateParams() { prepareParamsFn(this); }, @@ -197,7 +202,7 @@ MapController.prototype.instantiateTemplate = function(req, res, prepareParamsFn }, function afterLayergroupCreate(err, layergroup) { assert.ifError(err); - self.afterLayergroupCreate(req, mapConfig, layergroup, this); + self.afterLayergroupCreate(req, res, mapConfig, layergroup, this); }, function finishTemplateInstantiation(err, layergroup) { if (err) { @@ -217,7 +222,7 @@ MapController.prototype.instantiateTemplate = function(req, res, prepareParamsFn }; -MapController.prototype.afterLayergroupCreate = function(req, mapconfig, layergroup, callback) { +MapController.prototype.afterLayergroupCreate = function(req, res, mapconfig, layergroup, callback) { var self = this; var username = req.context.user; @@ -276,16 +281,14 @@ MapController.prototype.afterLayergroupCreate = function(req, mapconfig, layergr layergroup.layergroupid = layergroup.layergroupid + ':' + result.lastUpdatedTime; layergroup.last_updated = new Date(result.lastUpdatedTime).toISOString(); - var res = req.res; - if (res) { - if (req.method === 'GET') { - var ttl = global.environment.varnish.layergroupTtl || 86400; - res.header('Cache-Control', 'public,max-age='+ttl+',must-revalidate'); - res.header('Last-Modified', (new Date()).toUTCString()); - res.header('X-Cache-Channel', cacheChannel); + if (req.method === 'GET') { + var ttl = global.environment.varnish.layergroupTtl || 86400; + res.header('Cache-Control', 'public,max-age='+ttl+',must-revalidate'); + res.header('Last-Modified', (new Date()).toUTCString()); + res.header('X-Cache-Channel', cacheChannel); + if (result.affectedTables && result.affectedTables.length > 0) { + self.surrogateKeysCache.tag(res, new TablesCacheEntry(dbName, result.affectedTables)); } - - res.header('X-Layergroup-Id', layergroup.layergroupid); } return null;