From f019f346014df4d119fde855b1abf84e04b3dd7d Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Wed, 1 Apr 2015 15:04:56 +0200 Subject: [PATCH 01/17] Mapnik renderer configuration not part of the `renderer` root configuration - All configuration must be moved into `renderer.mapnik` - see `config/environments/*.js.example` for reference --- NEWS.md | 2 + config/environments/development.js.example | 44 +++++++++++++++++++++- config/environments/production.js.example | 44 +++++++++++++++++++++- config/environments/staging.js.example | 44 +++++++++++++++++++++- config/environments/test.js.example | 44 +++++++++++++++++++++- lib/cartodb/server_options.js | 1 + 6 files changed, 171 insertions(+), 8 deletions(-) diff --git a/NEWS.md b/NEWS.md index 9b2ea413..2d4f35ec 100644 --- a/NEWS.md +++ b/NEWS.md @@ -24,6 +24,8 @@ Announcements: - scale_factor * Affected tables for x-cache-channel will use direct connection to postgresql * Removes some metrics: authorized times ones + * Mapnik renderer configuration not part of the `renderer` root configuration + - All configuration must be moved into `renderer.mapnik`, see `config/environments/*.js.example` for reference - Removes rollbar as optional logger diff --git a/config/environments/development.js.example b/config/environments/development.js.example index d04ddf01..2fed947d 100644 --- a/config/environments/development.js.example +++ b/config/environments/development.js.example @@ -84,9 +84,49 @@ var config = { ,renderer: { // Milliseconds since last access before renderer cache item expires cache_ttl: 60000, - metatile: 4, - bufferSize: 64, statsInterval: 5000, // milliseconds between each report to statsd about number of renderers and mapnik pool status + mapnik: { + // The size of the pool of internal mapnik renderers + // Check the configuration of uv_threadpool_size to use suitable value + poolSize: 8, + + // Metatile is the number of tiles-per-side that are going + // to be rendered at once. If all of them will be requested + // we'd have saved time. If only one will be used, we'd have + // wasted time. + metatile: 2, + + // Buffer size is the tickness in pixel of a buffer + // around the rendered (meta?)tile. + // + // This is important for labels and other marker that overlap tile boundaries. + // Setting to 128 ensures no render artifacts. + // 64 may have artifacts but is faster. + // Less important if we can turn metatiling on. + bufferSize: 64, + + // SQL queries will be wrapped with ST_SnapToGrid + // Snapping all points of the geometry to a regular grid + snapToGrid: false, + + // SQL queries will be wrapeed with ST_ClipByBox2D + // Returning the portion of a geometry falling within a rectangle + // It will only work if snapToGrid is enabled + clipByBox2d: false, // this requires postgis >=2.2 and geos >=3.5 + + limits: { + // Time in milliseconds a render request can take before it fails, some notes: + // - 0 means no render limit + // - it considers metatiling, it naive implementation: (render timeout) * (number of tiles in metatile) + render: 0, + // As the render request will finish even if timed out, whether it should be placed in the internal + // cache or it should be fully discarded. When placed in the internal cache another attempt to retrieve + // the same tile will result in an immediate response, however that will use a lot of more application + // memory. If we want to enforce this behaviour we have to implement a cache eviction policy for the + // internal cache. + cacheOnTimeout: true + } + }, http: { timeout: 2000, // the timeout in ms for a http tile request proxy: undefined, // the url for a proxy server diff --git a/config/environments/production.js.example b/config/environments/production.js.example index 85408685..3adc127e 100644 --- a/config/environments/production.js.example +++ b/config/environments/production.js.example @@ -78,9 +78,49 @@ var config = { ,renderer: { // Milliseconds since last access before renderer cache item expires cache_ttl: 60000, - metatile: 4, - bufferSize: 64, statsInterval: 5000, // milliseconds between each report to statsd about number of renderers and mapnik pool status + mapnik: { + // The size of the pool of internal mapnik renderers + // Check the configuration of uv_threadpool_size to use suitable value + poolSize: 8, + + // Metatile is the number of tiles-per-side that are going + // to be rendered at once. If all of them will be requested + // we'd have saved time. If only one will be used, we'd have + // wasted time. + metatile: 2, + + // Buffer size is the tickness in pixel of a buffer + // around the rendered (meta?)tile. + // + // This is important for labels and other marker that overlap tile boundaries. + // Setting to 128 ensures no render artifacts. + // 64 may have artifacts but is faster. + // Less important if we can turn metatiling on. + bufferSize: 64, + + // SQL queries will be wrapped with ST_SnapToGrid + // Snapping all points of the geometry to a regular grid + snapToGrid: false, + + // SQL queries will be wrapeed with ST_ClipByBox2D + // Returning the portion of a geometry falling within a rectangle + // It will only work if snapToGrid is enabled + clipByBox2d: false, // this requires postgis >=2.2 and geos >=3.5 + + limits: { + // Time in milliseconds a render request can take before it fails, some notes: + // - 0 means no render limit + // - it considers metatiling, it naive implementation: (render timeout) * (number of tiles in metatile) + render: 0, + // As the render request will finish even if timed out, whether it should be placed in the internal + // cache or it should be fully discarded. When placed in the internal cache another attempt to retrieve + // the same tile will result in an immediate response, however that will use a lot of more application + // memory. If we want to enforce this behaviour we have to implement a cache eviction policy for the + // internal cache. + cacheOnTimeout: true + } + }, http: { timeout: 2000, // the timeout in ms for a http tile request proxy: undefined, // the url for a proxy server diff --git a/config/environments/staging.js.example b/config/environments/staging.js.example index d8e186b8..4c5fef84 100644 --- a/config/environments/staging.js.example +++ b/config/environments/staging.js.example @@ -78,9 +78,49 @@ var config = { ,renderer: { // Milliseconds since last access before renderer cache item expires cache_ttl: 60000, - metatile: 4, - bufferSize: 64, statsInterval: 5000, // milliseconds between each report to statsd about number of renderers and mapnik pool status + mapnik: { + // The size of the pool of internal mapnik renderers + // Check the configuration of uv_threadpool_size to use suitable value + poolSize: 8, + + // Metatile is the number of tiles-per-side that are going + // to be rendered at once. If all of them will be requested + // we'd have saved time. If only one will be used, we'd have + // wasted time. + metatile: 2, + + // Buffer size is the tickness in pixel of a buffer + // around the rendered (meta?)tile. + // + // This is important for labels and other marker that overlap tile boundaries. + // Setting to 128 ensures no render artifacts. + // 64 may have artifacts but is faster. + // Less important if we can turn metatiling on. + bufferSize: 64, + + // SQL queries will be wrapped with ST_SnapToGrid + // Snapping all points of the geometry to a regular grid + snapToGrid: false, + + // SQL queries will be wrapeed with ST_ClipByBox2D + // Returning the portion of a geometry falling within a rectangle + // It will only work if snapToGrid is enabled + clipByBox2d: false, // this requires postgis >=2.2 and geos >=3.5 + + limits: { + // Time in milliseconds a render request can take before it fails, some notes: + // - 0 means no render limit + // - it considers metatiling, it naive implementation: (render timeout) * (number of tiles in metatile) + render: 0, + // As the render request will finish even if timed out, whether it should be placed in the internal + // cache or it should be fully discarded. When placed in the internal cache another attempt to retrieve + // the same tile will result in an immediate response, however that will use a lot of more application + // memory. If we want to enforce this behaviour we have to implement a cache eviction policy for the + // internal cache. + cacheOnTimeout: true + } + }, http: { timeout: 2000, // the timeout in ms for a http tile request proxy: undefined, // the url for a proxy server diff --git a/config/environments/test.js.example b/config/environments/test.js.example index 9032752e..49527c4e 100644 --- a/config/environments/test.js.example +++ b/config/environments/test.js.example @@ -78,9 +78,49 @@ var config = { ,renderer: { // Milliseconds since last access before renderer cache item expires cache_ttl: 60000, - metatile: 4, - bufferSize: 64, statsInterval: 5000, // milliseconds between each report to statsd about number of renderers and mapnik pool status + mapnik: { + // The size of the pool of internal mapnik renderers + // Check the configuration of uv_threadpool_size to use suitable value + poolSize: 8, + + // Metatile is the number of tiles-per-side that are going + // to be rendered at once. If all of them will be requested + // we'd have saved time. If only one will be used, we'd have + // wasted time. + metatile: 2, + + // Buffer size is the tickness in pixel of a buffer + // around the rendered (meta?)tile. + // + // This is important for labels and other marker that overlap tile boundaries. + // Setting to 128 ensures no render artifacts. + // 64 may have artifacts but is faster. + // Less important if we can turn metatiling on. + bufferSize: 64, + + // SQL queries will be wrapped with ST_SnapToGrid + // Snapping all points of the geometry to a regular grid + snapToGrid: false, + + // SQL queries will be wrapeed with ST_ClipByBox2D + // Returning the portion of a geometry falling within a rectangle + // It will only work if snapToGrid is enabled + clipByBox2d: false, // this requires postgis >=2.2 and geos >=3.5 + + limits: { + // Time in milliseconds a render request can take before it fails, some notes: + // - 0 means no render limit + // - it considers metatiling, it naive implementation: (render timeout) * (number of tiles in metatile) + render: 0, + // As the render request will finish even if timed out, whether it should be placed in the internal + // cache or it should be fully discarded. When placed in the internal cache another attempt to retrieve + // the same tile will result in an immediate response, however that will use a lot of more application + // memory. If we want to enforce this behaviour we have to implement a cache eviction policy for the + // internal cache. + cacheOnTimeout: true + } + }, http: { timeout: 2000, // the timeout in ms for a http tile request proxy: undefined, // the url for a proxy server diff --git a/lib/cartodb/server_options.js b/lib/cartodb/server_options.js index e7f8b855..f3f3e3bd 100644 --- a/lib/cartodb/server_options.js +++ b/lib/cartodb/server_options.js @@ -70,6 +70,7 @@ module.exports = function(redisPool) { statsInterval: rendererConfig.statsInterval }, renderer: { + mapnik: rendererConfig.mapnik, http: rendererConfig.http }, redis: global.environment.redis, From a9ab9f8b5cdc0c458b4dbe207a2cdd281ef8a0eb Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Wed, 1 Apr 2015 15:11:58 +0200 Subject: [PATCH 02/17] Pick render limit and add it to request context - Extends the problematic fake request in templates - Picks the value in waterfall, this must be improved because: 1. It does not make sense if there is no layers with limits 2. If we want to include it always without considering the layer type we can do the operation in parallel --- lib/cartodb/controllers/template_maps.js | 3 +- lib/cartodb/server_options.js | 40 +++++++++++++++++++----- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/lib/cartodb/controllers/template_maps.js b/lib/cartodb/controllers/template_maps.js index e071d8a0..df504d82 100644 --- a/lib/cartodb/controllers/template_maps.js +++ b/lib/cartodb/controllers/template_maps.js @@ -408,7 +408,8 @@ TemplateMapsController.prototype.instantiateTemplate = function(req, res, templa if ( req.profiler ) req.profiler.done('TemplateMaps_instance'); if ( err ) throw err; layergroup = instance; - fakereq = { query: {}, params: {}, headers: _.clone(req.headers), + fakereq = {query: {}, params: {}, headers: _.clone(req.headers), + context: _.clone(req.context), method: req.method, res: res, profiler: req.profiler diff --git a/lib/cartodb/server_options.js b/lib/cartodb/server_options.js index f3f3e3bd..d8398809 100644 --- a/lib/cartodb/server_options.js +++ b/lib/cartodb/server_options.js @@ -1,12 +1,14 @@ var _ = require('underscore'); var step = require('step'); +var LZMA = require('lzma').LZMA; +var assert = require('assert'); +var RedisPool = require('redis-mpool'); + var QueryTablesApi = require('./api/query_tables_api'); var PgConnection = require('./backends/pg_connection'); -var LZMA = require('lzma').LZMA; var TemplateMaps = require('./template_maps.js'); var MapConfigNamedLayersAdapter = require('./models/mapconfig_named_layers_adapter'); var CdbRequest = require('./models/cdb_request'); -var assert = require('assert'); // Whitelist query parameters and attach format var REQUEST_QUERY_PARAMS_WHITELIST = [ @@ -18,8 +20,7 @@ var REQUEST_QUERY_PARAMS_WHITELIST = [ ]; module.exports = function(redisPool) { - redisPool = redisPool || - require('redis-mpool')(_.extend(global.environment.redis, {name: 'windshaft:server_options'})); + redisPool = redisPool || new RedisPool(_.extend(global.environment.redis, {name: 'windshaft:server_options'})); var cartoData = require('cartodb-redis')({ pool: redisPool }), lzmaWorker = new LZMA(), @@ -242,14 +243,37 @@ module.exports = function(redisPool) { }; me.beforeLayergroupCreate = function(req, requestMapConfig, callback) { - mapConfigNamedLayersAdapter.getLayers(cdbRequest.userByReq(req), requestMapConfig.layers, pgConnection, - function(err, layers, datasource) { + var user = cdbRequest.userByReq(req); + var namedLayersDatasource; + step( + function extractNamedLayers() { + mapConfigNamedLayersAdapter.getLayers(user, requestMapConfig.layers, pgConnection, this); + }, + function handleNamedLayers(err, layers, datasource) { + assert.ifError(err); + + namedLayersDatasource = datasource; + requestMapConfig.layers = layers; + + return null; + }, + function getLimits(err) { + assert.ifError(err); + cartoData.getTilerRenderLimit(user, this); + }, + function handleTilerLimits(err, renderLimit) { + assert.ifError(err); + req.context.limits = { + render: renderLimit + }; + return null; + }, + function finish(err) { if (err) { return callback(err); } - requestMapConfig.layers = layers; - return callback(null, requestMapConfig, datasource); + return callback(null, requestMapConfig, namedLayersDatasource); } ); }; From f0eeb393d6604a506e8b6252ad0a17209c9d2167 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Wed, 1 Apr 2015 15:49:01 +0200 Subject: [PATCH 03/17] Use windshaft render-limits branch Bump cartodb-redis version Regenerate npm-shrinkwrap.json as I accidentaly deleted it --- npm-shrinkwrap.json | 2375 +++++++++++++++++++++++++++++++++++++++++++ package.json | 4 +- 2 files changed, 2377 insertions(+), 2 deletions(-) create mode 100644 npm-shrinkwrap.json diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json new file mode 100644 index 00000000..09405e16 --- /dev/null +++ b/npm-shrinkwrap.json @@ -0,0 +1,2375 @@ +{ + "name": "windshaft-cartodb", + "version": "2.0.0", + "dependencies": { + "cartodb-psql": { + "version": "0.4.0", + "from": "cartodb-psql@~0.4.0", + "resolved": "https://registry.npmjs.org/cartodb-psql/-/cartodb-psql-0.4.0.tgz", + "dependencies": { + "pg": { + "version": "2.6.2-cdb1", + "from": "pg@git://github.com/CartoDB/node-postgres.git#2.6.2-cdb1", + "resolved": "git://github.com/CartoDB/node-postgres.git#836a2dc3131e873fc4ba20cd16e7fb69a7dca98a", + "dependencies": { + "generic-pool": { + "version": "2.0.3", + "from": "generic-pool@2.0.3", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.0.3.tgz" + }, + "buffer-writer": { + "version": "1.0.0", + "from": "buffer-writer@1.0.0", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-1.0.0.tgz" + } + } + } + } + }, + "cartodb-redis": { + "version": "0.12.0", + "from": "cartodb-redis@~0.12.0", + "dependencies": { + "redis-mpool": { + "version": "0.1.0", + "from": "redis-mpool@git://github.com/CartoDB/node-redis-mpool.git#0.1.0", + "resolved": "git://github.com/CartoDB/node-redis-mpool.git#47510b8d4525ee24aa2e5328976372274a1d144e", + "dependencies": { + "generic-pool": { + "version": "2.1.1", + "from": "generic-pool@~2.1.1", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.1.1.tgz" + }, + "redis": { + "version": "0.12.1", + "from": "redis@~0.12.1", + "resolved": "https://registry.npmjs.org/redis/-/redis-0.12.1.tgz" + }, + "hiredis": { + "version": "0.1.17", + "from": "hiredis@~0.1.17", + "resolved": "https://registry.npmjs.org/hiredis/-/hiredis-0.1.17.tgz", + "dependencies": { + "bindings": { + "version": "1.2.1", + "from": "bindings@*", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz" + }, + "nan": { + "version": "1.1.2", + "from": "nan@~1.1.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-1.1.2.tgz" + } + } + } + } + } + } + }, + "dot": { + "version": "1.0.3", + "from": "dot@~1.0.2", + "resolved": "https://registry.npmjs.org/dot/-/dot-1.0.3.tgz" + }, + "log4js": { + "version": "0.6.21", + "from": "https://github.com/CartoDB/log4js-node/tarball/cdb", + "resolved": "https://github.com/CartoDB/log4js-node/tarball/cdb", + "dependencies": { + "async": { + "version": "0.2.10", + "from": "async@~0.2.0", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz" + }, + "readable-stream": { + "version": "1.0.33", + "from": "readable-stream@~1.0.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", + "dependencies": { + "core-util-is": { + "version": "1.0.1", + "from": "core-util-is@~1.0.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" + }, + "isarray": { + "version": "0.0.1", + "from": "isarray@0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + }, + "string_decoder": { + "version": "0.10.31", + "from": "string_decoder@~0.10.x", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@~2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + } + } + } + } + }, + "lzma": { + "version": "1.3.7", + "from": "lzma@~1.3.7", + "resolved": "https://registry.npmjs.org/lzma/-/lzma-1.3.7.tgz" + }, + "queue-async": { + "version": "1.0.7", + "from": "queue-async@~1.0.7", + "resolved": "https://registry.npmjs.org/queue-async/-/queue-async-1.0.7.tgz" + }, + "redis-mpool": { + "version": "0.3.0", + "from": "redis-mpool@~0.3.0", + "resolved": "https://registry.npmjs.org/redis-mpool/-/redis-mpool-0.3.0.tgz", + "dependencies": { + "generic-pool": { + "version": "2.1.1", + "from": "generic-pool@~2.1.1", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.1.1.tgz" + }, + "redis": { + "version": "0.12.1", + "from": "redis@~0.12.1", + "resolved": "https://registry.npmjs.org/redis/-/redis-0.12.1.tgz" + }, + "hiredis": { + "version": "0.1.17", + "from": "hiredis@~0.1.17", + "resolved": "https://registry.npmjs.org/hiredis/-/hiredis-0.1.17.tgz", + "dependencies": { + "bindings": { + "version": "1.2.1", + "from": "bindings@*", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz" + }, + "nan": { + "version": "1.1.2", + "from": "nan@~1.1.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-1.1.2.tgz" + } + } + } + } + }, + "request": { + "version": "2.9.203", + "from": "request@~2.9.203", + "resolved": "https://registry.npmjs.org/request/-/request-2.9.203.tgz" + }, + "step": { + "version": "0.0.5", + "from": "step@~0.0.5", + "resolved": "https://registry.npmjs.org/step/-/step-0.0.5.tgz" + }, + "underscore": { + "version": "1.6.0", + "from": "underscore@~1.6.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz" + }, + "windshaft": { + "version": "0.41.0", + "from": "https://github.com/CartoDB/Windshaft/tarball/render-limits", + "resolved": "https://github.com/CartoDB/Windshaft/tarball/render-limits", + "dependencies": { + "chronograph": { + "version": "0.1.0", + "from": "chronograph@git://github.com/CartoDB/chronographjs.git#0.1.0", + "resolved": "git://github.com/CartoDB/chronographjs.git#0b8c35eee510cfa14a16be24d70533b38ecc1d2d" + }, + "grainstore": { + "version": "0.23.0", + "from": "grainstore@~0.23.0", + "resolved": "https://registry.npmjs.org/grainstore/-/grainstore-0.23.0.tgz", + "dependencies": { + "redis-mpool": { + "version": "0.1.0", + "from": "https://github.com/CartoDB/node-redis-mpool/tarball/0.1.0", + "resolved": "https://github.com/CartoDB/node-redis-mpool/tarball/0.1.0", + "dependencies": { + "generic-pool": { + "version": "2.1.1", + "from": "generic-pool@~2.1.1", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.1.1.tgz" + }, + "redis": { + "version": "0.12.1", + "from": "redis@~0.12.1", + "resolved": "https://registry.npmjs.org/redis/-/redis-0.12.1.tgz" + }, + "hiredis": { + "version": "0.1.17", + "from": "hiredis@~0.1.17", + "resolved": "https://registry.npmjs.org/hiredis/-/hiredis-0.1.17.tgz", + "dependencies": { + "bindings": { + "version": "1.2.1", + "from": "bindings@*", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz" + }, + "nan": { + "version": "1.1.2", + "from": "nan@~1.1.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-1.1.2.tgz" + } + } + } + } + }, + "carto": { + "version": "0.9.5-cdb2", + "from": "https://github.com/CartoDB/carto/tarball/0.9.5-cdb2", + "resolved": "https://github.com/CartoDB/carto/tarball/0.9.5-cdb2", + "dependencies": { + "underscore": { + "version": "1.4.4", + "from": "underscore@~1.4.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz" + }, + "mapnik-reference": { + "version": "5.0.9", + "from": "mapnik-reference@~5.0.7", + "resolved": "https://registry.npmjs.org/mapnik-reference/-/mapnik-reference-5.0.9.tgz" + }, + "xml2js": { + "version": "0.2.8", + "from": "xml2js@~0.2.4", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.2.8.tgz", + "dependencies": { + "sax": { + "version": "0.5.8", + "from": "sax@0.5.x", + "resolved": "https://registry.npmjs.org/sax/-/sax-0.5.8.tgz" + } + } + }, + "optimist": { + "version": "0.6.1", + "from": "optimist@~0.6.0", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "from": "wordwrap@~0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" + }, + "minimist": { + "version": "0.0.10", + "from": "minimist@~0.0.1", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz" + } + } + } + } + }, + "millstone": { + "version": "0.6.14", + "from": "millstone@0.6.14", + "resolved": "https://registry.npmjs.org/millstone/-/millstone-0.6.14.tgz", + "dependencies": { + "generic-pool": { + "version": "2.0.4", + "from": "generic-pool@~2.0.3", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.0.4.tgz" + }, + "request": { + "version": "2.34.0", + "from": "request@~2.34.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.34.0.tgz", + "dependencies": { + "qs": { + "version": "0.6.6", + "from": "qs@~0.6.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-0.6.6.tgz" + }, + "json-stringify-safe": { + "version": "5.0.0", + "from": "json-stringify-safe@~5.0.0", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.0.tgz" + }, + "forever-agent": { + "version": "0.5.2", + "from": "forever-agent@~0.5.0", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz" + }, + "node-uuid": { + "version": "1.4.3", + "from": "node-uuid@~1.4.0", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.3.tgz" + }, + "tough-cookie": { + "version": "0.12.1", + "from": "tough-cookie@>=0.12.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-0.12.1.tgz", + "dependencies": { + "punycode": { + "version": "1.3.2", + "from": "punycode@>=0.2.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz" + } + } + }, + "form-data": { + "version": "0.1.4", + "from": "form-data@~0.1.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", + "dependencies": { + "combined-stream": { + "version": "0.0.7", + "from": "combined-stream@~0.0.4", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "dependencies": { + "delayed-stream": { + "version": "0.0.5", + "from": "delayed-stream@0.0.5", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz" + } + } + }, + "async": { + "version": "0.9.0", + "from": "async@~0.9.0", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.0.tgz" + } + } + }, + "tunnel-agent": { + "version": "0.3.0", + "from": "tunnel-agent@~0.3.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.3.0.tgz" + }, + "http-signature": { + "version": "0.10.1", + "from": "http-signature@~0.10.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", + "dependencies": { + "assert-plus": { + "version": "0.1.5", + "from": "assert-plus@^0.1.5", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz" + }, + "asn1": { + "version": "0.1.11", + "from": "asn1@0.1.11", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz" + }, + "ctype": { + "version": "0.5.3", + "from": "ctype@0.5.3", + "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz" + } + } + }, + "oauth-sign": { + "version": "0.3.0", + "from": "oauth-sign@~0.3.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.3.0.tgz" + }, + "hawk": { + "version": "1.0.0", + "from": "hawk@~1.0.0", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.0.0.tgz", + "dependencies": { + "hoek": { + "version": "0.9.1", + "from": "hoek@0.9.x", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz" + }, + "boom": { + "version": "0.4.2", + "from": "boom@0.4.x", + "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz" + }, + "cryptiles": { + "version": "0.2.2", + "from": "cryptiles@0.2.x", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz" + }, + "sntp": { + "version": "0.2.4", + "from": "sntp@0.2.x", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz" + } + } + }, + "aws-sign2": { + "version": "0.5.0", + "from": "aws-sign2@~0.5.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz" + } + } + }, + "srs": { + "version": "0.4.6", + "from": "srs@~0.4.1", + "resolved": "https://registry.npmjs.org/srs/-/srs-0.4.6.tgz", + "dependencies": { + "nan": { + "version": "1.4.3", + "from": "nan@~1.4.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-1.4.3.tgz" + }, + "node-pre-gyp": { + "version": "0.6.1", + "from": "node-pre-gyp@~0.6.1", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.1.tgz", + "dependencies": { + "nopt": { + "version": "3.0.1", + "from": "nopt@~3.0.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.1.tgz", + "dependencies": { + "abbrev": { + "version": "1.0.5", + "from": "abbrev@1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.5.tgz" + } + } + }, + "npmlog": { + "version": "0.1.1", + "from": "npmlog@~0.1.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-0.1.1.tgz", + "dependencies": { + "ansi": { + "version": "0.3.0", + "from": "ansi@~0.3.0", + "resolved": "https://registry.npmjs.org/ansi/-/ansi-0.3.0.tgz" + } + } + }, + "request": { + "version": "2.48.0", + "from": "request@2.x", + "resolved": "https://registry.npmjs.org/request/-/request-2.48.0.tgz", + "dependencies": { + "bl": { + "version": "0.9.3", + "from": "bl@~0.9.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.3.tgz", + "dependencies": { + "readable-stream": { + "version": "1.0.33", + "from": "readable-stream@~1.0.26", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", + "dependencies": { + "core-util-is": { + "version": "1.0.1", + "from": "core-util-is@~1.0.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" + }, + "isarray": { + "version": "0.0.1", + "from": "isarray@0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + }, + "string_decoder": { + "version": "0.10.31", + "from": "string_decoder@~0.10.x", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@~2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + } + } + } + } + }, + "caseless": { + "version": "0.7.0", + "from": "caseless@~0.7.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.7.0.tgz" + }, + "forever-agent": { + "version": "0.5.2", + "from": "forever-agent@~0.5.0", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz" + }, + "form-data": { + "version": "0.1.4", + "from": "form-data@~0.1.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", + "dependencies": { + "mime": { + "version": "1.2.11", + "from": "mime@~1.2.11", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" + }, + "async": { + "version": "0.9.0", + "from": "async@~0.9.0", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.0.tgz" + } + } + }, + "json-stringify-safe": { + "version": "5.0.0", + "from": "json-stringify-safe@~5.0.0", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.0.tgz" + }, + "mime-types": { + "version": "1.0.2", + "from": "mime-types@~1.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz" + }, + "node-uuid": { + "version": "1.4.1", + "from": "node-uuid@~1.4.0", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.1.tgz" + }, + "qs": { + "version": "2.3.3", + "from": "qs@~2.3.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz" + }, + "tunnel-agent": { + "version": "0.4.0", + "from": "tunnel-agent@~0.4.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.0.tgz" + }, + "tough-cookie": { + "version": "0.12.1", + "from": "tough-cookie@>=0.12.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-0.12.1.tgz", + "dependencies": { + "punycode": { + "version": "1.3.2", + "from": "punycode@>=0.2.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz" + } + } + }, + "http-signature": { + "version": "0.10.0", + "from": "http-signature@~0.10.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.0.tgz", + "dependencies": { + "assert-plus": { + "version": "0.1.2", + "from": "assert-plus@0.1.2", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.2.tgz" + }, + "asn1": { + "version": "0.1.11", + "from": "asn1@0.1.11", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz" + }, + "ctype": { + "version": "0.5.2", + "from": "ctype@0.5.2", + "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.2.tgz" + } + } + }, + "oauth-sign": { + "version": "0.5.0", + "from": "oauth-sign@~0.5.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.5.0.tgz" + }, + "hawk": { + "version": "1.1.1", + "from": "hawk@1.1.1", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz", + "dependencies": { + "hoek": { + "version": "0.9.1", + "from": "hoek@0.9.x", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz" + }, + "boom": { + "version": "0.4.2", + "from": "boom@0.4.x", + "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz" + }, + "cryptiles": { + "version": "0.2.2", + "from": "cryptiles@0.2.x", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz" + }, + "sntp": { + "version": "0.2.4", + "from": "sntp@0.2.x", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz" + } + } + }, + "aws-sign2": { + "version": "0.5.0", + "from": "aws-sign2@~0.5.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz" + }, + "stringstream": { + "version": "0.0.4", + "from": "stringstream@~0.0.4", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.4.tgz" + }, + "combined-stream": { + "version": "0.0.7", + "from": "combined-stream@~0.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "dependencies": { + "delayed-stream": { + "version": "0.0.5", + "from": "delayed-stream@0.0.5", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz" + } + } + } + } + }, + "semver": { + "version": "4.1.0", + "from": "semver@~4.1.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.1.0.tgz" + }, + "tar": { + "version": "1.0.2", + "from": "tar@~1.0.2", + "resolved": "https://registry.npmjs.org/tar/-/tar-1.0.2.tgz", + "dependencies": { + "block-stream": { + "version": "0.0.7", + "from": "block-stream@*", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.7.tgz" + }, + "fstream": { + "version": "1.0.2", + "from": "fstream@^1.0.2", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.2.tgz", + "dependencies": { + "graceful-fs": { + "version": "3.0.4", + "from": "graceful-fs@3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.4.tgz" + } + } + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + } + } + }, + "tar-pack": { + "version": "2.0.0", + "from": "tar-pack@~2.0.0", + "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-2.0.0.tgz", + "dependencies": { + "uid-number": { + "version": "0.0.3", + "from": "uid-number@0.0.3", + "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.3.tgz" + }, + "once": { + "version": "1.1.1", + "from": "once@~1.1.1", + "resolved": "https://registry.npmjs.org/once/-/once-1.1.1.tgz" + }, + "debug": { + "version": "0.7.4", + "from": "debug@~0.7.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz" + }, + "fstream": { + "version": "0.1.31", + "from": "fstream@~0.1.22", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-0.1.31.tgz", + "dependencies": { + "graceful-fs": { + "version": "3.0.4", + "from": "graceful-fs@~3.0.2", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.4.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@~2.0.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + } + } + }, + "tar": { + "version": "0.1.20", + "from": "tar@~0.1.17", + "resolved": "https://registry.npmjs.org/tar/-/tar-0.1.20.tgz", + "dependencies": { + "block-stream": { + "version": "0.0.7", + "from": "block-stream@*", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.7.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + } + } + }, + "fstream-ignore": { + "version": "0.0.7", + "from": "fstream-ignore@0.0.7", + "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-0.0.7.tgz", + "dependencies": { + "minimatch": { + "version": "0.2.14", + "from": "minimatch@~0.2.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "dependencies": { + "lru-cache": { + "version": "2.5.0", + "from": "lru-cache@2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" + }, + "sigmund": { + "version": "1.0.0", + "from": "sigmund@~1.0.0", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" + } + } + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + } + } + }, + "readable-stream": { + "version": "1.0.33", + "from": "readable-stream@~1.0.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", + "dependencies": { + "core-util-is": { + "version": "1.0.1", + "from": "core-util-is@~1.0.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" + }, + "isarray": { + "version": "0.0.1", + "from": "isarray@0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + }, + "string_decoder": { + "version": "0.10.31", + "from": "string_decoder@~0.10.x", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@~2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + } + } + }, + "graceful-fs": { + "version": "1.2.3", + "from": "graceful-fs@1.2", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz" + } + } + }, + "mkdirp": { + "version": "0.5.0", + "from": "mkdirp@~0.5.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", + "dependencies": { + "minimist": { + "version": "0.0.8", + "from": "minimist@0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" + } + } + }, + "rc": { + "version": "0.5.4", + "from": "rc@~0.5.1", + "resolved": "https://registry.npmjs.org/rc/-/rc-0.5.4.tgz", + "dependencies": { + "minimist": { + "version": "0.0.10", + "from": "minimist@~0.0.7", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz" + }, + "deep-extend": { + "version": "0.2.11", + "from": "deep-extend@~0.2.5", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.2.11.tgz" + }, + "strip-json-comments": { + "version": "0.1.3", + "from": "strip-json-comments@0.1.x", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-0.1.3.tgz" + }, + "ini": { + "version": "1.1.0", + "from": "ini@~1.1.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.1.0.tgz" + } + } + }, + "rimraf": { + "version": "2.2.8", + "from": "rimraf@~2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz" + } + } + } + } + }, + "zipfile": { + "version": "0.5.7", + "from": "zipfile@~0.5.2", + "resolved": "https://registry.npmjs.org/zipfile/-/zipfile-0.5.7.tgz", + "dependencies": { + "nan": { + "version": "1.5.3", + "from": "nan@~1.5.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-1.5.3.tgz" + }, + "node-pre-gyp": { + "version": "0.6.2", + "from": "node-pre-gyp@>=0.6.2 <0.7.0", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.2.tgz", + "dependencies": { + "nopt": { + "version": "3.0.1", + "from": "nopt@~3.0.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.1.tgz", + "dependencies": { + "abbrev": { + "version": "1.0.5", + "from": "abbrev@1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.5.tgz" + } + } + }, + "npmlog": { + "version": "0.1.1", + "from": "npmlog@~0.1.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-0.1.1.tgz", + "dependencies": { + "ansi": { + "version": "0.3.0", + "from": "ansi@~0.3.0", + "resolved": "https://registry.npmjs.org/ansi/-/ansi-0.3.0.tgz" + } + } + }, + "request": { + "version": "2.51.0", + "from": "request@2.x", + "resolved": "https://registry.npmjs.org/request/-/request-2.51.0.tgz", + "dependencies": { + "bl": { + "version": "0.9.3", + "from": "bl@~0.9.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.3.tgz", + "dependencies": { + "readable-stream": { + "version": "1.0.33", + "from": "readable-stream@~1.0.26", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", + "dependencies": { + "core-util-is": { + "version": "1.0.1", + "from": "core-util-is@~1.0.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" + }, + "isarray": { + "version": "0.0.1", + "from": "isarray@0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + }, + "string_decoder": { + "version": "0.10.31", + "from": "string_decoder@~0.10.x", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@~2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + } + } + } + } + }, + "caseless": { + "version": "0.8.0", + "from": "caseless@~0.8.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.8.0.tgz" + }, + "forever-agent": { + "version": "0.5.2", + "from": "forever-agent@~0.5.0", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz" + }, + "form-data": { + "version": "0.2.0", + "from": "form-data@~0.2.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.2.0.tgz", + "dependencies": { + "async": { + "version": "0.9.0", + "from": "async@~0.9.0", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.0.tgz" + }, + "mime-types": { + "version": "2.0.7", + "from": "mime-types@~2.0.3", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.7.tgz", + "dependencies": { + "mime-db": { + "version": "1.5.0", + "from": "mime-db@~1.5.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.5.0.tgz" + } + } + } + } + }, + "json-stringify-safe": { + "version": "5.0.0", + "from": "json-stringify-safe@~5.0.0", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.0.tgz" + }, + "mime-types": { + "version": "1.0.2", + "from": "mime-types@~1.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz" + }, + "node-uuid": { + "version": "1.4.2", + "from": "node-uuid@~1.4.0", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.2.tgz" + }, + "qs": { + "version": "2.3.3", + "from": "qs@~2.3.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz" + }, + "tunnel-agent": { + "version": "0.4.0", + "from": "tunnel-agent@~0.4.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.0.tgz" + }, + "tough-cookie": { + "version": "0.12.1", + "from": "tough-cookie@>=0.12.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-0.12.1.tgz", + "dependencies": { + "punycode": { + "version": "1.3.2", + "from": "punycode@>=0.2.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz" + } + } + }, + "http-signature": { + "version": "0.10.1", + "from": "http-signature@~0.10.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", + "dependencies": { + "assert-plus": { + "version": "0.1.5", + "from": "assert-plus@^0.1.5", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz" + }, + "asn1": { + "version": "0.1.11", + "from": "asn1@0.1.11", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz" + }, + "ctype": { + "version": "0.5.3", + "from": "ctype@0.5.3", + "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz" + } + } + }, + "oauth-sign": { + "version": "0.5.0", + "from": "oauth-sign@~0.5.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.5.0.tgz" + }, + "hawk": { + "version": "1.1.1", + "from": "hawk@1.1.1", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz", + "dependencies": { + "hoek": { + "version": "0.9.1", + "from": "hoek@0.9.x", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz" + }, + "boom": { + "version": "0.4.2", + "from": "boom@0.4.x", + "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz" + }, + "cryptiles": { + "version": "0.2.2", + "from": "cryptiles@0.2.x", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz" + }, + "sntp": { + "version": "0.2.4", + "from": "sntp@0.2.x", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz" + } + } + }, + "aws-sign2": { + "version": "0.5.0", + "from": "aws-sign2@~0.5.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz" + }, + "stringstream": { + "version": "0.0.4", + "from": "stringstream@~0.0.4", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.4.tgz" + }, + "combined-stream": { + "version": "0.0.7", + "from": "combined-stream@~0.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "dependencies": { + "delayed-stream": { + "version": "0.0.5", + "from": "delayed-stream@0.0.5", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz" + } + } + } + } + }, + "semver": { + "version": "4.2.0", + "from": "semver@~4.2.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.2.0.tgz" + }, + "tar": { + "version": "1.0.3", + "from": "tar@~1.0.2", + "resolved": "https://registry.npmjs.org/tar/-/tar-1.0.3.tgz", + "dependencies": { + "block-stream": { + "version": "0.0.7", + "from": "block-stream@*", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.7.tgz" + }, + "fstream": { + "version": "1.0.3", + "from": "fstream@^1.0.2", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.3.tgz", + "dependencies": { + "graceful-fs": { + "version": "3.0.5", + "from": "graceful-fs@3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.5.tgz" + } + } + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + } + } + }, + "tar-pack": { + "version": "2.0.0", + "from": "tar-pack@~2.0.0", + "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-2.0.0.tgz", + "dependencies": { + "uid-number": { + "version": "0.0.3", + "from": "uid-number@0.0.3", + "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.3.tgz" + }, + "once": { + "version": "1.1.1", + "from": "once@~1.1.1", + "resolved": "https://registry.npmjs.org/once/-/once-1.1.1.tgz" + }, + "debug": { + "version": "0.7.4", + "from": "debug@~0.7.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz" + }, + "fstream": { + "version": "0.1.31", + "from": "fstream@~0.1.22", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-0.1.31.tgz", + "dependencies": { + "graceful-fs": { + "version": "3.0.5", + "from": "graceful-fs@3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.5.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@~2.0.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + } + } + }, + "tar": { + "version": "0.1.20", + "from": "tar@~0.1.17", + "resolved": "https://registry.npmjs.org/tar/-/tar-0.1.20.tgz", + "dependencies": { + "block-stream": { + "version": "0.0.7", + "from": "block-stream@*", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.7.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + } + } + }, + "fstream-ignore": { + "version": "0.0.7", + "from": "fstream-ignore@0.0.7", + "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-0.0.7.tgz", + "dependencies": { + "minimatch": { + "version": "0.2.14", + "from": "minimatch@~0.2.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "dependencies": { + "lru-cache": { + "version": "2.5.0", + "from": "lru-cache@2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" + }, + "sigmund": { + "version": "1.0.0", + "from": "sigmund@~1.0.0", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" + } + } + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + } + } + }, + "readable-stream": { + "version": "1.0.33", + "from": "readable-stream@~1.0.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", + "dependencies": { + "core-util-is": { + "version": "1.0.1", + "from": "core-util-is@~1.0.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" + }, + "isarray": { + "version": "0.0.1", + "from": "isarray@0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + }, + "string_decoder": { + "version": "0.10.31", + "from": "string_decoder@~0.10.x", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@~2.0.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + } + } + }, + "graceful-fs": { + "version": "1.2.3", + "from": "graceful-fs@1.2", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz" + } + } + }, + "mkdirp": { + "version": "0.5.0", + "from": "mkdirp@~0.5.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", + "dependencies": { + "minimist": { + "version": "0.0.8", + "from": "minimist@0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" + } + } + }, + "rc": { + "version": "0.5.5", + "from": "rc@~0.5.1", + "resolved": "https://registry.npmjs.org/rc/-/rc-0.5.5.tgz", + "dependencies": { + "minimist": { + "version": "0.0.10", + "from": "minimist@~0.0.7", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz" + }, + "deep-extend": { + "version": "0.2.11", + "from": "deep-extend@~0.2.5", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.2.11.tgz" + }, + "strip-json-comments": { + "version": "0.1.3", + "from": "strip-json-comments@0.1.x", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-0.1.3.tgz" + }, + "ini": { + "version": "1.3.2", + "from": "ini@~1.3.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.2.tgz" + } + } + }, + "rimraf": { + "version": "2.2.8", + "from": "rimraf@~2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz" + } + } + } + } + }, + "sqlite3": { + "version": "2.2.7", + "from": "sqlite3@2.x", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-2.2.7.tgz", + "dependencies": { + "nan": { + "version": "1.1.2", + "from": "nan@1.1.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-1.1.2.tgz" + }, + "node-pre-gyp": { + "version": "0.5.22", + "from": "node-pre-gyp@0.5.22", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.5.22.tgz", + "dependencies": { + "nopt": { + "version": "3.0.1", + "from": "nopt@~3.0.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.1.tgz", + "dependencies": { + "abbrev": { + "version": "1.0.5", + "from": "abbrev@1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.5.tgz" + } + } + }, + "npmlog": { + "version": "0.1.1", + "from": "npmlog@~0.1.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-0.1.1.tgz", + "dependencies": { + "ansi": { + "version": "0.3.0", + "from": "ansi@~0.3.0", + "resolved": "https://registry.npmjs.org/ansi/-/ansi-0.3.0.tgz" + } + } + }, + "request": { + "version": "2.39.0", + "from": "request@2.x", + "resolved": "https://registry.npmjs.org/request/-/request-2.39.0.tgz", + "dependencies": { + "qs": { + "version": "0.6.6", + "from": "qs@~0.6.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-0.6.6.tgz" + }, + "json-stringify-safe": { + "version": "5.0.0", + "from": "json-stringify-safe@~5.0.0", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.0.tgz" + }, + "mime-types": { + "version": "1.0.2", + "from": "mime-types@~1.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz" + }, + "forever-agent": { + "version": "0.5.2", + "from": "forever-agent@~0.5.0", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz" + }, + "node-uuid": { + "version": "1.4.1", + "from": "node-uuid@~1.4.0", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.1.tgz" + }, + "tough-cookie": { + "version": "0.12.1", + "from": "tough-cookie@>=0.12.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-0.12.1.tgz", + "dependencies": { + "punycode": { + "version": "1.3.0", + "from": "punycode@>=0.2.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.0.tgz" + } + } + }, + "form-data": { + "version": "0.1.4", + "from": "form-data@~0.1.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", + "dependencies": { + "combined-stream": { + "version": "0.0.5", + "from": "combined-stream@~0.0.4", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.5.tgz", + "dependencies": { + "delayed-stream": { + "version": "0.0.5", + "from": "delayed-stream@0.0.5", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz" + } + } + }, + "mime": { + "version": "1.2.11", + "from": "mime@~1.2.11", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" + }, + "async": { + "version": "0.9.0", + "from": "async@~0.9.0", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.0.tgz" + } + } + }, + "tunnel-agent": { + "version": "0.4.0", + "from": "tunnel-agent@~0.4.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.0.tgz" + }, + "http-signature": { + "version": "0.10.0", + "from": "http-signature@~0.10.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.0.tgz", + "dependencies": { + "assert-plus": { + "version": "0.1.2", + "from": "assert-plus@0.1.2", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.2.tgz" + }, + "asn1": { + "version": "0.1.11", + "from": "asn1@0.1.11", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz" + }, + "ctype": { + "version": "0.5.2", + "from": "ctype@0.5.2", + "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.2.tgz" + } + } + }, + "oauth-sign": { + "version": "0.3.0", + "from": "oauth-sign@~0.3.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.3.0.tgz" + }, + "hawk": { + "version": "1.1.1", + "from": "hawk@1.1.1", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz", + "dependencies": { + "hoek": { + "version": "0.9.1", + "from": "hoek@0.9.x", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz" + }, + "boom": { + "version": "0.4.2", + "from": "boom@0.4.x", + "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz" + }, + "cryptiles": { + "version": "0.2.2", + "from": "cryptiles@0.2.x", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz" + }, + "sntp": { + "version": "0.2.4", + "from": "sntp@0.2.x", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz" + } + } + }, + "aws-sign2": { + "version": "0.5.0", + "from": "aws-sign2@~0.5.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz" + }, + "stringstream": { + "version": "0.0.4", + "from": "stringstream@~0.0.4", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.4.tgz" + } + } + }, + "semver": { + "version": "3.0.1", + "from": "semver@~3.0.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-3.0.1.tgz" + }, + "tar": { + "version": "1.0.0", + "from": "tar@~1.0.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-1.0.0.tgz", + "dependencies": { + "block-stream": { + "version": "0.0.7", + "from": "block-stream@*", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.7.tgz" + }, + "fstream": { + "version": "1.0.1", + "from": "fstream@^1.0.0", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.1.tgz", + "dependencies": { + "graceful-fs": { + "version": "3.0.2", + "from": "graceful-fs@3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.2.tgz" + } + } + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@~2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + } + } + }, + "tar-pack": { + "version": "2.0.0", + "from": "tar-pack@~2.0.0", + "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-2.0.0.tgz", + "dependencies": { + "uid-number": { + "version": "0.0.3", + "from": "uid-number@0.0.3", + "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.3.tgz" + }, + "once": { + "version": "1.1.1", + "from": "once@~1.1.1", + "resolved": "https://registry.npmjs.org/once/-/once-1.1.1.tgz" + }, + "debug": { + "version": "0.7.4", + "from": "debug@~0.7.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz" + }, + "fstream": { + "version": "0.1.31", + "from": "fstream@~0.1.22", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-0.1.31.tgz", + "dependencies": { + "graceful-fs": { + "version": "3.0.2", + "from": "graceful-fs@3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.2.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + } + } + }, + "tar": { + "version": "0.1.20", + "from": "tar@~0.1.17", + "resolved": "https://registry.npmjs.org/tar/-/tar-0.1.20.tgz", + "dependencies": { + "block-stream": { + "version": "0.0.7", + "from": "block-stream@*", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.7.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + } + } + }, + "fstream-ignore": { + "version": "0.0.7", + "from": "fstream-ignore@0.0.7", + "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-0.0.7.tgz", + "dependencies": { + "minimatch": { + "version": "0.2.14", + "from": "minimatch@~0.2.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "dependencies": { + "lru-cache": { + "version": "2.5.0", + "from": "lru-cache@2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" + }, + "sigmund": { + "version": "1.0.0", + "from": "sigmund@~1.0.0", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" + } + } + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + } + } + }, + "readable-stream": { + "version": "1.0.27-1", + "from": "readable-stream@~1.0.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.27-1.tgz", + "dependencies": { + "core-util-is": { + "version": "1.0.1", + "from": "core-util-is@~1.0.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" + }, + "isarray": { + "version": "0.0.1", + "from": "isarray@0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + }, + "string_decoder": { + "version": "0.10.25-1", + "from": "string_decoder@~0.10.x", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.25-1.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + } + } + }, + "graceful-fs": { + "version": "1.2.3", + "from": "graceful-fs@1.2", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz" + } + } + }, + "mkdirp": { + "version": "0.5.0", + "from": "mkdirp@~0.5.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", + "dependencies": { + "minimist": { + "version": "0.0.8", + "from": "minimist@0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" + } + } + }, + "rc": { + "version": "0.5.0", + "from": "rc@~0.5.0", + "resolved": "https://registry.npmjs.org/rc/-/rc-0.5.0.tgz", + "dependencies": { + "minimist": { + "version": "0.0.10", + "from": "minimist@~0.0.7", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz" + }, + "deep-extend": { + "version": "0.2.11", + "from": "deep-extend@~0.2.5", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.2.11.tgz" + }, + "strip-json-comments": { + "version": "0.1.3", + "from": "strip-json-comments@0.1.x", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-0.1.3.tgz" + }, + "ini": { + "version": "1.1.0", + "from": "ini@~1.1.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.1.0.tgz" + } + } + }, + "rimraf": { + "version": "2.2.8", + "from": "rimraf@~2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz" + } + } + }, + "set-immediate": { + "version": "0.1.1", + "from": "set-immediate@0.1.1", + "resolved": "https://registry.npmjs.org/set-immediate/-/set-immediate-0.1.1.tgz" + } + } + }, + "mime": { + "version": "1.2.11", + "from": "mime@~1.2.9", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" + }, + "mkdirp": { + "version": "0.3.5", + "from": "mkdirp@~0.3.3", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz" + }, + "optimist": { + "version": "0.6.1", + "from": "optimist@~0.6.0", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "from": "wordwrap@~0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" + }, + "minimist": { + "version": "0.0.10", + "from": "minimist@~0.0.1", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz" + } + } + } + } + } + } + }, + "express": { + "version": "2.5.11", + "from": "express@~2.5.11", + "resolved": "https://registry.npmjs.org/express/-/express-2.5.11.tgz", + "dependencies": { + "connect": { + "version": "1.9.2", + "from": "connect@1.x", + "resolved": "https://registry.npmjs.org/connect/-/connect-1.9.2.tgz", + "dependencies": { + "formidable": { + "version": "1.0.17", + "from": "formidable@1.0.x", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.0.17.tgz" + } + } + }, + "mime": { + "version": "1.2.4", + "from": "mime@1.2.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.4.tgz" + }, + "qs": { + "version": "0.4.2", + "from": "qs@0.4.x", + "resolved": "https://registry.npmjs.org/qs/-/qs-0.4.2.tgz" + }, + "mkdirp": { + "version": "0.3.0", + "from": "mkdirp@0.3.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz" + } + } + }, + "tilelive": { + "version": "4.5.3", + "from": "tilelive@~4.5.3", + "resolved": "https://registry.npmjs.org/tilelive/-/tilelive-4.5.3.tgz", + "dependencies": { + "optimist": { + "version": "0.6.1", + "from": "optimist@~0.6.0", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "from": "wordwrap@~0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" + }, + "minimist": { + "version": "0.0.10", + "from": "minimist@~0.0.1", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz" + } + } + } + } + }, + "tilelive-mapnik": { + "version": "0.6.15", + "from": "https://github.com/CartoDB/tilelive-mapnik/tarball/cdb-limits", + "resolved": "https://github.com/CartoDB/tilelive-mapnik/tarball/cdb-limits", + "dependencies": { + "generic-pool": { + "version": "2.1.1", + "from": "generic-pool@~2.1.1", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.1.1.tgz" + }, + "mime": { + "version": "1.2.11", + "from": "mime@~1.2.11", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" + } + } + }, + "mapnik": { + "version": "1.4.15-cdb1", + "from": "https://github.com/CartoDB/node-mapnik/tarball/1.4.15-cdb1", + "resolved": "https://github.com/CartoDB/node-mapnik/tarball/1.4.15-cdb1", + "dependencies": { + "nan": { + "version": "1.2.0", + "from": "nan@~1.2.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-1.2.0.tgz" + }, + "mapnik-vector-tile": { + "version": "0.5.5", + "from": "mapnik-vector-tile@0.5.5", + "resolved": "https://registry.npmjs.org/mapnik-vector-tile/-/mapnik-vector-tile-0.5.5.tgz" + }, + "node-pre-gyp": { + "version": "0.5.25", + "from": "node-pre-gyp@0.5.25", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.5.25.tgz", + "dependencies": { + "nopt": { + "version": "3.0.1", + "from": "nopt@~3.0.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.1.tgz", + "dependencies": { + "abbrev": { + "version": "1.0.5", + "from": "abbrev@1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.5.tgz" + } + } + }, + "npmlog": { + "version": "0.1.1", + "from": "npmlog@~0.1.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-0.1.1.tgz", + "dependencies": { + "ansi": { + "version": "0.3.0", + "from": "ansi@~0.3.0", + "resolved": "https://registry.npmjs.org/ansi/-/ansi-0.3.0.tgz" + } + } + }, + "request": { + "version": "2.40.0", + "from": "request@2.x", + "resolved": "https://registry.npmjs.org/request/-/request-2.40.0.tgz", + "dependencies": { + "qs": { + "version": "1.0.2", + "from": "qs@~1.0.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-1.0.2.tgz" + }, + "json-stringify-safe": { + "version": "5.0.0", + "from": "json-stringify-safe@~5.0.0", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.0.tgz" + }, + "mime-types": { + "version": "1.0.2", + "from": "mime-types@~1.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz" + }, + "forever-agent": { + "version": "0.5.2", + "from": "forever-agent@~0.5.0", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz" + }, + "node-uuid": { + "version": "1.4.1", + "from": "node-uuid@~1.4.0", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.1.tgz" + }, + "tough-cookie": { + "version": "0.12.1", + "from": "tough-cookie@>=0.12.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-0.12.1.tgz", + "dependencies": { + "punycode": { + "version": "1.3.1", + "from": "punycode@>=0.2.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.1.tgz" + } + } + }, + "form-data": { + "version": "0.1.4", + "from": "form-data@~0.1.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", + "dependencies": { + "combined-stream": { + "version": "0.0.5", + "from": "combined-stream@~0.0.4", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.5.tgz", + "dependencies": { + "delayed-stream": { + "version": "0.0.5", + "from": "delayed-stream@0.0.5", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz" + } + } + }, + "mime": { + "version": "1.2.11", + "from": "mime@~1.2.11", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" + }, + "async": { + "version": "0.9.0", + "from": "async@~0.9.0", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.0.tgz" + } + } + }, + "tunnel-agent": { + "version": "0.4.0", + "from": "tunnel-agent@~0.4.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.0.tgz" + }, + "http-signature": { + "version": "0.10.0", + "from": "http-signature@~0.10.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.0.tgz", + "dependencies": { + "assert-plus": { + "version": "0.1.2", + "from": "assert-plus@0.1.2", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.2.tgz" + }, + "asn1": { + "version": "0.1.11", + "from": "asn1@0.1.11", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz" + }, + "ctype": { + "version": "0.5.2", + "from": "ctype@0.5.2", + "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.2.tgz" + } + } + }, + "oauth-sign": { + "version": "0.3.0", + "from": "oauth-sign@~0.3.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.3.0.tgz" + }, + "hawk": { + "version": "1.1.1", + "from": "hawk@1.1.1", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz", + "dependencies": { + "hoek": { + "version": "0.9.1", + "from": "hoek@0.9.x", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz" + }, + "boom": { + "version": "0.4.2", + "from": "boom@0.4.x", + "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz" + }, + "cryptiles": { + "version": "0.2.2", + "from": "cryptiles@0.2.x", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz" + }, + "sntp": { + "version": "0.2.4", + "from": "sntp@0.2.x", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz" + } + } + }, + "aws-sign2": { + "version": "0.5.0", + "from": "aws-sign2@~0.5.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz" + }, + "stringstream": { + "version": "0.0.4", + "from": "stringstream@~0.0.4", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.4.tgz" + } + } + }, + "semver": { + "version": "3.0.1", + "from": "semver@~3.0.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-3.0.1.tgz" + }, + "tar": { + "version": "1.0.1", + "from": "tar@~1.0.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-1.0.1.tgz", + "dependencies": { + "block-stream": { + "version": "0.0.7", + "from": "block-stream@*", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.7.tgz" + }, + "fstream": { + "version": "1.0.2", + "from": "fstream@^1.0.2", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.2.tgz", + "dependencies": { + "graceful-fs": { + "version": "3.0.2", + "from": "graceful-fs@3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.2.tgz" + } + } + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + } + } + }, + "tar-pack": { + "version": "2.0.0", + "from": "tar-pack@~2.0.0", + "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-2.0.0.tgz", + "dependencies": { + "uid-number": { + "version": "0.0.3", + "from": "uid-number@0.0.3", + "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.3.tgz" + }, + "once": { + "version": "1.1.1", + "from": "once@~1.1.1", + "resolved": "https://registry.npmjs.org/once/-/once-1.1.1.tgz" + }, + "debug": { + "version": "0.7.4", + "from": "debug@~0.7.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz" + }, + "fstream": { + "version": "0.1.31", + "from": "fstream@~0.1.22", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-0.1.31.tgz", + "dependencies": { + "graceful-fs": { + "version": "3.0.2", + "from": "graceful-fs@~3.0.2", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.2.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + } + } + }, + "tar": { + "version": "0.1.20", + "from": "tar@~0.1.17", + "resolved": "https://registry.npmjs.org/tar/-/tar-0.1.20.tgz", + "dependencies": { + "block-stream": { + "version": "0.0.7", + "from": "block-stream@*", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.7.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + } + } + }, + "fstream-ignore": { + "version": "0.0.7", + "from": "fstream-ignore@0.0.7", + "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-0.0.7.tgz", + "dependencies": { + "minimatch": { + "version": "0.2.14", + "from": "minimatch@~0.2.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "dependencies": { + "lru-cache": { + "version": "2.5.0", + "from": "lru-cache@2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" + }, + "sigmund": { + "version": "1.0.0", + "from": "sigmund@~1.0.0", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" + } + } + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + } + } + }, + "readable-stream": { + "version": "1.0.31", + "from": "readable-stream@~1.0.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.31.tgz", + "dependencies": { + "core-util-is": { + "version": "1.0.1", + "from": "core-util-is@~1.0.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" + }, + "isarray": { + "version": "0.0.1", + "from": "isarray@0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + }, + "string_decoder": { + "version": "0.10.31", + "from": "string_decoder@~0.10.x", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@~2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + } + } + }, + "graceful-fs": { + "version": "1.2.3", + "from": "graceful-fs@1.2", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz" + } + } + }, + "mkdirp": { + "version": "0.5.0", + "from": "mkdirp@~0.5.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", + "dependencies": { + "minimist": { + "version": "0.0.8", + "from": "minimist@0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" + } + } + }, + "rc": { + "version": "0.5.1", + "from": "rc@~0.5.0", + "resolved": "https://registry.npmjs.org/rc/-/rc-0.5.1.tgz", + "dependencies": { + "minimist": { + "version": "0.0.10", + "from": "minimist@~0.0.7", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz" + }, + "deep-extend": { + "version": "0.2.11", + "from": "deep-extend@~0.2.5", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.2.11.tgz" + }, + "strip-json-comments": { + "version": "0.1.3", + "from": "strip-json-comments@0.1.x", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-0.1.3.tgz" + }, + "ini": { + "version": "1.1.0", + "from": "ini@~1.1.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.1.0.tgz" + } + } + }, + "rimraf": { + "version": "2.2.8", + "from": "rimraf@~2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz" + } + } + } + } + }, + "canvas": { + "version": "1.2.1", + "from": "canvas@1.2.1", + "resolved": "https://registry.npmjs.org/canvas/-/canvas-1.2.1.tgz", + "dependencies": { + "nan": { + "version": "1.5.3", + "from": "nan@~1.5.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-1.5.3.tgz" + } + } + }, + "carto": { + "version": "0.15.1-cdb1", + "from": "https://github.com/CartoDB/carto/tarball/0.15.1-cdb1", + "resolved": "https://github.com/CartoDB/carto/tarball/0.15.1-cdb1", + "dependencies": { + "mapnik-reference": { + "version": "6.0.5", + "from": "mapnik-reference@~6.0.2", + "resolved": "https://registry.npmjs.org/mapnik-reference/-/mapnik-reference-6.0.5.tgz" + }, + "optimist": { + "version": "0.6.1", + "from": "optimist@~0.6.0", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "from": "wordwrap@~0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" + }, + "minimist": { + "version": "0.0.10", + "from": "minimist@~0.0.1", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz" + } + } + } + } + }, + "step-profiler": { + "version": "0.2.1", + "from": "step-profiler@~0.2.1", + "resolved": "https://registry.npmjs.org/step-profiler/-/step-profiler-0.2.1.tgz" + }, + "torque.js": { + "version": "2.11.0", + "from": "torque.js@~2.11.0", + "resolved": "https://registry.npmjs.org/torque.js/-/torque.js-2.11.0.tgz" + }, + "request": { + "version": "2.48.0", + "from": "request@2.48.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.48.0.tgz", + "dependencies": { + "bl": { + "version": "0.9.4", + "from": "bl@~0.9.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.4.tgz", + "dependencies": { + "readable-stream": { + "version": "1.0.33", + "from": "readable-stream@~1.0.26", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", + "dependencies": { + "core-util-is": { + "version": "1.0.1", + "from": "core-util-is@~1.0.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" + }, + "isarray": { + "version": "0.0.1", + "from": "isarray@0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + }, + "string_decoder": { + "version": "0.10.31", + "from": "string_decoder@~0.10.x", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@~2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + } + } + } + } + }, + "caseless": { + "version": "0.7.0", + "from": "caseless@~0.7.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.7.0.tgz" + }, + "forever-agent": { + "version": "0.5.2", + "from": "forever-agent@~0.5.0", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz" + }, + "form-data": { + "version": "0.1.4", + "from": "form-data@~0.1.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", + "dependencies": { + "mime": { + "version": "1.2.11", + "from": "mime@~1.2.11", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" + }, + "async": { + "version": "0.9.0", + "from": "async@~0.9.0", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.0.tgz" + } + } + }, + "json-stringify-safe": { + "version": "5.0.0", + "from": "json-stringify-safe@~5.0.0", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.0.tgz" + }, + "mime-types": { + "version": "1.0.2", + "from": "mime-types@~1.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz" + }, + "node-uuid": { + "version": "1.4.3", + "from": "node-uuid@~1.4.0", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.3.tgz" + }, + "qs": { + "version": "2.3.3", + "from": "qs@~2.3.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz" + }, + "tunnel-agent": { + "version": "0.4.0", + "from": "tunnel-agent@~0.4.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.0.tgz" + }, + "tough-cookie": { + "version": "0.12.1", + "from": "tough-cookie@>=0.12.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-0.12.1.tgz", + "dependencies": { + "punycode": { + "version": "1.3.2", + "from": "punycode@>=0.2.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz" + } + } + }, + "http-signature": { + "version": "0.10.1", + "from": "http-signature@~0.10.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", + "dependencies": { + "assert-plus": { + "version": "0.1.5", + "from": "assert-plus@^0.1.5", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz" + }, + "asn1": { + "version": "0.1.11", + "from": "asn1@0.1.11", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz" + }, + "ctype": { + "version": "0.5.3", + "from": "ctype@0.5.3", + "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz" + } + } + }, + "oauth-sign": { + "version": "0.5.0", + "from": "oauth-sign@~0.5.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.5.0.tgz" + }, + "hawk": { + "version": "1.1.1", + "from": "hawk@1.1.1", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz", + "dependencies": { + "hoek": { + "version": "0.9.1", + "from": "hoek@0.9.x", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz" + }, + "boom": { + "version": "0.4.2", + "from": "boom@0.4.x", + "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz" + }, + "cryptiles": { + "version": "0.2.2", + "from": "cryptiles@0.2.x", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz" + }, + "sntp": { + "version": "0.2.4", + "from": "sntp@0.2.x", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz" + } + } + }, + "aws-sign2": { + "version": "0.5.0", + "from": "aws-sign2@~0.5.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz" + }, + "stringstream": { + "version": "0.0.4", + "from": "stringstream@~0.0.4", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.4.tgz" + }, + "combined-stream": { + "version": "0.0.7", + "from": "combined-stream@~0.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "dependencies": { + "delayed-stream": { + "version": "0.0.5", + "from": "delayed-stream@0.0.5", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz" + } + } + } + } + }, + "abaculus": { + "version": "1.1.0", + "from": "https://github.com/CartoDB/abaculus/tarball/cdb-stats", + "resolved": "https://github.com/CartoDB/abaculus/tarball/cdb-stats" + }, + "sphericalmercator": { + "version": "1.0.2", + "from": "sphericalmercator@1.0.2", + "resolved": "https://registry.npmjs.org/sphericalmercator/-/sphericalmercator-1.0.2.tgz" + }, + "node-statsd": { + "version": "0.0.7", + "from": "node-statsd@~0.0.7", + "resolved": "https://registry.npmjs.org/node-statsd/-/node-statsd-0.0.7.tgz" + } + } + } + } +} diff --git a/package.json b/package.json index da3344c3..56b9a067 100644 --- a/package.json +++ b/package.json @@ -24,11 +24,11 @@ "dependencies": { "underscore" : "~1.6.0", "dot": "~1.0.2", - "windshaft": "https://github.com/CartoDB/Windshaft/tarball/master", + "windshaft": "https://github.com/CartoDB/Windshaft/tarball/render-limits", "step": "~0.0.5", "queue-async": "~1.0.7", "request": "~2.9.203", - "cartodb-redis": "~0.11.0", + "cartodb-redis": "~0.12.0", "cartodb-psql": "~0.4.0", "redis-mpool": "~0.3.0", "lzma": "~1.3.7", From b8395010a33426f2b0edf77b5f9de7545d7fb93d Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Wed, 1 Apr 2015 17:39:02 +0200 Subject: [PATCH 04/17] Adds some tests for limits based on user limits --- .jshintrc | 2 + test/acceptance/limits.js | 150 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 152 insertions(+) create mode 100644 test/acceptance/limits.js diff --git a/.jshintrc b/.jshintrc index 4aedb3cf..f03eef65 100644 --- a/.jshintrc +++ b/.jshintrc @@ -87,6 +87,8 @@ "describe": true, "before": true, "after": true, + "beforeEach": true, + "afterEach": true, "it": true, "suite": true, "suiteSetup": true, diff --git a/test/acceptance/limits.js b/test/acceptance/limits.js new file mode 100644 index 00000000..be6c46ee --- /dev/null +++ b/test/acceptance/limits.js @@ -0,0 +1,150 @@ +require('../support/test_helper'); + +var assert = require('../support/assert'); +var _ = require('underscore'); +var redis = require('redis'); + +var CartodbWindshaft = require('../../lib/cartodb/cartodb_windshaft'); +var serverOptions = require('../../lib/cartodb/server_options')(); +var server = new CartodbWindshaft(serverOptions); +server.setMaxListeners(0); + +describe('render limits', function() { + + var layergroupUrl = '/api/v1/map'; + + var redisClient = redis.createClient(global.environment.redis.port); + after(function(done) { + redisClient.keys("map_style|*", function(err, matches) { + redisClient.del(matches, function() { + done(); + }); + }); + }); + + var keysToDelete = []; + afterEach(function(done) { + redisClient.DEL(keysToDelete, function() { + keysToDelete = []; + done(); + }); + }); + + var user = 'localhost'; + + var pointSleepSql = "SELECT pg_sleep(1)," + + " 'SRID=3857;POINT(0 0)'::geometry the_geom_webmercator, 1 cartodb_id"; + var pointCartoCss = '#layer { marker-fill:red; }'; + var polygonSleepSql = "SELECT pg_sleep(1)," + + " ST_Buffer('SRID=3857;POINT(0 0)'::geometry, 100000000) the_geom_webmercator, 1 cartodb_id"; + var polygonCartoCss = '#layer { polygon-fill:red; }'; + + function singleLayergroupConfig(sql, cartocss) { + return { + version: '1.0.0', + layers: [ + { + type: 'mapnik', + options: { + sql: sql, + cartocss: cartocss, + cartocss_version: '2.0.1' + } + } + ] + }; + } + + function createRequest(layergroup, userHost) { + return { + url: layergroupUrl, + method: 'POST', + headers: { + host: userHost, + 'Content-Type': 'application/json' + }, + data: JSON.stringify(layergroup) + }; + } + + function withRenderLimit(user, renderLimit, callback) { + redisClient.SELECT(5, function(err) { + if (err) { + return callback(err); + } + var userLimitsKey = 'limits:tiler:' + user; + redisClient.HSET(userLimitsKey, 'render', renderLimit, function(err) { + if (err) { + return callback(err); + } + keysToDelete.push(userLimitsKey); + return callback(); + }); + }); + + } + + it("layergroup creation fails if test tile is slow", function(done) { + withRenderLimit(user, 50, function(err) { + if (err) { + return done(err); + } + + var layergroup = singleLayergroupConfig(polygonSleepSql, polygonCartoCss); + assert.response(server, + createRequest(layergroup, user), + { + status: 400 + }, + function(res) { + var parsed = JSON.parse(res.body); + assert.deepEqual(parsed, { errors: [ 'Render timed out' ] }); + done(); + } + ); + }); + }); + + it("layergroup creation works if test tile is fast but tile request fails if they are slow", function(done) { + withRenderLimit(user, 50, function(err) { + if (err) { + return done(err); + } + + var layergroup = singleLayergroupConfig(pointSleepSql, pointCartoCss); + assert.response(server, + createRequest(layergroup, user), + { + status: 200 + }, + function(res) { + assert.response(server, + { + url: layergroupUrl + _.template('/<%= layergroupId %>/<%= z %>/<%= x %>/<%= y %>.png', { + layergroupId: JSON.parse(res.body).layergroupid, + z: 0, + x: 0, + y: 0 + }), + method: 'GET', + headers: { + host: 'localhost' + }, + encoding: 'binary' + }, + { + status: 400 + }, + function(res) { + var parsed = JSON.parse(res.body); + assert.deepEqual(parsed, { error: 'Render timed out' }); + done(); + } + ); + + } + ); + }); + }); + +}); From 38e4812b437e87f4e8f26111deb8ccc7864dd0ac Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Wed, 1 Apr 2015 19:35:55 +0200 Subject: [PATCH 05/17] Restore previous beforeLayergroupCreate hook behaviour Adds new rendercache's beforeRendererCreate hook --- lib/cartodb/server_options.js | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/lib/cartodb/server_options.js b/lib/cartodb/server_options.js index d8398809..92b4db39 100644 --- a/lib/cartodb/server_options.js +++ b/lib/cartodb/server_options.js @@ -242,28 +242,19 @@ module.exports = function(redisPool) { }); }; - me.beforeLayergroupCreate = function(req, requestMapConfig, callback) { + me.renderCache.beforeRendererCreate = function(req, callback) { var user = cdbRequest.userByReq(req); - var namedLayersDatasource; + + var rendererOptions = {}; + step( - function extractNamedLayers() { - mapConfigNamedLayersAdapter.getLayers(user, requestMapConfig.layers, pgConnection, this); - }, - function handleNamedLayers(err, layers, datasource) { - assert.ifError(err); - - namedLayersDatasource = datasource; - requestMapConfig.layers = layers; - - return null; - }, function getLimits(err) { assert.ifError(err); cartoData.getTilerRenderLimit(user, this); }, function handleTilerLimits(err, renderLimit) { assert.ifError(err); - req.context.limits = { + rendererOptions.limits = { render: renderLimit }; return null; @@ -273,7 +264,20 @@ module.exports = function(redisPool) { return callback(err); } - return callback(null, requestMapConfig, namedLayersDatasource); + return callback(null, rendererOptions); + } + ); + }; + + me.beforeLayergroupCreate = function(req, requestMapConfig, callback) { + mapConfigNamedLayersAdapter.getLayers(cdbRequest.userByReq(req), requestMapConfig.layers, pgConnection, + function(err, layers, datasource) { + if (err) { + return callback(err); + } + + requestMapConfig.layers = layers; + return callback(null, requestMapConfig, datasource); } ); }; From bf7044d7231f027f4bc4409b1b1a385e019708bb Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Wed, 1 Apr 2015 19:36:43 +0200 Subject: [PATCH 06/17] Adds tests to test new per user limit --- test/acceptance/limits.js | 79 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 74 insertions(+), 5 deletions(-) diff --git a/test/acceptance/limits.js b/test/acceptance/limits.js index be6c46ee..98273b47 100644 --- a/test/acceptance/limits.js +++ b/test/acceptance/limits.js @@ -5,9 +5,7 @@ var _ = require('underscore'); var redis = require('redis'); var CartodbWindshaft = require('../../lib/cartodb/cartodb_windshaft'); -var serverOptions = require('../../lib/cartodb/server_options')(); -var server = new CartodbWindshaft(serverOptions); -server.setMaxListeners(0); +var serverOptions = require('../../lib/cartodb/server_options'); describe('render limits', function() { @@ -22,6 +20,12 @@ describe('render limits', function() { }); }); + var server; + beforeEach(function() { + server = new CartodbWindshaft(serverOptions()); + server.setMaxListeners(0); + }); + var keysToDelete = []; afterEach(function(done) { redisClient.DEL(keysToDelete, function() { @@ -32,10 +36,10 @@ describe('render limits', function() { var user = 'localhost'; - var pointSleepSql = "SELECT pg_sleep(1)," + + var pointSleepSql = "SELECT pg_sleep(0.5)," + " 'SRID=3857;POINT(0 0)'::geometry the_geom_webmercator, 1 cartodb_id"; var pointCartoCss = '#layer { marker-fill:red; }'; - var polygonSleepSql = "SELECT pg_sleep(1)," + + var polygonSleepSql = "SELECT pg_sleep(0.5)," + " ST_Buffer('SRID=3857;POINT(0 0)'::geometry, 100000000) the_geom_webmercator, 1 cartodb_id"; var polygonCartoCss = '#layer { polygon-fill:red; }'; @@ -105,6 +109,28 @@ describe('render limits', function() { }); }); + it("layergroup creation does not fail if user limit is high enough even if test tile is slow", function(done) { + withRenderLimit(user, 5000, function(err) { + if (err) { + return done(err); + } + + var layergroup = singleLayergroupConfig(polygonSleepSql, polygonCartoCss); + assert.response(server, + createRequest(layergroup, user), + { + status: 200 + }, + function(res) { + var parsed = JSON.parse(res.body); + assert.ok(parsed.layergroupid); + done(); + } + ); + }); + }); + + it("layergroup creation works if test tile is fast but tile request fails if they are slow", function(done) { withRenderLimit(user, 50, function(err) { if (err) { @@ -147,4 +173,47 @@ describe('render limits', function() { }); }); + it("tile request does not fail if user limit is high enough", function(done) { + withRenderLimit(user, 5000, function(err) { + if (err) { + return done(err); + } + + var layergroup = singleLayergroupConfig(pointSleepSql, pointCartoCss); + assert.response(server, + createRequest(layergroup, user), + { + status: 200 + }, + function(res) { + assert.response(server, + { + url: layergroupUrl + _.template('/<%= layergroupId %>/<%= z %>/<%= x %>/<%= y %>.png', { + layergroupId: JSON.parse(res.body).layergroupid, + z: 0, + x: 0, + y: 0 + }), + method: 'GET', + headers: { + host: 'localhost' + }, + encoding: 'binary' + }, + { + status: 200, + headers: { + 'Content-Type': 'image/png' + } + }, + function(res, err) { + done(err); + } + ); + + } + ); + }); + }); + }); From 091352e75bbba89cdbfba24145da1967a9d5d995 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 6 Apr 2015 18:00:46 +0200 Subject: [PATCH 07/17] Fix typo --- config/environments/development.js.example | 2 +- config/environments/production.js.example | 2 +- config/environments/staging.js.example | 2 +- config/environments/test.js.example | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/config/environments/development.js.example b/config/environments/development.js.example index 2fed947d..92a31731 100644 --- a/config/environments/development.js.example +++ b/config/environments/development.js.example @@ -109,7 +109,7 @@ var config = { // Snapping all points of the geometry to a regular grid snapToGrid: false, - // SQL queries will be wrapeed with ST_ClipByBox2D + // SQL queries will be wrapped with ST_ClipByBox2D // Returning the portion of a geometry falling within a rectangle // It will only work if snapToGrid is enabled clipByBox2d: false, // this requires postgis >=2.2 and geos >=3.5 diff --git a/config/environments/production.js.example b/config/environments/production.js.example index 3adc127e..db1e06cb 100644 --- a/config/environments/production.js.example +++ b/config/environments/production.js.example @@ -103,7 +103,7 @@ var config = { // Snapping all points of the geometry to a regular grid snapToGrid: false, - // SQL queries will be wrapeed with ST_ClipByBox2D + // SQL queries will be wrapped with ST_ClipByBox2D // Returning the portion of a geometry falling within a rectangle // It will only work if snapToGrid is enabled clipByBox2d: false, // this requires postgis >=2.2 and geos >=3.5 diff --git a/config/environments/staging.js.example b/config/environments/staging.js.example index 4c5fef84..668f85d7 100644 --- a/config/environments/staging.js.example +++ b/config/environments/staging.js.example @@ -103,7 +103,7 @@ var config = { // Snapping all points of the geometry to a regular grid snapToGrid: false, - // SQL queries will be wrapeed with ST_ClipByBox2D + // SQL queries will be wrapped with ST_ClipByBox2D // Returning the portion of a geometry falling within a rectangle // It will only work if snapToGrid is enabled clipByBox2d: false, // this requires postgis >=2.2 and geos >=3.5 diff --git a/config/environments/test.js.example b/config/environments/test.js.example index 49527c4e..1fb77ca1 100644 --- a/config/environments/test.js.example +++ b/config/environments/test.js.example @@ -103,7 +103,7 @@ var config = { // Snapping all points of the geometry to a regular grid snapToGrid: false, - // SQL queries will be wrapeed with ST_ClipByBox2D + // SQL queries will be wrapped with ST_ClipByBox2D // Returning the portion of a geometry falling within a rectangle // It will only work if snapToGrid is enabled clipByBox2d: false, // this requires postgis >=2.2 and geos >=3.5 From e3c6569302d01fe8594a04ec1c056c11f223faab Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 6 Apr 2015 18:43:40 +0200 Subject: [PATCH 08/17] Adds an onTileErrorStrategy that intercepts error timeout - returns an fallback image without error --- assets/render-timeout-fallback.png | Bin 0 -> 10177 bytes config/environments/development.js.example | 2 ++ config/environments/production.js.example | 2 ++ config/environments/staging.js.example | 2 ++ config/environments/test.js.example | 2 ++ lib/cartodb/server_options.js | 14 ++++++++++++++ 6 files changed, 22 insertions(+) create mode 100644 assets/render-timeout-fallback.png diff --git a/assets/render-timeout-fallback.png b/assets/render-timeout-fallback.png new file mode 100644 index 0000000000000000000000000000000000000000..f80cdbf89aa661983aa198950fd2659e9440d793 GIT binary patch literal 10177 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 T(ii&~6;M-trd0gM% Date: Mon, 6 Apr 2015 18:44:57 +0200 Subject: [PATCH 09/17] Tests for both: onTileErrorStrategy enabled and disabled --- test/acceptance/limits.js | 314 ++++++++++++++-------- test/fixtures/render-timeout-fallback.png | Bin 0 -> 10177 bytes 2 files changed, 201 insertions(+), 113 deletions(-) create mode 100644 test/fixtures/render-timeout-fallback.png diff --git a/test/acceptance/limits.js b/test/acceptance/limits.js index 98273b47..fbe37186 100644 --- a/test/acceptance/limits.js +++ b/test/acceptance/limits.js @@ -88,132 +88,220 @@ describe('render limits', function() { } - it("layergroup creation fails if test tile is slow", function(done) { - withRenderLimit(user, 50, function(err) { - if (err) { - return done(err); - } - - var layergroup = singleLayergroupConfig(polygonSleepSql, polygonCartoCss); - assert.response(server, - createRequest(layergroup, user), - { - status: 400 - }, - function(res) { - var parsed = JSON.parse(res.body); - assert.deepEqual(parsed, { errors: [ 'Render timed out' ] }); - done(); - } - ); + describe('with onTileErrorStrategy DISABLED', function() { + var onTileErrorStrategyEnabled; + before(function() { + onTileErrorStrategyEnabled = global.environment.enabledFeatures.onTileErrorStrategy; + global.environment.enabledFeatures.onTileErrorStrategy = false; }); - }); - it("layergroup creation does not fail if user limit is high enough even if test tile is slow", function(done) { - withRenderLimit(user, 5000, function(err) { - if (err) { - return done(err); - } + after(function() { + global.environment.enabledFeatures.onTileErrorStrategy = onTileErrorStrategyEnabled; + }); - var layergroup = singleLayergroupConfig(polygonSleepSql, polygonCartoCss); - assert.response(server, - createRequest(layergroup, user), - { - status: 200 - }, - function(res) { - var parsed = JSON.parse(res.body); - assert.ok(parsed.layergroupid); - done(); + it("layergroup creation fails if test tile is slow", function(done) { + withRenderLimit(user, 50, function(err) { + if (err) { + return done(err); } - ); + + var layergroup = singleLayergroupConfig(polygonSleepSql, polygonCartoCss); + assert.response(server, + createRequest(layergroup, user), + { + status: 400 + }, + function(res) { + var parsed = JSON.parse(res.body); + assert.deepEqual(parsed, { errors: [ 'Render timed out' ] }); + done(); + } + ); + }); + }); + + it("layergroup creation does not fail if user limit is high enough even if test tile is slow", function(done) { + withRenderLimit(user, 5000, function(err) { + if (err) { + return done(err); + } + + var layergroup = singleLayergroupConfig(polygonSleepSql, polygonCartoCss); + assert.response(server, + createRequest(layergroup, user), + { + status: 200 + }, + function(res) { + var parsed = JSON.parse(res.body); + assert.ok(parsed.layergroupid); + done(); + } + ); + }); }); - }); - it("layergroup creation works if test tile is fast but tile request fails if they are slow", function(done) { - withRenderLimit(user, 50, function(err) { - if (err) { - return done(err); - } + it("layergroup creation works if test tile is fast but tile request fails if they are slow", function(done) { + withRenderLimit(user, 50, function(err) { + if (err) { + return done(err); + } - var layergroup = singleLayergroupConfig(pointSleepSql, pointCartoCss); - assert.response(server, - createRequest(layergroup, user), - { - status: 200 - }, - function(res) { - assert.response(server, - { - url: layergroupUrl + _.template('/<%= layergroupId %>/<%= z %>/<%= x %>/<%= y %>.png', { - layergroupId: JSON.parse(res.body).layergroupid, - z: 0, - x: 0, - y: 0 - }), - method: 'GET', - headers: { - host: 'localhost' + var layergroup = singleLayergroupConfig(pointSleepSql, pointCartoCss); + assert.response(server, + createRequest(layergroup, user), + { + status: 200 + }, + function(res) { + assert.response(server, + { + url: layergroupUrl + _.template('/<%= layergroupId %>/<%= z %>/<%= x %>/<%= y %>.png', { + layergroupId: JSON.parse(res.body).layergroupid, + z: 0, + x: 0, + y: 0 + }), + method: 'GET', + headers: { + host: 'localhost' + }, + encoding: 'binary' }, - encoding: 'binary' - }, - { - status: 400 - }, - function(res) { - var parsed = JSON.parse(res.body); - assert.deepEqual(parsed, { error: 'Render timed out' }); - done(); - } - ); - - } - ); - }); - }); - - it("tile request does not fail if user limit is high enough", function(done) { - withRenderLimit(user, 5000, function(err) { - if (err) { - return done(err); - } - - var layergroup = singleLayergroupConfig(pointSleepSql, pointCartoCss); - assert.response(server, - createRequest(layergroup, user), - { - status: 200 - }, - function(res) { - assert.response(server, - { - url: layergroupUrl + _.template('/<%= layergroupId %>/<%= z %>/<%= x %>/<%= y %>.png', { - layergroupId: JSON.parse(res.body).layergroupid, - z: 0, - x: 0, - y: 0 - }), - method: 'GET', - headers: { - host: 'localhost' + { + status: 400 }, - encoding: 'binary' - }, - { - status: 200, - headers: { - 'Content-Type': 'image/png' + function(res) { + var parsed = JSON.parse(res.body); + assert.deepEqual(parsed, { error: 'Render timed out' }); + done(); } - }, - function(res, err) { - done(err); - } - ); + ); - } - ); + } + ); + }); }); + + it("tile request does not fail if user limit is high enough", function(done) { + withRenderLimit(user, 5000, function(err) { + if (err) { + return done(err); + } + + var layergroup = singleLayergroupConfig(pointSleepSql, pointCartoCss); + assert.response(server, + createRequest(layergroup, user), + { + status: 200 + }, + function(res) { + assert.response(server, + { + url: layergroupUrl + _.template('/<%= layergroupId %>/<%= z %>/<%= x %>/<%= y %>.png', { + layergroupId: JSON.parse(res.body).layergroupid, + z: 0, + x: 0, + y: 0 + }), + method: 'GET', + headers: { + host: 'localhost' + }, + encoding: 'binary' + }, + { + status: 200, + headers: { + 'Content-Type': 'image/png' + } + }, + function(res, err) { + done(err); + } + ); + + } + ); + }); + }); + + }); + + describe('with onTileErrorStrategy', function() { + + it("layergroup creation works even if test tile is slow", function(done) { + withRenderLimit(user, 50, function(err) { + if (err) { + return done(err); + } + + var layergroup = singleLayergroupConfig(polygonSleepSql, polygonCartoCss); + assert.response(server, + createRequest(layergroup, user), + { + status: 200 + }, + function(res) { + var parsed = JSON.parse(res.body); + assert.ok(parsed.layergroupid); + done(); + } + ); + }); + }); + + it("layergroup creation and tile requests works even if they are slow but returns fallback", function(done) { + withRenderLimit(user, 50, function(err) { + if (err) { + return done(err); + } + + var layergroup = singleLayergroupConfig(pointSleepSql, pointCartoCss); + assert.response(server, + createRequest(layergroup, user), + { + status: 200 + }, + function(res) { + assert.response(server, + { + url: layergroupUrl + _.template('/<%= layergroupId %>/<%= z %>/<%= x %>/<%= y %>.png', { + layergroupId: JSON.parse(res.body).layergroupid, + z: 0, + x: 0, + y: 0 + }), + method: 'GET', + headers: { + host: 'localhost' + }, + encoding: 'binary' + }, + { + status: 200, + headers: { + 'Content-Type': 'image/png' + } + }, + function(res, err) { + if (err) { + done(err); + } + assert.imageEqualsFile(res.body, './test/fixtures/render-timeout-fallback.png', 25, + function(imgErr/*, similarity*/) { + done(imgErr); + } + ); + } + ); + + } + ); + }); + }); + }); }); diff --git a/test/fixtures/render-timeout-fallback.png b/test/fixtures/render-timeout-fallback.png new file mode 100644 index 0000000000000000000000000000000000000000..f80cdbf89aa661983aa198950fd2659e9440d793 GIT binary patch literal 10177 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 T(ii&~6;M-trd0gM% Date: Mon, 6 Apr 2015 18:52:54 +0200 Subject: [PATCH 10/17] Adds a feature flag to cache timed out tile requests: cacheOnTimeout --- config/environments/development.js.example | 3 +++ config/environments/production.js.example | 3 +++ config/environments/staging.js.example | 3 +++ config/environments/test.js.example | 3 +++ lib/cartodb/server_options.js | 1 + 5 files changed, 13 insertions(+) diff --git a/config/environments/development.js.example b/config/environments/development.js.example index 398564d7..5403256d 100644 --- a/config/environments/development.js.example +++ b/config/environments/development.js.example @@ -196,6 +196,9 @@ var config = { // Use this as a feature flags enabling/disabling mechanism ,enabledFeatures: { + // whether a timed out render request should be cached in memory after is computed or not + // beware keeping it will grow up the memory usage + cacheOnTimeout: false, // whether it should intercept tile render errors an act based on them, enabled by default. onTileErrorStrategy: true, // whether the affected tables for a given SQL must query directly postgresql or use the SQL API diff --git a/config/environments/production.js.example b/config/environments/production.js.example index 7fbc6eb2..1c0ba3a7 100644 --- a/config/environments/production.js.example +++ b/config/environments/production.js.example @@ -196,6 +196,9 @@ var config = { // Use this as a feature flags enabling/disabling mechanism ,enabledFeatures: { + // whether a timed out render request should be cached in memory after is computed or not + // beware keeping it will grow up the memory usage + cacheOnTimeout: false, // whether it should intercept tile render errors an act based on them, enabled by default. onTileErrorStrategy: true, // whether the affected tables for a given SQL must query directly postgresql or use the SQL API diff --git a/config/environments/staging.js.example b/config/environments/staging.js.example index 6ad7e5d2..7375600b 100644 --- a/config/environments/staging.js.example +++ b/config/environments/staging.js.example @@ -196,6 +196,9 @@ var config = { // Use this as a feature flags enabling/disabling mechanism ,enabledFeatures: { + // whether a timed out render request should be cached in memory after is computed or not + // beware keeping it will grow up the memory usage + cacheOnTimeout: false, // whether it should intercept tile render errors an act based on them, enabled by default. onTileErrorStrategy: true, // whether the affected tables for a given SQL must query directly postgresql or use the SQL API diff --git a/config/environments/test.js.example b/config/environments/test.js.example index 99a1647a..4f0e2227 100644 --- a/config/environments/test.js.example +++ b/config/environments/test.js.example @@ -192,6 +192,9 @@ var config = { // Use this as a feature flags enabling/disabling mechanism ,enabledFeatures: { + // whether a timed out render request should be cached in memory after is computed or not + // beware keeping it will grow up the memory usage + cacheOnTimeout: false, // whether it should intercept tile render errors an act based on them, enabled by default. onTileErrorStrategy: true, // whether the affected tables for a given SQL must query directly postgresql or use the SQL API diff --git a/lib/cartodb/server_options.js b/lib/cartodb/server_options.js index ee0cb6ea..a91e03e0 100644 --- a/lib/cartodb/server_options.js +++ b/lib/cartodb/server_options.js @@ -269,6 +269,7 @@ module.exports = function(redisPool) { function handleTilerLimits(err, renderLimit) { assert.ifError(err); rendererOptions.limits = { + cacheOnTimeout: global.environment.enabledFeatures.cacheOnTimeout || false, render: renderLimit }; return null; From 775b2b75a6d9852e85b2547d3666ee0cc2eab51e Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Tue, 7 Apr 2015 10:41:19 +0200 Subject: [PATCH 11/17] Fix typo --- config/environments/development.js.example | 2 +- config/environments/production.js.example | 2 +- config/environments/staging.js.example | 2 +- config/environments/test.js.example | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/config/environments/development.js.example b/config/environments/development.js.example index 5403256d..eca061b5 100644 --- a/config/environments/development.js.example +++ b/config/environments/development.js.example @@ -117,7 +117,7 @@ var config = { limits: { // Time in milliseconds a render request can take before it fails, some notes: // - 0 means no render limit - // - it considers metatiling, it naive implementation: (render timeout) * (number of tiles in metatile) + // - it considers metatiling, naive implementation: (render timeout) * (number of tiles in metatile) render: 0, // As the render request will finish even if timed out, whether it should be placed in the internal // cache or it should be fully discarded. When placed in the internal cache another attempt to retrieve diff --git a/config/environments/production.js.example b/config/environments/production.js.example index 1c0ba3a7..7cecf67f 100644 --- a/config/environments/production.js.example +++ b/config/environments/production.js.example @@ -111,7 +111,7 @@ var config = { limits: { // Time in milliseconds a render request can take before it fails, some notes: // - 0 means no render limit - // - it considers metatiling, it naive implementation: (render timeout) * (number of tiles in metatile) + // - it considers metatiling, naive implementation: (render timeout) * (number of tiles in metatile) render: 0, // As the render request will finish even if timed out, whether it should be placed in the internal // cache or it should be fully discarded. When placed in the internal cache another attempt to retrieve diff --git a/config/environments/staging.js.example b/config/environments/staging.js.example index 7375600b..32e1c581 100644 --- a/config/environments/staging.js.example +++ b/config/environments/staging.js.example @@ -111,7 +111,7 @@ var config = { limits: { // Time in milliseconds a render request can take before it fails, some notes: // - 0 means no render limit - // - it considers metatiling, it naive implementation: (render timeout) * (number of tiles in metatile) + // - it considers metatiling, naive implementation: (render timeout) * (number of tiles in metatile) render: 0, // As the render request will finish even if timed out, whether it should be placed in the internal // cache or it should be fully discarded. When placed in the internal cache another attempt to retrieve diff --git a/config/environments/test.js.example b/config/environments/test.js.example index 4f0e2227..80f2c6b5 100644 --- a/config/environments/test.js.example +++ b/config/environments/test.js.example @@ -111,7 +111,7 @@ var config = { limits: { // Time in milliseconds a render request can take before it fails, some notes: // - 0 means no render limit - // - it considers metatiling, it naive implementation: (render timeout) * (number of tiles in metatile) + // - it considers metatiling, naive implementation: (render timeout) * (number of tiles in metatile) render: 0, // As the render request will finish even if timed out, whether it should be placed in the internal // cache or it should be fully discarded. When placed in the internal cache another attempt to retrieve From 2ea880ce2cdb192f9d91d8902d4c70b312798a00 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Tue, 7 Apr 2015 11:09:35 +0200 Subject: [PATCH 12/17] cacheOnTimeout only for mapnik renderer it does not make sense to have that as a general feature --- config/environments/development.js.example | 3 --- config/environments/production.js.example | 3 --- config/environments/staging.js.example | 3 --- config/environments/test.js.example | 3 --- 4 files changed, 12 deletions(-) diff --git a/config/environments/development.js.example b/config/environments/development.js.example index eca061b5..7b7866b1 100644 --- a/config/environments/development.js.example +++ b/config/environments/development.js.example @@ -196,9 +196,6 @@ var config = { // Use this as a feature flags enabling/disabling mechanism ,enabledFeatures: { - // whether a timed out render request should be cached in memory after is computed or not - // beware keeping it will grow up the memory usage - cacheOnTimeout: false, // whether it should intercept tile render errors an act based on them, enabled by default. onTileErrorStrategy: true, // whether the affected tables for a given SQL must query directly postgresql or use the SQL API diff --git a/config/environments/production.js.example b/config/environments/production.js.example index 7cecf67f..72fae68b 100644 --- a/config/environments/production.js.example +++ b/config/environments/production.js.example @@ -196,9 +196,6 @@ var config = { // Use this as a feature flags enabling/disabling mechanism ,enabledFeatures: { - // whether a timed out render request should be cached in memory after is computed or not - // beware keeping it will grow up the memory usage - cacheOnTimeout: false, // whether it should intercept tile render errors an act based on them, enabled by default. onTileErrorStrategy: true, // whether the affected tables for a given SQL must query directly postgresql or use the SQL API diff --git a/config/environments/staging.js.example b/config/environments/staging.js.example index 32e1c581..242890f6 100644 --- a/config/environments/staging.js.example +++ b/config/environments/staging.js.example @@ -196,9 +196,6 @@ var config = { // Use this as a feature flags enabling/disabling mechanism ,enabledFeatures: { - // whether a timed out render request should be cached in memory after is computed or not - // beware keeping it will grow up the memory usage - cacheOnTimeout: false, // whether it should intercept tile render errors an act based on them, enabled by default. onTileErrorStrategy: true, // whether the affected tables for a given SQL must query directly postgresql or use the SQL API diff --git a/config/environments/test.js.example b/config/environments/test.js.example index 80f2c6b5..de03dc7f 100644 --- a/config/environments/test.js.example +++ b/config/environments/test.js.example @@ -192,9 +192,6 @@ var config = { // Use this as a feature flags enabling/disabling mechanism ,enabledFeatures: { - // whether a timed out render request should be cached in memory after is computed or not - // beware keeping it will grow up the memory usage - cacheOnTimeout: false, // whether it should intercept tile render errors an act based on them, enabled by default. onTileErrorStrategy: true, // whether the affected tables for a given SQL must query directly postgresql or use the SQL API From 1782f240ce991f2794fec525dda3106f84932bc0 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Tue, 7 Apr 2015 11:38:00 +0200 Subject: [PATCH 13/17] Upgrade cartodb-redis package --- npm-shrinkwrap.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 09405e16..46eb1305 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -27,8 +27,8 @@ } }, "cartodb-redis": { - "version": "0.12.0", - "from": "cartodb-redis@~0.12.0", + "version": "0.12.1", + "from": "cartodb-redis@~0.12.1", "dependencies": { "redis-mpool": { "version": "0.1.0", @@ -1732,7 +1732,7 @@ }, "mime": { "version": "1.2.11", - "from": "mime@~1.2.11", + "from": "mime@~1.2.9", "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" } } diff --git a/package.json b/package.json index 56b9a067..08a2e01f 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "step": "~0.0.5", "queue-async": "~1.0.7", "request": "~2.9.203", - "cartodb-redis": "~0.12.0", + "cartodb-redis": "~0.12.1", "cartodb-psql": "~0.4.0", "redis-mpool": "~0.3.0", "lzma": "~1.3.7", From 2eb7529efbe85471ae98c4d5e396c8a4f95a2f59 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Tue, 7 Apr 2015 12:52:33 +0200 Subject: [PATCH 14/17] Pick cacheOnTimeout and render limit from mapnik config - adds default mapnik configuration values - removes old top-level mapnik config, rely on renderer one --- lib/cartodb/server_options.js | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/lib/cartodb/server_options.js b/lib/cartodb/server_options.js index a91e03e0..188ba578 100644 --- a/lib/cartodb/server_options.js +++ b/lib/cartodb/server_options.js @@ -33,9 +33,16 @@ module.exports = function(redisPool) { var rendererConfig = _.defaults(global.environment.renderer || {}, { cache_ttl: 60000, // milliseconds - metatile: 4, - bufferSize: 64, - statsInterval: 60000 + statsInterval: 60000, + mapnik: { + poolSize: 8, + metatile: 2, + bufferSize: 64, + snapToGrid: false, + clipByBox2d: false, + limits: {} + }, + http: {} }); var me = { @@ -63,11 +70,6 @@ module.exports = function(redisPool) { mapnik_tile_format: global.environment.mapnik_tile_format || 'png', default_layergroup_ttl: global.environment.mapConfigTTL || 7200 }, - mapnik: { - poolSize: rendererConfig.poolSize, - metatile: rendererConfig.metatile, - bufferSize: rendererConfig.bufferSize - }, statsd: global.environment.statsd, renderCache: { ttl: rendererConfig.cache_ttl, @@ -269,8 +271,8 @@ module.exports = function(redisPool) { function handleTilerLimits(err, renderLimit) { assert.ifError(err); rendererOptions.limits = { - cacheOnTimeout: global.environment.enabledFeatures.cacheOnTimeout || false, - render: renderLimit + cacheOnTimeout: rendererConfig.mapnik.limits.cacheOnTimeout || false, + render: renderLimit || rendererConfig.mapnik.limits.render || 0 }; return null; }, From 907ed478cff21ddb0d8ac83987e129d24b2b94f1 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Tue, 7 Apr 2015 13:00:20 +0200 Subject: [PATCH 15/17] Tidy app.js --- Makefile | 2 +- app.js | 45 ++++++++++++++++++++++++--------------------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/Makefile b/Makefile index 11899d75..2bd19912 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,7 @@ test: config/environments/test.js jshint: @echo "***jshint***" - @./node_modules/.bin/jshint lib/ + @./node_modules/.bin/jshint lib/ app.js test-all: jshint test diff --git a/app.js b/app.js index 539043e9..19361566 100755 --- a/app.js +++ b/app.js @@ -7,17 +7,21 @@ * environments: [development, production] */ -var path = require('path'), - fs = require('fs'), - RedisPool = require('redis-mpool') -; +var path = require('path'); +var fs = require('fs'); +var RedisPool = require('redis-mpool'); +var _ = require('underscore'); +var ENV; +if ( process.argv[2] ) { + ENV = process.argv[2]; +} else if ( process.env.NODE_ENV ) { + ENV = process.env.NODE_ENV; +} else { + ENV = 'development'; +} -if ( process.argv[2] ) ENV = process.argv[2]; -else if ( process.env['NODE_ENV'] ) ENV = process.env['NODE_ENV']; -else ENV = 'development'; - -process.env['NODE_ENV'] = ENV; +process.env.NODE_ENV = ENV; // sanity check if (ENV != 'development' && ENV != 'production' && ENV != 'staging' ){ @@ -26,14 +30,12 @@ if (ENV != 'development' && ENV != 'production' && ENV != 'staging' ){ process.exit(1); } -var _ = require('underscore'); - // set environment specific variables global.environment = require(__dirname + '/config/environments/' + ENV); global.environment.api_hostname = require('os').hostname().split('.')[0]; global.log4js = require('log4js'); -log4js_config = { +var log4js_config = { appenders: [], replaceConsole:true }; @@ -60,18 +62,18 @@ if ( global.environment.log_filename ) { ); } -log4js.configure(log4js_config, { cwd: __dirname }); -global.logger = log4js.getLogger(); +global.log4js.configure(log4js_config, { cwd: __dirname }); +global.logger = global.log4js.getLogger(); var redisOpts = _.extend(global.environment.redis, { name: 'windshaft' }), redisPool = new RedisPool(redisOpts); // Include cartodb_windshaft only _after_ the "global" variable is set // See https://github.com/Vizzuality/Windshaft-cartodb/issues/28 -var CartodbWindshaft = require('./lib/cartodb/cartodb_windshaft'), +var cartodbWindshaft = require('./lib/cartodb/cartodb_windshaft'), serverOptions = require('./lib/cartodb/server_options')(redisPool); -ws = CartodbWindshaft(serverOptions); +var ws = cartodbWindshaft(serverOptions); if (global.statsClient) { redisPool.on('status', function(status) { @@ -93,19 +95,20 @@ ws.listen(global.environment.port, global.environment.host); var version = require("./package").version; ws.on('listening', function() { - console.log("Windshaft tileserver " + version + " started on " - + global.environment.host + ':' + global.environment.port - + " (" + ENV + ")"); + console.log( + "Windshaft tileserver %s started on %s:%s (%s)", + version, global.environment.host, global.environment.port, ENV + ); }); process.on('SIGHUP', function() { global.log4js.clearAndShutdownAppenders(function() { global.log4js.configure(log4js_config); - global.logger = log4js.getLogger(); + global.logger = global.log4js.getLogger(); console.log('Log files reloaded'); }); }); process.on('uncaughtException', function(err) { - logger.error('Uncaught exception: ' + err.stack); + global.logger.error('Uncaught exception: ' + err.stack); }); From 69c623b5b29a34cebeea7238260184515fa754d6 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Tue, 7 Apr 2015 14:36:43 +0200 Subject: [PATCH 16/17] Regenerate npm-shrinkwrap.json --- npm-shrinkwrap.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 46eb1305..2ff43176 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1722,8 +1722,8 @@ }, "tilelive-mapnik": { "version": "0.6.15", - "from": "https://github.com/CartoDB/tilelive-mapnik/tarball/cdb-limits", - "resolved": "https://github.com/CartoDB/tilelive-mapnik/tarball/cdb-limits", + "from": "https://github.com/CartoDB/tilelive-mapnik/tarball/cdb", + "resolved": "https://github.com/CartoDB/tilelive-mapnik/tarball/cdb", "dependencies": { "generic-pool": { "version": "2.1.1", @@ -2356,8 +2356,8 @@ }, "abaculus": { "version": "1.1.0", - "from": "https://github.com/CartoDB/abaculus/tarball/cdb-stats", - "resolved": "https://github.com/CartoDB/abaculus/tarball/cdb-stats" + "from": "https://github.com/CartoDB/abaculus/tarball/cdb", + "resolved": "https://github.com/CartoDB/abaculus/tarball/cdb" }, "sphericalmercator": { "version": "1.0.2", From 47cc1de89b8359abc128cf7ab986810fab8563ab Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Tue, 7 Apr 2015 17:57:21 +0200 Subject: [PATCH 17/17] Uses windshaft@0.41.0 registry version --- npm-shrinkwrap.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 2ff43176..676dd57a 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -103,7 +103,7 @@ }, "inherits": { "version": "2.0.1", - "from": "inherits@~2.0.1", + "from": "inherits@2", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } @@ -171,8 +171,8 @@ }, "windshaft": { "version": "0.41.0", - "from": "https://github.com/CartoDB/Windshaft/tarball/render-limits", - "resolved": "https://github.com/CartoDB/Windshaft/tarball/render-limits", + "from": "windshaft@0.41.0", + "resolved": "https://registry.npmjs.org/windshaft/-/windshaft-0.41.0.tgz", "dependencies": { "chronograph": { "version": "0.1.0", diff --git a/package.json b/package.json index 08a2e01f..fc6e5451 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "dependencies": { "underscore" : "~1.6.0", "dot": "~1.0.2", - "windshaft": "https://github.com/CartoDB/Windshaft/tarball/render-limits", + "windshaft": "0.41.0", "step": "~0.0.5", "queue-async": "~1.0.7", "request": "~2.9.203",