tileblaster 1.0.7 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/builtins/check.js CHANGED
@@ -3,22 +3,13 @@
3
3
  const cache = {};
4
4
 
5
5
  module.exports = function({ req, res, opts, data }, next, skip){
6
+ const debug = this.lib.debug;
6
7
 
7
8
  // fill cache for map
8
9
  if (!cache.hasOwnProperty(data.map)) {
9
10
 
10
11
  cache[data.map] = {};
11
12
 
12
- // skip function
13
- cache[data.map].abort = function(err){
14
- if (res.used) return;
15
- res.statusCode = cache[data.map].status;
16
- if (cache[data.map].hints && err) res.setHeader("x-tileblaster-hint", err.message || err.toString());
17
- res.end();
18
- res.used = true; // mark connection as used
19
- return skip(); // skip rest of jobs
20
- };
21
-
22
13
  cache[data.map].status = (opts.status && Number.isInteger(opts.status)) ? opts.status : 204;
23
14
 
24
15
  cache[data.map].hints = !!opts.hints;
@@ -99,29 +90,40 @@ module.exports = function({ req, res, opts, data }, next, skip){
99
90
  };
100
91
  opts = cache[data.map];
101
92
 
93
+ // skip function
94
+ const abort = function abort (err){
95
+ debug.info("Check: Abort %s/%s/%s/%s: %s", data.map, data.req.params.z, data.req.params.x, data.req.params.y, err.message || err.toString());
96
+ if (res.used) return;
97
+ res.statusCode = cache[data.map].status;
98
+ if (cache[data.map].hints && err) res.setHeader("x-tileblaster-hint", err.message || err.toString());
99
+ res.end();
100
+ res.used = true; // mark connection as used
101
+ return skip(); // skip rest of jobs
102
+ };
103
+
102
104
  // check for NaNs
103
- if (isNaN(data.req.params.z) || isNaN(data.req.params.x) || isNaN(data.req.params.y)) return cache[data.map].abort(new Error("illegal zxy."));
105
+ if (isNaN(data.req.params.z) || isNaN(data.req.params.x) || isNaN(data.req.params.y)) return abort(new Error("illegal zxy."));
104
106
 
105
107
  // check zoom
106
- if (data.req.params.z < opts.minZoom || data.req.params.z > opts.maxZoom) return cache[data.map].abort(new Error("illegal zoom."));
108
+ if (data.req.params.z < opts.minZoom || data.req.params.z > opts.maxZoom) return abort(new Error("illegal zoom."));
107
109
 
108
110
  // check bounds
109
111
  if (opts.bounds) {
110
112
  if (opts.bounds[data.req.params.z][0] < opts.bounds[data.req.params.z][2]) { // check for bounds spanning antimeridian
111
113
  // bounds don't span antimeridian
112
- if (data.req.params.x < opts.bounds[data.req.params.z][0] || data.req.params.x > opts.bounds[data.req.params.z][2]) return cache[data.map].abort(new Error("x is out of bounds."));
114
+ if (data.req.params.x < opts.bounds[data.req.params.z][0] || data.req.params.x > opts.bounds[data.req.params.z][2]) return abort(new Error("x is out of bounds."));
113
115
  } else {
114
116
  // bounds span antimeridian
115
- if (data.req.params.x > opts.bounds[data.req.params.z][0] && data.req.params.x < opts.bounds[data.req.params.z][2]) return cache[data.map].abort(new Error("x is out of bounds, bounds span antimeridian"));
117
+ if (data.req.params.x > opts.bounds[data.req.params.z][0] && data.req.params.x < opts.bounds[data.req.params.z][2]) return abort(new Error("x is out of bounds, bounds span antimeridian"));
116
118
  }
117
- if (data.req.params.y < opts.bounds[data.req.params.z][1] || data.req.params.y > opts.bounds[data.req.params.z][3]) return cache[data.map].abort(new Error("y is out of bounds."));
119
+ if (data.req.params.y < opts.bounds[data.req.params.z][1] || data.req.params.y > opts.bounds[data.req.params.z][3]) return abort(new Error("y is out of bounds."));
118
120
  }
119
121
 
120
122
  // check extension
121
- if (opts.extensions.length > 0 && !opts.extensions.includes(data.req.params.e) && !opts.extensions.includes(data.req.params.f)) return cache[data.map].abort(new Error("illegal extension."));
123
+ if (opts.extensions.length > 0 && !opts.extensions.includes(data.req.params.e) && !opts.extensions.includes(data.req.params.f)) return abort(new Error("illegal extension."));
122
124
 
123
125
  // check density
124
- if (opts.density && !opts.density.includes(data.req.params.d) && !opts.density.includes(data.req.params.f)) return cache[data.map].abort(new Error("illegal density marker."));
126
+ if (opts.density && !opts.density.includes(data.req.params.d) && !opts.density.includes(data.req.params.f)) return abort(new Error("illegal density marker."));
125
127
 
126
128
  // all passed
127
129
  next();
@@ -17,22 +17,23 @@ module.exports = function({ req, res, opts, data }, next, skip){
17
17
  headers: ((opts.hasOwnProperty("headers")) ? opts.headers : {}),
18
18
  });
19
19
 
20
- // skip function
21
- cache[data.map].abort = function(err){
22
- if (res.used) return;
23
- res.statusCode = 204; // no content
24
- res.setHeader("x-tileblaster-hint", err.message || err.toString());
25
- res.end();
26
- res.used = true; // mark connection as used
27
- return skip(); // skip rest of jobs
28
- };
29
-
30
20
  };
