Merge branch 'master' into res-locals-user
This commit is contained in:
commit
0aaafa2068
BIN
assets/render-timeout-fallback.mvt
Normal file
BIN
assets/render-timeout-fallback.mvt
Normal file
Binary file not shown.
@ -4,6 +4,7 @@ var step = require('step');
|
|||||||
var cors = require('../middleware/cors');
|
var cors = require('../middleware/cors');
|
||||||
var userMiddleware = require('../middleware/user');
|
var userMiddleware = require('../middleware/user');
|
||||||
var allowQueryParams = require('../middleware/allow-query-params');
|
var allowQueryParams = require('../middleware/allow-query-params');
|
||||||
|
var vectorError = require('../middleware/vector-error');
|
||||||
|
|
||||||
var DataviewBackend = require('../backends/dataview');
|
var DataviewBackend = require('../backends/dataview');
|
||||||
var AnalysisStatusBackend = require('../backends/analysis-status');
|
var AnalysisStatusBackend = require('../backends/analysis-status');
|
||||||
@ -50,7 +51,8 @@ LayergroupController.prototype.register = function(app) {
|
|||||||
cors(),
|
cors(),
|
||||||
userMiddleware,
|
userMiddleware,
|
||||||
this.prepareContext,
|
this.prepareContext,
|
||||||
this.tile.bind(this)
|
this.tile.bind(this),
|
||||||
|
vectorError()
|
||||||
);
|
);
|
||||||
|
|
||||||
app.get(
|
app.get(
|
||||||
@ -58,7 +60,8 @@ LayergroupController.prototype.register = function(app) {
|
|||||||
cors(),
|
cors(),
|
||||||
userMiddleware,
|
userMiddleware,
|
||||||
this.prepareContext,
|
this.prepareContext,
|
||||||
this.tile.bind(this)
|
this.tile.bind(this),
|
||||||
|
vectorError()
|
||||||
);
|
);
|
||||||
|
|
||||||
app.get(
|
app.get(
|
||||||
@ -67,7 +70,8 @@ LayergroupController.prototype.register = function(app) {
|
|||||||
userMiddleware,
|
userMiddleware,
|
||||||
validateLayerRouteMiddleware,
|
validateLayerRouteMiddleware,
|
||||||
this.prepareContext,
|
this.prepareContext,
|
||||||
this.layer.bind(this)
|
this.layer.bind(this),
|
||||||
|
vectorError()
|
||||||
);
|
);
|
||||||
|
|
||||||
app.get(
|
app.get(
|
||||||
|
@ -6,6 +6,7 @@ var NamedMapsCacheEntry = require('../cache/model/named_maps_entry');
|
|||||||
var cors = require('../middleware/cors');
|
var cors = require('../middleware/cors');
|
||||||
var userMiddleware = require('../middleware/user');
|
var userMiddleware = require('../middleware/user');
|
||||||
var allowQueryParams = require('../middleware/allow-query-params');
|
var allowQueryParams = require('../middleware/allow-query-params');
|
||||||
|
var vectorError = require('../middleware/vector-error');
|
||||||
|
|
||||||
function NamedMapsController(prepareContext, namedMapProviderCache, tileBackend, previewBackend,
|
function NamedMapsController(prepareContext, namedMapProviderCache, tileBackend, previewBackend,
|
||||||
surrogateKeysCache, tablesExtentApi, metadataBackend) {
|
surrogateKeysCache, tablesExtentApi, metadataBackend) {
|
||||||
@ -26,7 +27,8 @@ NamedMapsController.prototype.register = function(app) {
|
|||||||
cors(),
|
cors(),
|
||||||
userMiddleware,
|
userMiddleware,
|
||||||
this.prepareContext,
|
this.prepareContext,
|
||||||
this.tile.bind(this)
|
this.tile.bind(this),
|
||||||
|
vectorError()
|
||||||
);
|
);
|
||||||
|
|
||||||
app.get(
|
app.get(
|
||||||
@ -102,6 +104,7 @@ NamedMapsController.prototype.tile = function(req, res, next) {
|
|||||||
},
|
},
|
||||||
function handleImage(err, tile, headers, stats) {
|
function handleImage(err, tile, headers, stats) {
|
||||||
req.profiler.add(stats);
|
req.profiler.add(stats);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
err.label = 'NAMED_MAP_TILE';
|
err.label = 'NAMED_MAP_TILE';
|
||||||
next(err);
|
next(err);
|
||||||
|
30
lib/cartodb/middleware/vector-error.js
Normal file
30
lib/cartodb/middleware/vector-error.js
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
const timeoutErrorVectorTile = fs.readFileSync(__dirname + '/../../../assets/render-timeout-fallback.mvt');
|
||||||
|
|
||||||
|
module.exports = function vectorError() {
|
||||||
|
return function vectorErrorMiddleware(err, req, res, next) {
|
||||||
|
if(req.params.format === 'mvt') {
|
||||||
|
|
||||||
|
if (isTimeoutError(err)) {
|
||||||
|
res.set('Content-Type', 'application/x-protobuf');
|
||||||
|
return res.status(429).send(timeoutErrorVectorTile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
next(err);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
function isRenderTimeoutError (err) {
|
||||||
|
return err.message === 'Render timed out';
|
||||||
|
}
|
||||||
|
|
||||||
|
function isDatasourceTimeoutError (err) {
|
||||||
|
return err.message && err.message.match(/canceling statement due to statement timeout/i);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isTimeoutError (err) {
|
||||||
|
return isRenderTimeoutError(err) || isDatasourceTimeoutError(err);
|
||||||
|
}
|
37
scripts/mvt-timeout-error.py
Executable file
37
scripts/mvt-timeout-error.py
Executable file
@ -0,0 +1,37 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import mapbox_vector_tile
|
||||||
|
|
||||||
|
lines_list = []
|
||||||
|
|
||||||
|
# main diagonal line
|
||||||
|
lines_list.append({ "geometry":"LINESTRING (0 0, 4096 4096)"})
|
||||||
|
|
||||||
|
# diagonal lines
|
||||||
|
for i in range(4096/32, 4096, 4096/32):
|
||||||
|
start = i
|
||||||
|
end = 4096 - i
|
||||||
|
|
||||||
|
lines_list.append({ "geometry":"LINESTRING (0 " + str(start) + ", " + str(end) + " 4096)" })
|
||||||
|
lines_list.append({ "geometry":"LINESTRING (" + str(start) + " 0, 4096 " + str(end) + ")" })
|
||||||
|
|
||||||
|
# box lines
|
||||||
|
lines_list.append({ "geometry":"LINESTRING (0 0, 0 4096)"})
|
||||||
|
lines_list.append({ "geometry":"LINESTRING (0 4096, 4096 4096)"})
|
||||||
|
lines_list.append({ "geometry":"LINESTRING (4096 4096, 4096 0)"})
|
||||||
|
lines_list.append({ "geometry":"LINESTRING (4096 0, 0 0)"})
|
||||||
|
|
||||||
|
|
||||||
|
tile = mapbox_vector_tile.encode([
|
||||||
|
{
|
||||||
|
"name": "errorTileSquareLayer",
|
||||||
|
"features": [{ "geometry":"POLYGON ((0 0, 0 4096, 4096 4096, 4096 0, 0 0))" }]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "errorTileStripesLayer",
|
||||||
|
"features": lines_list
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
with open('./assets/render-timeout-fallback.mvt', 'w+') as f:
|
||||||
|
f.write(tile)
|
@ -419,18 +419,23 @@ describe('user database timeout limit', function () {
|
|||||||
response: {
|
response: {
|
||||||
status: 429,
|
status: 429,
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json; charset=utf-8'
|
'Content-Type': 'application/x-protobuf'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.testClient.getTile(0, 0, 0, params, (err, res, timeoutError) => {
|
this.testClient.getTile(0, 0, 0, params, (err, res, tile) => {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
|
|
||||||
assert.deepEqual(timeoutError, DATASOURCE_TIMEOUT_ERROR);
|
var tileJSON = tile.toJSON();
|
||||||
|
assert.equal(Array.isArray(tileJSON), true);
|
||||||
|
assert.equal(tileJSON.length, 2);
|
||||||
|
assert.equal(tileJSON[0].name, 'errorTileSquareLayer');
|
||||||
|
assert.equal(tileJSON[1].name, 'errorTileStripesLayer');
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -232,7 +232,7 @@ describe('user render timeout limit', function () {
|
|||||||
response: {
|
response: {
|
||||||
status: 429,
|
status: 429,
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json; charset=utf-8'
|
'Content-Type': 'application/x-protobuf'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -240,15 +240,12 @@ describe('user render timeout limit', function () {
|
|||||||
this.testClient.getTile(0, 0, 0, params, (err, res, tile) => {
|
this.testClient.getTile(0, 0, 0, params, (err, res, tile) => {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
|
|
||||||
assert.deepEqual(tile, {
|
var tileJSON = tile.toJSON();
|
||||||
errors: ['You are over platform\'s limits. Please contact us to know more details'],
|
assert.equal(Array.isArray(tileJSON), true);
|
||||||
errors_with_context: [{
|
assert.equal(tileJSON.length, 2);
|
||||||
type: 'limit',
|
assert.equal(tileJSON[0].name, 'errorTileSquareLayer');
|
||||||
subtype: 'datasource',
|
assert.equal(tileJSON[1].name, 'errorTileStripesLayer');
|
||||||
message: 'You are over platform\'s limits. Please contact us to know more details'
|
|
||||||
}]
|
|
||||||
});
|
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user