Adds Surrogate Keys to named maps
This commit is contained in:
32
lib/cartodb/cache/backend/varnish_http.js
vendored
Normal file
32
lib/cartodb/cache/backend/varnish_http.js
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
var request = require('request');
|
||||
|
||||
function VarnishHttpCacheBackend(host, port) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
module.exports = VarnishHttpCacheBackend;
|
||||
|
||||
/**
|
||||
* @param cacheObject should respond to `key() -> String` method
|
||||
* @param {Function} callback
|
||||
*/
|
||||
VarnishHttpCacheBackend.prototype.invalidate = function(cacheObject, callback) {
|
||||
request(
|
||||
{
|
||||
method: 'PURGE',
|
||||
url: 'http://' + this.host + ':' + this.port + '/key',
|
||||
headers: {
|
||||
'Invalidation-Match': '\b' + cacheObject.key() + '\b'
|
||||
}
|
||||
},
|
||||
function(err, response) {
|
||||
if (err || response.statusCode !== 204) {
|
||||
return callback(new Error('Unable to invalidate Varnish object'));
|
||||
}
|
||||
return callback(null);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
module.exports = VarnishHttpCacheBackend;
|
||||
18
lib/cartodb/cache/model/named_maps_entry.js
vendored
Normal file
18
lib/cartodb/cache/model/named_maps_entry.js
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
var crypto = require('crypto');
|
||||
|
||||
function NamedMaps(owner, name) {
|
||||
this.namespace = 'n';
|
||||
this.owner = owner;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
module.exports = NamedMaps;
|
||||
|
||||
|
||||
NamedMaps.prototype.key = function() {
|
||||
return this.namespace + ':' + shortHashKey(this.owner + ':' + this.name);
|
||||
};
|
||||
|
||||
function shortHashKey(target) {
|
||||
return crypto.createHash('sha256').update(target).digest('base64').substring(0,6);
|
||||
}
|
||||
26
lib/cartodb/cache/surrogate_keys_cache.js
vendored
Normal file
26
lib/cartodb/cache/surrogate_keys_cache.js
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* @param cacheBackend should respond to `invalidate(cacheObject, callback)` method
|
||||
* @constructor
|
||||
*/
|
||||
function SurrogateKeysCache(cacheBackend) {
|
||||
this.cacheBackend = cacheBackend;
|
||||
}
|
||||
|
||||
module.exports = SurrogateKeysCache;
|
||||
|
||||
|
||||
/**
|
||||
* @param response should respond to `header(key, value)` method
|
||||
* @param cacheObject should respond to `key() -> String` method
|
||||
*/
|
||||
SurrogateKeysCache.prototype.tag = function(response, cacheObject) {
|
||||
response.header('Surrogate-Key', cacheObject.key());
|
||||
};
|
||||
|
||||
/**
|
||||
* @param cacheObject should respond to `key() -> String` method
|
||||
* @param {Function} callback
|
||||
*/
|
||||
SurrogateKeysCache.prototype.invalidate = function(cacheObject, callback) {
|
||||
this.cacheBackend.invalidate(cacheObject, callback);
|
||||
};
|
||||
@@ -25,15 +25,6 @@ var CartodbWindshaft = function(serverOptions) {
|
||||
|
||||
var cartoData = require('cartodb-redis')({pool: redisPool});
|
||||
|
||||
if(serverOptions.cache_enabled) {
|
||||
console.log("cache invalidation enabled, varnish on ", serverOptions.varnish_host, ' ', serverOptions.varnish_port);
|
||||
Cache.init(serverOptions.varnish_host, serverOptions.varnish_port, serverOptions.varnish_secret);
|
||||
serverOptions.afterStateChange = function(req, data, callback) {
|
||||
Cache.invalidate_db(req.params.dbname, req.params.table);
|
||||
callback(null, data);
|
||||
}
|
||||
}
|
||||
|
||||
serverOptions.beforeStateChange = function(req, callback) {
|
||||
var err = null;
|
||||
if ( ! req.params.hasOwnProperty('_authorizedByApiKey') ) {
|
||||
@@ -54,6 +45,35 @@ var CartodbWindshaft = function(serverOptions) {
|
||||
var templateMaps = new TemplateMaps(redisPool, templateMapsOpts);
|
||||
serverOptions.templateMaps = templateMaps;
|
||||
|
||||
var SurrogateKeysCache = require('./cache/surrogate_keys_cache'),
|
||||
NamedMapsCacheEntry = require('./cache/model/named_maps_entry'),
|
||||
VarnishHttpCacheBackend = require('./cache/backend/varnish_http'),
|
||||
varnishHttpCacheBackend = new VarnishHttpCacheBackend(serverOptions.varnish_host, serverOptions.varnish_http_port),
|
||||
surrogateKeysCache = new SurrogateKeysCache(varnishHttpCacheBackend);
|
||||
|
||||
if (serverOptions.cache_enabled) {
|
||||
|
||||
console.log("cache invalidation enabled, varnish on ", serverOptions.varnish_host, ' ', serverOptions.varnish_port);
|
||||
|
||||
Cache.init(serverOptions.varnish_host, serverOptions.varnish_port, serverOptions.varnish_secret);
|
||||
serverOptions.afterStateChange = function(req, data, callback) {
|
||||
Cache.invalidate_db(req.params.dbname, req.params.table);
|
||||
callback(null, data);
|
||||
};
|
||||
|
||||
function invalidateNamedMap(owner, templateName) {
|
||||
surrogateKeysCache.invalidate(new NamedMapsCacheEntry(owner, templateName), function(err) {
|
||||
if (err) {
|
||||
console.warn('Cache: surrogate key invalidation failed');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
['update', 'delete'].forEach(function(eventType) {
|
||||
templateMaps.on(eventType, invalidateNamedMap);
|
||||
});
|
||||
}
|
||||
|
||||
// boot
|
||||
var ws = new Windshaft.Server(serverOptions);
|
||||
|
||||
@@ -138,7 +158,7 @@ var CartodbWindshaft = function(serverOptions) {
|
||||
|
||||
var TemplateMapsController = require('./controllers/template_maps'),
|
||||
templateMapsController = new TemplateMapsController(
|
||||
ws, serverOptions, templateMaps, cartoData, template_baseurl
|
||||
ws, serverOptions, templateMaps, cartoData, template_baseurl, surrogateKeysCache, NamedMapsCacheEntry
|
||||
);
|
||||
templateMapsController.register(ws);
|
||||
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
var Step = require('step');
|
||||
var _ = require('underscore');
|
||||
|
||||
function TemplateMapsController(app, serverOptions, templateMaps, metadataBackend, templateBaseUrl) {
|
||||
function TemplateMapsController(app, serverOptions, templateMaps, metadataBackend, templateBaseUrl, surrogateKeysCache,
|
||||
NamedMapsCacheEntry) {
|
||||
this.app = app;
|
||||
this.serverOptions = serverOptions;
|
||||
this.templateMaps = templateMaps;
|
||||
this.metadataBackend = metadataBackend;
|
||||
this.templateBaseUrl = templateBaseUrl;
|
||||
this.surrogateKeysCache = surrogateKeysCache;
|
||||
this.NamedMapsCacheEntry = NamedMapsCacheEntry;
|
||||
}
|
||||
|
||||
module.exports = TemplateMapsController;
|
||||
@@ -430,6 +433,9 @@ TemplateMapsController.prototype.instantiateTemplate = function(req, res, templa
|
||||
}
|
||||
var tplhash = self.templateMaps.fingerPrint(template).substring(0,8);
|
||||
layergroup.layergroupid = cdbuser + '@' + tplhash + '@' + layergroup.layergroupid;
|
||||
|
||||
self.surrogateKeysCache.tag(res, new self.NamedMapsCacheEntry(cdbuser, template.name));
|
||||
|
||||
return layergroup;
|
||||
},
|
||||
callback
|
||||
|
||||
Reference in New Issue
Block a user