31
21
  const vt = cache[data.map];
32
22
 
33
- debug.info("Fetching %s/%s/%s", data.req.params.z, data.req.params.x, data.req.params.y);
23
+ // abort function
24
+ const abort = function abort(err){
25
+ debug.info("Versatiles: Abort %s/%s/%s/%s: %s", data.map, data.req.params.z, data.req.params.x, data.req.params.y, err.message || err.toString());
26
+ if (res.used) return;
27
+ res.statusCode = 204; // no content
28
+ res.end();
29
+ res.used = true; // mark connection as used
30
+ return skip(); // skip rest of jobs
31
+ };
32
+
33
+ debug.info("Versatiles: Fetching %s/%s/%s/%s", data.map, data.req.params.z, data.req.params.x, data.req.params.y);
34
34
  vt.getTile(data.req.params.z, data.req.params.x, data.req.params.y, function(err, buf){
35
- if (err) return cache[data.map].abort(err); // fail gracefully
35
+ if (err) return abort(err); // fail gracefully
36
+ if (buf.length === 0) return abort(new Error("Tile does not exist")); // fail gracefully
36
37
 
37
38
  // if precompressed, keep in tile stack
38
39
  /* TODO evaluate side effects
@@ -51,7 +52,7 @@ module.exports = function({ req, res, opts, data }, next, skip){
51
52
 
52
53
  // decompress tile
53
54
  vt.decompress(vt.header.tile_precompression, buf, function(err, buf){
54
- if (err) return cache[data.map].abort(err); // fail gracefully
55
+ if (err) return abort(err); // fail gracefully
55
56
 
56
57
  const tile = {
57
58
  buffer: buf,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tileblaster",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "description": "a quick and versatile map tile caching proxy",
5
5
  "main": "tileblaster.js",
6
6
  "bin": {
package/tileblaster.js CHANGED
@@ -113,9 +113,26 @@ const tileblaster = module.exports = function tileblaster(config){
113
113
 
114
114
  self.queue.push(function(next){ // queue tasks
115
115
 
116
+ args.start = Date.now();
117
+ args.timeout = setTimeout(function(){
118
+ debug.warn("Task timed out: %s (%d total, %d running)", req.path, self.queue.stack.length, self.queue.running);
119
+ if (res.used) return debug.warn("Connection already used.", req.path);
120
+ res.used = true;
121
+ args.timeout = null;
122
+ res.statusCode = 500;
123
+ res.setHeader("content-type", "text/plain");
124
+ res.end("Error.");
125
+ next();
126
+ },30000);
127
+
116
128
  // create tasks from map
117
129
  tasks(self.maps[req.map]).run(args, function(err, { res }){
118
130
 
131
+ // check if timed out
132
+ if (args.timeout === null) return;
133
+ clearTimeout(args.timeout);
134
+ debug.info("Task complete: %s (%ds)", req.path, ((Date.now()-args.start)/1000));
135
+
119
136
  next(); // free queue
120
137
 
121
138
  // FIXME provide more context