naturalatlas / tilestrata
Showing 2 of 5 files from the diff.

@@ -20,6 +20,7 @@
Loading
20 20
var HEADER_XPOWEREDBY = 'TileStrata/' + version;
21 21
var BUFFER_NOTFOUND = Buffer.from('Not found', 'utf8');
22 22
var BUFFER_NOTIMPLEMENTED = Buffer.from('Not implemented', 'utf8');
23 +
var BUFFER_NOTINITIALIZED = Buffer.from('Not initialized', 'utf8');
23 24
24 25
log.heading = 'tilestrata';
25 26
log.prefixStyle = {fg: 'grey'}
@@ -99,10 +100,20 @@
Loading
99 100
		self.initialize = async.memoize(TileServer.prototype.initialize.bind(self));
100 101
		if (callback) callback(err);
101 102
	};
102 -
103 -
	async.each(_.values(this.layers), function(layer, callback) {
104 -
		async.each(_.values(layer.routes), function(route, callback) {
105 -
			route.handler._initialize(self, callback);
103 +
	var verbose = self.options.verbose;
104 +
	var skipFailures = self.options.skipFailures;
105 +
	async.eachSeries(_.values(this.layers), function(layer, callback) {
106 +
		async.eachSeries(_.values(layer.routes), function(route, callback) {
107 +
			route.handler._initialize(self, function(err) {
108 +
				var contextString = layer.name + ' ' + route.filename;
109 +
				if (err) {
110 +
					var level = skipFailures ? 'warn' : 'error';
111 +
					log[level](contextString + ' init failed', err.stack);
112 +
				} else if (verbose) {
113 +
					log.info(contextString + ' initialized');
114 +
				}
115 +
				callback(skipFailures ? null : err);
116 +
			});
106 117
		}, function(err) {
107 118
			if (err) err = new Error('Unable to initialize "' + layer.name + '" layer: "' + (err.message || err) + '"');
108 119
			callback(err);
@@ -183,91 +194,98 @@
Loading
183 194
	var self = this;
184 195
	if (!req) return callback(404, BUFFER_NOTFOUND, {});
185 196
	var _method = req.method;
186 -
187 197
	if (req.method === 'HEAD') {
188 198
		_method = 'GET';
189 199
	}
190 200
191 -
	var handler = this._getTileHandler(req);
192 -
	if (!handler) {
193 -
		return callback(404, BUFFER_NOTFOUND, {
194 -
			'X-Powered-By': HEADER_XPOWEREDBY,
195 -
			'Content-Length': BUFFER_NOTFOUND.length
196 -
		});
197 -
	} else if (_method !== _method.toUpperCase() || !handler[_method]) {
198 -
		return callback(501, BUFFER_NOTIMPLEMENTED, {
199 -
			'X-Powered-By': HEADER_XPOWEREDBY,
200 -
			'Content-Length': BUFFER_NOTIMPLEMENTED.length
201 -
		});
202 -
	}
201 +
	this.initialize(function(err) {
202 +
		if (err) return callback(err);
203 +
		var handler = self._getTileHandler(req);
203 204
204 -
	var result = {};
205 +
		if (!handler) {
206 +
			return callback(404, BUFFER_NOTFOUND, {
207 +
				'X-Powered-By': HEADER_XPOWEREDBY,
208 +
				'Content-Length': BUFFER_NOTFOUND.length
209 +
			});
210 +
		} else if (_method !== _method.toUpperCase() || !handler[_method]) {
211 +
			return callback(501, BUFFER_NOTIMPLEMENTED, {
212 +
				'X-Powered-By': HEADER_XPOWEREDBY,
213 +
				'Content-Length': BUFFER_NOTIMPLEMENTED.length
214 +
			});
215 +
		} else if (!handler.initialized) {
216 +
			return callback(500, BUFFER_NOTINITIALIZED, {
217 +
				'X-Powered-By': HEADER_XPOWEREDBY,
218 +
				'Content-Length': BUFFER_NOTINITIALIZED.length
219 +
			});
220 +
		}
205 221
206 -
	async.series([
207 -
		function invokeRequestHooks(callback) {
208 -
			if (!http || !handler.requestHooks.length) return callback();
209 -
			async.eachSeries(handler.requestHooks, function(hook, callback) {
210 -
				var __profile = self.profile(hook.id, req);
211 -
				hook.plugin.reqhook(self, req, http.req, http.res, function(err) {
212 -
					__profile(err);
213 -
					callback(err);
222 +
		var result = {};
223 +
		async.series([
224 +
			function invokeRequestHooks(callback) {
225 +
				if (!http || !handler.requestHooks.length) return callback();
226 +
				async.eachSeries(handler.requestHooks, function(hook, callback) {
227 +
					var __profile = self.profile(hook.id, req);
228 +
					hook.plugin.reqhook(self, req, http.req, http.res, function(err) {
229 +
						__profile(err);
230 +
						callback(err);
231 +
					});
232 +
				}, callback);
233 +
			},
234 +
			function handleRequest(callback) {
235 +
				handler[_method](self, req, function(status, buffer, headers) {
236 +
					headers = headers || {};
237 +
					var headerKeysBefore = Object.keys(headers);
238 +
					headers['X-Powered-By'] = HEADER_XPOWEREDBY;
239 +
					if (status === 200) {
240 +
						headers['Cache-Control'] = 'max-age=60';
241 +
					}
242 +
					normalizeHeaders(headers, headerKeysBefore);
243 +
244 +
					result = {status: status, buffer: buffer, headers: headers};
245 +
					callback();
214 246
				});
215 -
			}, callback);
216 -
		},
217 -
		function handleRequest(callback) {
218 -
			handler[_method](self, req, function(status, buffer, headers) {
219 -
				headers = headers || {};
220 -
				var headerKeysBefore = Object.keys(headers);
221 -
				headers['X-Powered-By'] = HEADER_XPOWEREDBY;
222 -
				if (status === 200) {
223 -
					headers['Cache-Control'] = 'max-age=60';
247 +
			},
248 +
			function invokeResponseHooks(callback) {
249 +
				if (!http || !handler.responseHooks.length) return callback();
250 +
				var headerKeysBefore = Object.keys(result.headers);
251 +
				async.eachSeries(handler.responseHooks, function(hook, callback) {
252 +
					var __profile = self.profile(hook.id, req);
253 +
					hook.plugin.reshook(self, req, http.req, http.res, result, function(err) {
254 +
						normalizeHeaders(result.headers, headerKeysBefore);
255 +
						__profile(err);
256 +
						callback(err);
257 +
					});
258 +
				}, callback);
259 +
			},
260 +
			function finalizeResult(callback) {
261 +
				if (!result.headers) result.headers = {};
262 +
				var headerKeysBefore = Object.keys(result.headers);
263 +
				if (result.status !== 204) {
264 +
					result.headers['Content-Length'] = result.buffer ? result.buffer.length : 0;
224 265
				}
225 -
				normalizeHeaders(headers, headerKeysBefore);
266 +
				normalizeHeaders(result.headers, headerKeysBefore);
267 +
268 +
				// head request support
269 +
				if (req.method === 'HEAD') result.buffer = Buffer.from('', 'utf8');
226 270
227 -
				result = {status: status, buffer: buffer, headers: headers};
228 271
				callback();
229 -
			});
230 -
		},
231 -
		function invokeResponseHooks(callback) {
232 -
			if (!http || !handler.responseHooks.length) return callback();
233 -
			var headerKeysBefore = Object.keys(result.headers);
234 -
			async.eachSeries(handler.responseHooks, function(hook, callback) {
235 -
				var __profile = self.profile(hook.id, req);
236 -
				hook.plugin.reshook(self, req, http.req, http.res, result, function(err) {
237 -
					normalizeHeaders(result.headers, headerKeysBefore);
238 -
					__profile(err);
239 -
					callback(err);
272 +
			}
273 +
		], function(err) {
274 +
			if (err) {
275 +
				var buffer = Buffer.from(String(err.message || err), 'utf8');
276 +
				log.error(null, 'Failed to serve ' + req.filename + ' for "' + req.layer + '" layer {x:' + req.x + ',y:' + req.y + ',z:' + req.z + '}');
277 +
				log.error(null, err.stack || err);
278 +
				callback(500, buffer, {
279 +
					'Cache-Control': 'no-cache, no-store, must-revalidate',
280 +
					'Pragma': 'no-cache',
281 +
					'Expires': '0',
282 +
					'X-Powered-By': HEADER_XPOWEREDBY,
283 +
					'Content-Length': buffer.length
240 284
				});
241 -
			}, callback);
242 -
		},
243 -
		function finalizeResult(callback) {
244 -
			if (!result.headers) result.headers = {};
245 -
			var headerKeysBefore = Object.keys(result.headers);
246 -
			if (result.status !== 204) {
247 -
				result.headers['Content-Length'] = result.buffer ? result.buffer.length : 0;
285 +
			} else {
286 +
				callback(result.status, result.buffer, result.headers);
248 287
			}
249 -
			normalizeHeaders(result.headers, headerKeysBefore);
250 -
251 -
			// head request support
252 -
			if (req.method === 'HEAD') result.buffer = Buffer.from('', 'utf8');
253 -
254 -
			callback();
255 -
		}
256 -
	], function(err) {
257 -
		if (err) {
258 -
			var buffer = Buffer.from(String(err.message || err), 'utf8');
259 -
			log.error(null, 'Failed to serve ' + req.filename + ' for "' + req.layer + '" layer {x:' + req.x + ',y:' + req.y + ',z:' + req.z + '}');
260 -
			log.error(null, err);
261 -
			callback(500, buffer, {
262 -
				'Cache-Control': 'no-cache, no-store, must-revalidate',
263 -
				'Pragma': 'no-cache',
264 -
				'Expires': '0',
265 -
				'X-Powered-By': HEADER_XPOWEREDBY,
266 -
				'Content-Length': buffer.length
267 -
			});
268 -
		} else {
269 -
			callback(result.status, result.buffer, result.headers);
270 -
		}
288 +
		});
271 289
	});
272 290
};
273 291
@@ -483,7 +501,7 @@
Loading
483 501
			self.balancer_token = body.token;
484 502
			self.balancer_check_interval = body.check_interval;
485 503
			self.handleBalancerPing();
486 -
		    recovery.reconnected();
504 +
			recovery.reconnected();
487 505
		});
488 506
	});
489 507

@@ -6,6 +6,7 @@
Loading
6 6
7 7
var TileRequestHandler = module.exports = function(options) {
8 8
	options = options || {};
9 +
	this.initialized = false;
9 10
	this.provider = null;
10 11
	this.caches = [];
11 12
	this.transforms = [];
@@ -81,8 +82,8 @@
Loading
81 82
		return function(err) {
82 83
			if (err && skip_errors) {
83 84
				last_error = err;
84 -
				log.warn('plugin', 'Failed to close: "' + err.message + '"');
85 -
				return callback(err);
85 +
				log.warn('plugin', 'Failed to "' + plugin_method + '": "' + err.message + '"');
86 +
				return callback();
86 87
			}
87 88
			return callback(err);
88 89
		};
@@ -123,17 +124,23 @@
Loading
123 124
		}
124 125
	], function(err) {
125 126
		setImmediate(function() {
126 -
			callback(err || last_error || null);
127 +
			var finalError = skip_errors ? null : err || last_error;
128 +
			callback(finalError || null);
127 129
		});
128 130
	});
129 131
};
130 132
131 133
TileRequestHandler.prototype._destroy = function(server, callback) {
134 +
	this.initialized = false;
132 135
	this._invokeLifecycleMethod(server, 'destroy', true, callback);
133 136
};
134 137
135 138
TileRequestHandler.prototype._initialize = function(server, callback) {
136 -
	this._invokeLifecycleMethod(server, 'init', false, callback);
139 +
	var self = this;
140 +
	this._invokeLifecycleMethod(server, 'init', false, function(err) {
141 +
		if (!err) self.initialized = true;
142 +
		callback(err);
143 +
	});
137 144
};
138 145
139 146
/**
Files Coverage
lib 98.04%
index.js 87.18%
Project Totals (9 files) 97.48%
Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file. The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files. The size and color of each slice is representing the number of statements and the coverage, respectively.
Grid
Each block represents a single file in the project. The size and color of each block is represented by the number of statements and the coverage, respectively.
Loading