Adds analysis MapConfig adapter to named maps

This commit is contained in:
Raul Ochoa 2016-04-07 16:18:48 +02:00
parent efacafaa0d
commit 077c4ab907
6 changed files with 251 additions and 13 deletions

View File

@ -2,17 +2,21 @@ var _ = require('underscore');
var dot = require('dot');
var NamedMapMapConfigProvider = require('../models/mapconfig/named_map_provider');
var MapConfigNamedLayersAdapter = require('../models/mapconfig_named_layers_adapter');
var AnalysisMapConfigAdapter = require('../models/analysis_mapconfig_adapter');
var templateName = require('../backends/template_maps').templateName;
var queue = require('queue-async');
var LruCache = require("lru-cache");
function NamedMapProviderCache(templateMaps, pgConnection, userLimitsApi, overviewsAdapter, turboCartocssAdapter) {
function NamedMapProviderCache(templateMaps, pgConnection, metadataBackend, userLimitsApi, overviewsAdapter,
turboCartocssAdapter) {
this.templateMaps = templateMaps;
this.pgConnection = pgConnection;
this.metadataBackend = metadataBackend;
this.userLimitsApi = userLimitsApi;
this.namedLayersAdapter = new MapConfigNamedLayersAdapter(templateMaps);
this.analysisMapConfigAdapter = new AnalysisMapConfigAdapter();
this.overviewsAdapter = overviewsAdapter;
this.turboCartocssAdapter = turboCartocssAdapter;
@ -30,10 +34,12 @@ NamedMapProviderCache.prototype.get = function(user, templateId, config, authTok
namedMapProviders[providerKey] = new NamedMapMapConfigProvider(
this.templateMaps,
this.pgConnection,
this.metadataBackend,
this.userLimitsApi,
this.namedLayersAdapter,
this.overviewsAdapter,
this.turboCartocssAdapter,
this.analysisMapConfigAdapter,
user,
templateId,
config,

View File

@ -257,10 +257,12 @@ MapController.prototype.instantiateTemplate = function(req, res, prepareParamsFn
mapConfigProvider = new NamedMapMapConfigProvider(
self.templateMaps,
self.pgConnection,
self.metadataBackend,
self.userLimitsApi,
self.namedLayersAdapter,
self.overviewsAdapter,
self.turboCartoCssAdapter,
self.analysisMapConfigAdapter,
cdbuser,
req.params.template_id,
templateParams,

View File

@ -11,14 +11,16 @@ var QueryTables = require('cartodb-query-tables');
* @constructor
* @type {NamedMapMapConfigProvider}
*/
function NamedMapMapConfigProvider(templateMaps, pgConnection, userLimitsApi,
namedLayersAdapter, overviewsAdapter, turboCartoCssAdapter,
function NamedMapMapConfigProvider(templateMaps, pgConnection, metadataBackend, userLimitsApi,
namedLayersAdapter, overviewsAdapter, turboCartoCssAdapter, analysisMapConfigAdapter,
owner, templateId, config, authToken, params) {
this.templateMaps = templateMaps;
this.pgConnection = pgConnection;
this.metadataBackend = metadataBackend;
this.userLimitsApi = userLimitsApi;
this.namedLayersAdapter = namedLayersAdapter;
this.turboCartoCssAdapter = turboCartoCssAdapter;
this.analysisMapConfigAdapter = analysisMapConfigAdapter;
this.overviewsAdapter = overviewsAdapter;
this.owner = owner;
@ -53,15 +55,29 @@ NamedMapMapConfigProvider.prototype.getMapConfig = function(callback) {
var mapConfig = null;
var datasource = null;
var rendererParams;
var apiKey;
step(
function getTemplate() {
self.getTemplate(this);
},
function prepareParams(err, tpl) {
function prepareDbParams(err, tpl) {
assert.ifError(err);
self.template = tpl;
rendererParams = _.extend({}, self.params, {
user: self.owner
});
self.setDBParams(self.owner, rendererParams, this);
},
function getUserApiKey(err) {
assert.ifError(err);
self.metadataBackend.getUserMapKey(self.owner, this);
},
function prepareParams(err, _apiKey) {
assert.ifError(err);
self.template = tpl;
apiKey = _apiKey;
var templateParams = {};
if (self.config) {
@ -78,6 +94,34 @@ NamedMapMapConfigProvider.prototype.getMapConfig = function(callback) {
assert.ifError(err);
return self.templateMaps.instance(self.template, templateParams);
},
function prepareAnalysisLayers(err, requestMapConfig) {
assert.ifError(err);
var analysisConfiguration = {
db: {
host: rendererParams.dbhost,
port: rendererParams.dbport,
dbname: rendererParams.dbname,
user: rendererParams.dbuser,
pass: rendererParams.dbpassword
},
batch: {
// TODO load this from configuration
endpoint: 'http://127.0.0.1:8080/api/v1/sql/job',
username: self.owner,
apiKey: apiKey
}
};
var filters = {};
if (self.params.filters) {
try {
filters = JSON.parse(self.params.filters);
} catch (e) {
// ignore
}
}
self.analysisMapConfigAdapter.getLayers(analysisConfiguration, requestMapConfig, filters, this);
},
function prepareLayergroup(err, _mapConfig) {
assert.ifError(err);
var next = this;
@ -126,17 +170,10 @@ NamedMapMapConfigProvider.prototype.getMapConfig = function(callback) {
return next(null, _mapConfig, datasource);
});
},
function beforeLayergroupCreate(err, _mapConfig, _datasource) {
function prepareContextLimits(err, _mapConfig, _datasource) {
assert.ifError(err);
mapConfig = _mapConfig;
datasource = _datasource;
rendererParams = _.extend({}, self.params, {
user: self.owner
});
self.setDBParams(self.owner, rendererParams, this);
},
function prepareContextLimits(err) {
assert.ifError(err);
self.userLimitsApi.getRenderLimits(self.owner, this);
},
function cacheAndReturnMapConfig(err, renderLimits) {

View File

@ -152,6 +152,7 @@ module.exports = function(serverOptions) {
var namedMapProviderCache = new NamedMapProviderCache(
templateMaps,
pgConnection,
metadataBackend,
userLimitsApi,
overviewsAdapter,
turboCartocssAdapter

View File

@ -0,0 +1,192 @@
var assert = require('../../support/assert');
var step = require('step');
//var mapnik = require('windshaft').mapnik;
var helper = require('../../support/test_helper');
var CartodbWindshaft = require('../../../lib/cartodb/server');
var serverOptions = require('../../../lib/cartodb/server_options');
var server = new CartodbWindshaft(serverOptions);
var LayergroupToken = require('../../../lib/cartodb/models/layergroup_token');
describe('named-maps analysis', function() {
var IMAGE_TOLERANCE_PER_MIL = 20;
var username = 'localhost';
var widgetsTemplateName = 'widgets-template';
var layergroupid;
var layergroup;
var keysToDelete;
beforeEach(function(done) {
keysToDelete = {};
var widgetsTemplate = {
version: '0.0.1',
name: widgetsTemplateName,
layergroup: {
version: '1.5.0',
layers: [
{
"type": "cartodb",
"options": {
"source": {
"id": "HEAD"
},
"cartocss": '#buffer { polygon-fill: red; }',
"cartocss_version": "2.3.0"
}
}
],
analyses: [
{
"id": "HEAD",
"type": "buffer",
"params": {
"source": {
"id": "2570e105-7b37-40d2-bdf4-1af889598745",
"type": "source",
"params": {
"query": "select * from populated_places_simple_reduced"
}
},
"radio": 50000
}
}
]
}
};
var template_params = {};
step(
function createTemplate()
{
var next = this;
assert.response(
server,
{
url: '/api/v1/map/named?api_key=1234',
method: 'POST',
headers: {
host: username,
'Content-Type': 'application/json'
},
data: JSON.stringify(widgetsTemplate)
},
{
status: 200
},
function(res, err) {
next(err, res);
}
);
},
function instantiateTemplate(err, res) {
assert.ifError(err);
assert.deepEqual(JSON.parse(res.body), { template_id: widgetsTemplateName });
var next = this;
assert.response(
server,
{
url: '/api/v1/map/named/' + widgetsTemplateName,
method: 'POST',
headers: {
host: username,
'Content-Type': 'application/json'
},
data: JSON.stringify(template_params)
},
{
status: 200
},
function(res) {
next(null, res);
}
);
},
function finish(err, res) {
assert.ifError(err);
layergroup = JSON.parse(res.body);
assert.ok(layergroup.hasOwnProperty('layergroupid'), "Missing 'layergroupid' from: " + res.body);
layergroupid = layergroup.layergroupid;
keysToDelete['map_cfg|' + LayergroupToken.parse(layergroup.layergroupid).token] = 0;
keysToDelete['user:localhost:mapviews:global'] = 5;
return done();
}
);
});
afterEach(function(done) {
step(
function deleteTemplate(err) {
assert.ifError(err);
var next = this;
assert.response(
server,
{
url: '/api/v1/map/named/' + widgetsTemplateName + '?api_key=1234',
method: 'DELETE',
headers: {
host: username
}
},
{
status: 204
},
function(res, err) {
next(err, res);
}
);
},
function deleteRedisKeys(err) {
assert.ifError(err);
helper.deleteRedisKeys(keysToDelete, done);
}
);
});
it('should be able to retrieve widgets from all URLs', function(done) {
assert.response(
server,
{
url: '/api/v1/map/' + layergroupid + '/6/31/24.png',
method: 'GET',
encoding: 'binary',
headers: {
host: username
}
},
{
status: 200,
headers: {
'Content-Type': 'image/png'
}
},
function(res, err) {
if (err) {
return done(err);
}
// var image = mapnik.Image.fromBytes(new Buffer(res.body, 'binary'));
// assert.ok(image);
var fixturePath = './test/fixtures/analysis/named-map-buffer.png';
assert.imageBufferIsSimilarToFile(res.body, fixturePath, IMAGE_TOLERANCE_PER_MIL, function(err) {
assert.ok(!err, err);
done();
});
}
);
});
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB