Keep a counter of layergroup created per user.
The counter is in redis db 5, in a field "mapviews" of an hash "tiler:users:USERNAME". It's incremented whenever the layergroup token for a configuration is requested.
This commit is contained in:
@@ -19,7 +19,8 @@ module.exports = function() {
|
||||
user_metadata_db: 5,
|
||||
table_metadata_db: 0,
|
||||
user_key: "rails:users:<%= username %>",
|
||||
table_key: "rails:<%= database_name %>:<%= table_name %>"
|
||||
table_key: "rails:<%= database_name %>:<%= table_name %>",
|
||||
user_stats_key: "tiler:users:<%= username %>"
|
||||
};
|
||||
|
||||
|
||||
@@ -43,6 +44,24 @@ module.exports = function() {
|
||||
});
|
||||
};
|
||||
|
||||
me.userFromHostname = function(hostname) {
|
||||
return hostname.split('.')[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment mapview count for a user
|
||||
*
|
||||
* @param username
|
||||
* @param callback will be called with the new value
|
||||
*/
|
||||
me.incMapviewCount = function(username, callback) {
|
||||
var redisKey = _.template(this.user_stats_key, {username: username});
|
||||
|
||||
this.redisCmd(me.user_metadata_db, 'HINCRBY', [redisKey, 'mapviews', 1], function(err, val) {
|
||||
if ( err ) callback(err, null);
|
||||
else callback(err, val);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
@@ -207,6 +226,11 @@ module.exports = function() {
|
||||
this.redisCmd(db,'SISMEMBER',[setKey, member], callback);
|
||||
};
|
||||
|
||||
// Redis INCREMENT
|
||||
me.increment = function(db, key, callback) {
|
||||
this.redisCmd(db,'INCR', key, callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* Use Redis
|
||||
*
|
||||
|
||||
@@ -220,6 +220,29 @@ module.exports = function(){
|
||||
me.afterLayergroupCreate = function(req, mapconfig, response, callback) {
|
||||
var token = response.layergroupid;
|
||||
|
||||
var username = cartoData.userFromHostname(req.headers.host);
|
||||
|
||||
var tasksleft = 2; // redis key and affectedTables
|
||||
var errors = [];
|
||||
|
||||
var done = function(err) {
|
||||
if ( err ) {
|
||||
errors.push('' + err);
|
||||
}
|
||||
if ( ! --tasksleft ) {
|
||||
err = errors.length ? new Error(errors.join('\n')) : null;
|
||||
callback(err);
|
||||
}
|
||||
}
|
||||
|
||||
// Don't wait for the mapview count increment to
|
||||
// take place before proceeding. Error will be logged
|
||||
// asyncronously
|
||||
cartoData.incMapviewCount(username, function(err) {
|
||||
if ( err ) console.log("ERROR: failed to increment mapview count for user '" + username + "': " + err);
|
||||
done();
|
||||
});
|
||||
|
||||
var sql = [];
|
||||
_.each(mapconfig.layers, function(lyr) {
|
||||
sql.push(lyr.options.sql);
|
||||
@@ -234,14 +257,14 @@ module.exports = function(){
|
||||
|
||||
me.affectedTables(usr, key, sql, function(err, tableNames) {
|
||||
|
||||
if ( err ) { callback(err); return; }
|
||||
if ( err ) { done(err); return; }
|
||||
var cacheChannel = me.buildCacheChannel(dbName,tableNames);
|
||||
me.channelCache[cacheKey] = cacheChannel; // store for caching
|
||||
// find last updated
|
||||
me.findLastUpdated(usr, key, tableNames, function(err, lastUpdated) {
|
||||
if ( err ) { callback(err); return; }
|
||||
if ( err ) { done(err); return; }
|
||||
response.last_updated = lastUpdated;
|
||||
callback(null);
|
||||
done(null);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@@ -329,6 +329,87 @@ suite('multilayer', function() {
|
||||
);
|
||||
});
|
||||
|
||||
test("layergroup creation raises mapviews counter", function(done) {
|
||||
var layergroup = {
|
||||
version: '1.0.0',
|
||||
layers: [
|
||||
{ options: {
|
||||
sql: 'select 1 as cartodb_id, '
|
||||
+ 'ST_Buffer(!bbox!, -32*greatest(!pixel_width!,!pixel_height!)) as the_geom_webmercator',
|
||||
cartocss: '#layer { polygon-fill:red; }',
|
||||
cartocss_version: '2.0.1'
|
||||
} }
|
||||
]
|
||||
};
|
||||
var statskey = "tiler:users:localhost";
|
||||
var mapviews_field = 'mapviews';
|
||||
var redis_stats_client = redis.createClient(global.environment.redis.port);
|
||||
var redis_stats_db = 5;
|
||||
var expected_token; // will be set on first post and checked on second
|
||||
Step(
|
||||
function clean_stats()
|
||||
{
|
||||
var next = this;
|
||||
redis_stats_client.select(redis_stats_db, function(err) {
|
||||
if ( err ) next(err);
|
||||
else redis_stats_client.del(statskey, next);
|
||||
});
|
||||
},
|
||||
function do_post_1(err)
|
||||
{
|
||||
if ( err ) throw err;
|
||||
var next = this;
|
||||
assert.response(server, {
|
||||
url: '/tiles/layergroup',
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(layergroup)
|
||||
}, {}, function(res) {
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
expected_token = JSON.parse(res.body).layergroupid;
|
||||
redis_stats_client.hget(statskey, mapviews_field, next);
|
||||
});
|
||||
},
|
||||
function check_stats_1_do_post_2(err, val) {
|
||||
if ( err ) throw err;
|
||||
assert.equal(val, 1);
|
||||
var next = this;
|
||||
assert.response(server, {
|
||||
url: '/tiles/layergroup',
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(layergroup)
|
||||
}, {}, function(res) {
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
assert.equal(JSON.parse(res.body).layergroupid, expected_token);
|
||||
redis_stats_client.hget(statskey, mapviews_field, next);
|
||||
});
|
||||
},
|
||||
function check_stats_2(err, val)
|
||||
{
|
||||
if ( err ) throw err;
|
||||
assert.equal(val, 2);
|
||||
return 1;
|
||||
},
|
||||
function finish(err) {
|
||||
var errors = [];
|
||||
if ( err ) {
|
||||
errors.push(err.message);
|
||||
console.log("Error: " + err);
|
||||
}
|
||||
redis_client.keys("map_style|cartodb_test_user_1_db|~" + expected_token, function(err, matches) {
|
||||
if ( err ) errors.push(err.message);
|
||||
assert.equal(matches.length, 1, "Missing expected token " + expected_token + " from redis: " + matches);
|
||||
redis_client.del(matches, function(err) {
|
||||
if ( err ) errors.push(err.message);
|
||||
if ( errors.length ) done(new Error(errors));
|
||||
else done(null);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
suiteTeardown(function(done) {
|
||||
// This test will add map_style records, like
|
||||
// 'map_style|null|publicuser|my_table',
|
||||
|
||||
Reference in New Issue
Block a user