diff --git a/lib/cartodb/cache/named_map_provider_cache.js b/lib/cartodb/cache/named_map_provider_cache.js index 7bb8e25c..df536af5 100644 --- a/lib/cartodb/cache/named_map_provider_cache.js +++ b/lib/cartodb/cache/named_map_provider_cache.js @@ -7,12 +7,13 @@ var queue = require('queue-async'); var LruCache = require("lru-cache"); -function NamedMapProviderCache(templateMaps, pgConnection, userLimitsApi, turboCartocssAdapter) { +function NamedMapProviderCache(templateMaps, pgConnection, userLimitsApi, overviewsAdapter, turboCartocssAdapter) { this.templateMaps = templateMaps; this.pgConnection = pgConnection; this.userLimitsApi = userLimitsApi; this.namedLayersAdapter = new MapConfigNamedLayersAdapter(templateMaps); + this.overviewsAdapter = overviewsAdapter; this.turboCartocssAdapter = turboCartocssAdapter; this.providerCache = new LruCache({ max: 2000 }); @@ -31,6 +32,7 @@ NamedMapProviderCache.prototype.get = function(user, templateId, config, authTok this.pgConnection, this.userLimitsApi, this.namedLayersAdapter, + this.overviewsAdapter, this.turboCartocssAdapter, user, templateId, diff --git a/lib/cartodb/controllers/map.js b/lib/cartodb/controllers/map.js index 36b7b975..07e0eea5 100644 --- a/lib/cartodb/controllers/map.js +++ b/lib/cartodb/controllers/map.js @@ -18,7 +18,6 @@ var NamedMapsCacheEntry = require('../cache/model/named_maps_entry'); var MapConfigNamedLayersAdapter = require('../models/mapconfig_named_layers_adapter'); var NamedMapMapConfigProvider = require('../models/mapconfig/named_map_provider'); var CreateLayergroupMapConfigProvider = require('../models/mapconfig/create_layergroup_provider'); -var MapConfigOverviewsAdapter = require('../models/mapconfig_overviews_adapter'); /** * @param {AuthApi} authApi @@ -33,8 +32,8 @@ var MapConfigOverviewsAdapter = require('../models/mapconfig_overviews_adapter') * @constructor */ function MapController(authApi, pgConnection, templateMaps, mapBackend, metadataBackend, - overviewsMetadataApi, - surrogateKeysCache, userLimitsApi, layergroupAffectedTables, turboCartoCssAdapter) { + surrogateKeysCache, userLimitsApi, layergroupAffectedTables, + overviewsAdapter, turboCartoCssAdapter) { BaseController.call(this, authApi, pgConnection); @@ -42,14 +41,13 @@ function MapController(authApi, pgConnection, templateMaps, mapBackend, metadata this.templateMaps = templateMaps; this.mapBackend = mapBackend; this.metadataBackend = metadataBackend; - this.overviewsMetadataApi = overviewsMetadataApi; this.surrogateKeysCache = surrogateKeysCache; this.userLimitsApi = userLimitsApi; this.layergroupAffectedTables = layergroupAffectedTables; this.turboCartoCssAdapter = turboCartoCssAdapter; this.namedLayersAdapter = new MapConfigNamedLayersAdapter(templateMaps); - this.overviewsAdapter = new MapConfigOverviewsAdapter(this.overviewsMetadataApi); + this.overviewsAdapter = overviewsAdapter; } util.inherits(MapController, BaseController); @@ -231,6 +229,7 @@ MapController.prototype.instantiateTemplate = function(req, res, prepareParamsFn self.pgConnection, self.userLimitsApi, self.namedLayersAdapter, + self.overviewsAdapter, self.turboCartoCssAdapter, cdbuser, req.params.template_id, @@ -240,22 +239,6 @@ MapController.prototype.instantiateTemplate = function(req, res, prepareParamsFn ); mapConfigProvider.getMapConfig(this); }, - function addOverviewsInformation(err, requestMapConfig, rendererParams/*, context*/) { - assert.ifError(err); - var next = this; - self.overviewsAdapter.getLayers(req.context.user, requestMapConfig.layers, - function(err, layers) { - if (err) { - return next(err); - } - - if (layers) { - requestMapConfig.layers = layers; - } - return next(null, requestMapConfig, rendererParams); - } - ); - }, function createLayergroup(err, mapConfig_, rendererParams) { assert.ifError(err); mapConfig = mapConfig_; diff --git a/lib/cartodb/models/mapconfig/named_map_provider.js b/lib/cartodb/models/mapconfig/named_map_provider.js index ebf1f55c..deeb39a2 100644 --- a/lib/cartodb/models/mapconfig/named_map_provider.js +++ b/lib/cartodb/models/mapconfig/named_map_provider.js @@ -11,13 +11,15 @@ var QueryTables = require('cartodb-query-tables'); * @constructor * @type {NamedMapMapConfigProvider} */ -function NamedMapMapConfigProvider(templateMaps, pgConnection, userLimitsApi, namedLayersAdapter, - turboCartoCssAdapter, owner, templateId, config, authToken, params) { +function NamedMapMapConfigProvider(templateMaps, pgConnection, userLimitsApi, + namedLayersAdapter, overviewsAdapter, turboCartoCssAdapter, + owner, templateId, config, authToken, params) { this.templateMaps = templateMaps; this.pgConnection = pgConnection; this.userLimitsApi = userLimitsApi; this.namedLayersAdapter = namedLayersAdapter; this.turboCartoCssAdapter = turboCartoCssAdapter; + this.overviewsAdapter = overviewsAdapter; this.owner = owner; this.templateName = templateName(templateId); @@ -92,6 +94,22 @@ NamedMapMapConfigProvider.prototype.getMapConfig = function(callback) { } ); }, + function addOverviewsInformation(err, _mapConfig, datasource) { + assert.ifError(err); + var next = this; + + self.overviewsAdapter.getLayers(self.owner, _mapConfig.layers, function(err, layers) { + if (err) { + return next(err); + } + + if (layers) { + _mapConfig.layers = layers; + } + + return next(null, _mapConfig, datasource); + }); + }, function parseTurboCartoCss(err, _mapConfig, datasource) { assert.ifError(err); var next = this; diff --git a/lib/cartodb/server.js b/lib/cartodb/server.js index 28eea3c5..5f628501 100644 --- a/lib/cartodb/server.js +++ b/lib/cartodb/server.js @@ -30,6 +30,8 @@ var PgConnection = require('./backends/pg_connection'); var timeoutErrorTilePath = __dirname + '/../../assets/render-timeout-fallback.png'; var timeoutErrorTile = require('fs').readFileSync(timeoutErrorTilePath, {encoding: null}); +var MapConfigOverviewsAdapter = require('./models/mapconfig_overviews_adapter'); + var TurboCartocssParser = require('./utils/style/turbo-cartocss-parser'); var TurboCartocssAdapter = require('./utils/style/turbo-cartocss-adapter'); @@ -142,6 +144,8 @@ module.exports = function(serverOptions) { var layergroupAffectedTablesCache = new LayergroupAffectedTablesCache(); app.layergroupAffectedTablesCache = layergroupAffectedTablesCache; + var overviewsAdapter = new MapConfigOverviewsAdapter(overviewsMetadataApi); + var turboCartoCssParser = new TurboCartocssParser(pgQueryRunner); var turboCartocssAdapter = new TurboCartocssAdapter(turboCartoCssParser); @@ -149,6 +153,7 @@ module.exports = function(serverOptions) { templateMaps, pgConnection, userLimitsApi, + overviewsAdapter, turboCartocssAdapter ); @@ -184,10 +189,10 @@ module.exports = function(serverOptions) { templateMaps, mapBackend, metadataBackend, - overviewsMetadataApi, surrogateKeysCache, userLimitsApi, layergroupAffectedTablesCache, + overviewsAdapter, turboCartocssAdapter ).register(app); diff --git a/test/acceptance/overviews_metadata_named_maps.js b/test/acceptance/overviews_metadata_named_maps.js new file mode 100644 index 00000000..38326986 --- /dev/null +++ b/test/acceptance/overviews_metadata_named_maps.js @@ -0,0 +1,174 @@ +var test_helper = require('../support/test_helper'); + +var assert = require('../support/assert'); +var CartodbWindshaft = require(__dirname + '/../../lib/cartodb/server'); +var serverOptions = require(__dirname + '/../../lib/cartodb/server_options'); +var server = new CartodbWindshaft(serverOptions); + +var LayergroupToken = require('../../lib/cartodb/models/layergroup_token'); + +var RedisPool = require('redis-mpool'); + +var step = require('step'); + +var windshaft = require('windshaft'); + + +describe('overviews metadata for named maps', function() { + // configure redis pool instance to use in tests + var redisPool = new RedisPool(global.environment.redis); + + var overviews_layer = { + type: 'cartodb', + options: { + sql: 'SELECT * FROM test_table_overviews', + cartocss: '#layer { marker-fill: black; }', + cartocss_version: '2.3.0' + } + }; + + var non_overviews_layer = { + type: 'cartodb', + options: { + sql: 'SELECT * FROM test_table', + cartocss: '#layer { marker-fill: black; }', + cartocss_version: '2.3.0' + } + }; + + var keysToDelete; + + beforeEach(function() { + keysToDelete = {}; + }); + + afterEach(function(done) { + test_helper.deleteRedisKeys(keysToDelete, done); + }); + + var templateId = 'overviews-template-1'; + + var template = { + version: '0.0.1', + name: templateId, + auth: { method: 'open' }, + layergroup: { + version: '1.0.0', + layers: [overviews_layer, non_overviews_layer] + } + }; + + it("should add overviews data to layers", function(done) { + step( + function postTemplate() + { + var next = this; + + assert.response(server, { + url: '/api/v1/map/named?api_key=1234', + method: 'POST', + headers: {host: 'localhost', 'Content-Type': 'application/json' }, + data: JSON.stringify(template) + }, {}, function(res, err) { + next(err, res); + }); + }, + function checkTemplate(err, res) { + assert.ifError(err); + + var next = this; + assert.equal(res.statusCode, 200); + assert.deepEqual(JSON.parse(res.body), { + template_id: templateId + }); + next(null); + }, + function instantiateTemplate(err) { + assert.ifError(err); + + var next = this; + assert.response(server, { + url: '/api/v1/map/named/' + templateId, + method: 'POST', + headers: { + host: 'localhost', + 'Content-Type': 'application/json' + } + }, {}, + function(res, err) { + return next(err, res); + }); + + }, + function checkInstanciation(err, res) { + assert.ifError(err); + + var next = this; + + assert.equal(res.statusCode, 200); + + var parsedBody = JSON.parse(res.body); + + keysToDelete['map_cfg|' + LayergroupToken.parse(parsedBody.layergroupid).token] = 0; + keysToDelete['user:localhost:mapviews:global'] = 5; + + assert.ok(parsedBody.layergroupid); + assert.ok(parsedBody.last_updated); + + next(null, parsedBody.layergroupid); + }, + + function checkMapconfig(err, layergroupId) + { + assert.ifError(err); + + var next = this; + + var mapStore = new windshaft.storage.MapStore({ + pool: redisPool, + expire_time: 500000 + }); + mapStore.load(LayergroupToken.parse(layergroupId).token, function(err, mapConfig) { + assert.ifError(err); + assert.deepEqual(non_overviews_layer, mapConfig._cfg.layers[1]); + assert.equal(mapConfig._cfg.layers[0].type, 'cartodb'); + assert.ok(mapConfig._cfg.layers[0].options.query_rewrite_data); + var expected_data = { + overviews: { + test_table_overviews: { + 1: { table: '_vovw_1_test_table_overviews' }, + 2: { table: '_vovw_2_test_table_overviews' } + } + } + }; + assert.deepEqual(mapConfig._cfg.layers[0].options.query_rewrite_data, expected_data); + }); + + next(err); + }, + function deleteTemplate(err) { + assert.ifError(err); + + var next = this; + + assert.response(server, { + url: '/api/v1/map/named/' + templateId + '?api_key=1234', + method: 'DELETE', + headers: { host: 'localhost' } + }, {}, function (res, err) { + next(err, res); + }); + }, + function checkDeleteTemplate(err, res) { + assert.ifError(err); + assert.equal(res.statusCode, 204); + assert.ok(!res.body); + + return null; + }, + function finish(err) { + done(err); + } + ); + }); +});