1 | ;
|
2 | //
|
3 | // Shared microservices framework.
|
4 | //
|
5 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
6 | return new (P || (P = Promise))(function (resolve, reject) {
|
7 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
8 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
9 | function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
10 | step((generator = generator.apply(thisArg, _arguments || [])).next());
|
11 | });
|
12 | };
|
13 | var __generator = (this && this.__generator) || function (thisArg, body) {
|
14 | var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
15 | return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
16 | function verb(n) { return function (v) { return step([n, v]); }; }
|
17 | function step(op) {
|
18 | if (f) throw new TypeError("Generator is already executing.");
|
19 | while (_) try {
|
20 | if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
21 | if (y = 0, t) op = [op[0] & 2, t.value];
|
22 | switch (op[0]) {
|
23 | case 0: case 1: t = op; break;
|
24 | case 4: _.label++; return { value: op[1], done: false };
|
25 | case 5: _.label++; y = op[1]; op = [0]; continue;
|
26 | case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
27 | default:
|
28 | if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
29 | if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
30 | if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
31 | if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
32 | if (t[2]) _.ops.pop();
|
33 | _.trys.pop(); continue;
|
34 | }
|
35 | op = body.call(thisArg, _);
|
36 | } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
37 | if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
38 | }
|
39 | };
|
40 | var __values = (this && this.__values) || function (o) {
|
41 | var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
|
42 | if (m) return m.call(o);
|
43 | return {
|
44 | next: function () {
|
45 | if (o && i >= o.length) o = void 0;
|
46 | return { value: o && o[i++], done: !o };
|
47 | }
|
48 | };
|
49 | };
|
50 | Object.defineProperty(exports, "__esModule", { value: true });
|
51 | var express = require("express");
|
52 | var amqp = require("amqplib");
|
53 | var axios_1 = require("axios");
|
54 | var request = require("request");
|
55 | var utils_1 = require("./utils");
|
56 | exports.asyncHandler = utils_1.asyncHandler;
|
57 | exports.retry = utils_1.retry;
|
58 | exports.sleep = utils_1.sleep;
|
59 | exports.verifyBodyParam = utils_1.verifyBodyParam;
|
60 | exports.verifyQueryParam = utils_1.verifyQueryParam;
|
61 | var morganBody = require('morgan-body');
|
62 | var http = require("http");
|
63 | var bodyParser = require("body-parser");
|
64 | var uuid = require("uuid");
|
65 | var perf_hooks_1 = require("perf_hooks");
|
66 | var inProduction = process.env.NODE_ENV === "production";
|
67 | var enableMorgan = !inProduction || process.env.ENABLE_MORGAN === "true";
|
68 | process.on('exit', function (code) {
|
69 | if (code === 0) {
|
70 | console.log("Process exited with code: " + code);
|
71 | }
|
72 | else {
|
73 | console.error("Process exited with error code: " + code);
|
74 | }
|
75 | });
|
76 | process.on('uncaughtException', function (err) {
|
77 | console.error("Uncaught exception: " + (err && err.stack || err));
|
78 | process.exit(1);
|
79 | });
|
80 | process.on('unhandledRejection', function (reason, promise) {
|
81 | console.error('Unhandled promise rejection at:', reason.stack || reason);
|
82 | process.exit(1);
|
83 | });
|
84 | //
|
85 | // Used to register an event handler to be setup after messaging system has started.
|
86 | //
|
87 | var EventHandler = /** @class */ (function () {
|
88 | function EventHandler(eventName, eventHandlerFn) {
|
89 | this.eventName = eventName;
|
90 | this.eventHandlerFn = eventHandlerFn;
|
91 | }
|
92 | return EventHandler;
|
93 | }());
|
94 | //
|
95 | // Class that represents a particular microservice instance.
|
96 | //
|
97 | var MicroService = /** @class */ (function () {
|
98 | function MicroService(config) {
|
99 | var _this = this;
|
100 | //
|
101 | // The unique ID for the particular instance of the microservice.
|
102 | //
|
103 | this.id = uuid.v4();
|
104 | //
|
105 | // Event handlers that have been registered to be setup once
|
106 | // connection to message queue is established.
|
107 | ///
|
108 | this.registeredEventHandlers = new Set();
|
109 | /**
|
110 | * Reference to the timer interface.
|
111 | * Allows code to be timed for performance.
|
112 | */
|
113 | this.timer = {
|
114 | start: function (timerName) {
|
115 | // Just a stub for the moment.
|
116 | },
|
117 | stop: function (timerName) {
|
118 | // Just a stub for the moment.
|
119 | },
|
120 | };
|
121 | /**
|
122 | * Reference to the metrics interface.
|
123 | * Allows a service to output metrics.
|
124 | */
|
125 | this.metrics = {
|
126 | discrete: function (name, value) {
|
127 | // Just a stub for the moment.
|
128 | },
|
129 | continuous: function (name, value) {
|
130 | // Just a stub for the moment.
|
131 | },
|
132 | };
|
133 | this.config = Object.assign({}, config);
|
134 | this.expressApp = express();
|
135 | this.httpServer = new http.Server(this.expressApp);
|
136 | //
|
137 | // Allow middleware, but only under certain conditions.
|
138 | //
|
139 | function unless(pred, middleware) {
|
140 | return function (req, res, next) {
|
141 | if (pred(req)) {
|
142 | next(); // Skip this middleware.
|
143 | }
|
144 | else {
|
145 | middleware(req, res, next); // Invoke middleware.
|
146 | }
|
147 | };
|
148 | }
|
149 | this.expressApp.use(unless(function (req) { return req.method === "PUT"; }, bodyParser.json()));
|
150 | this.expressApp.use(unless(function (req) { return req.method === "PUT"; }, bodyParser.urlencoded({ extended: true })));
|
151 | if (enableMorgan) {
|
152 | console.log("Enabling Morgan request tracing.");
|
153 | morganBody(this.expressApp, {
|
154 | noColors: true,
|
155 | });
|
156 | }
|
157 | this.expressApp.get("/is-alive", function (req, res) {
|
158 | res.json({ ok: true });
|
159 | });
|
160 | this.rest = {
|
161 | /**
|
162 | * Create a handler for incoming HTTP GET requests.
|
163 | * Implemented by Express under the hood.
|
164 | */
|
165 | get: function (route, requestHandler) {
|
166 | _this.expressApp.get(route, function (req, res) {
|
167 | _this.verbose("Handling GET " + route);
|
168 | var startTime = perf_hooks_1.performance.now();
|
169 | requestHandler(req, res)
|
170 | .then(function () {
|
171 | _this.verbose("HTTP GET handler for " + route + " finished in " + (perf_hooks_1.performance.now() - startTime).toFixed(2) + "ms");
|
172 | })
|
173 | .catch(function (err) {
|
174 | console.error("Error from handler: HTTP GET " + route);
|
175 | console.error(err && err.stack || err);
|
176 | if (!res.headersSent) {
|
177 | res.sendStatus(500);
|
178 | }
|
179 | });
|
180 | });
|
181 | },
|
182 | /**
|
183 | * Create a handler for incoming HTTP POST requests.
|
184 | * Implemented by Express under the hood.
|
185 | */
|
186 | post: function (route, requestHandler) {
|
187 | _this.expressApp.post(route, function (req, res) {
|
188 | _this.verbose("Handling POST " + route);
|
189 | var startTime = perf_hooks_1.performance.now();
|
190 | requestHandler(req, res)
|
191 | .then(function () {
|
192 | _this.verbose("HTTP POST handler for " + route + " finished in " + (perf_hooks_1.performance.now() - startTime).toFixed(2) + "ms");
|
193 | })
|
194 | .catch(function (err) {
|
195 | console.error("Error from handler: HTTP POST " + route);
|
196 | console.error(err && err.stack || err);
|
197 | if (!res.headersSent) {
|
198 | res.sendStatus(500);
|
199 | }
|
200 | });
|
201 | });
|
202 | },
|
203 | /**
|
204 | * Create a handler for incoming HTTP PUT requests.
|
205 | * Implemented by Express under the hood
|
206 | *
|
207 | * @param route
|
208 | * @param requestHandler
|
209 | */
|
210 | put: function (route, requestHandler) {
|
211 | _this.expressApp.put(route, function (req, res) {
|
212 | _this.verbose("Handling PUT " + route);
|
213 | var startTime = perf_hooks_1.performance.now();
|
214 | requestHandler(req, res)
|
215 | .then(function () {
|
216 | _this.verbose("HTTP PUT handler for " + route + " finished in " + (perf_hooks_1.performance.now() - startTime).toFixed(2) + "ms");
|
217 | })
|
218 | .catch(function (err) {
|
219 | console.error("Error from handler: HTTP PUT " + route);
|
220 | console.error(err && err.stack || err);
|
221 | if (!res.headersSent) {
|
222 | res.sendStatus(500);
|
223 | }
|
224 | });
|
225 | });
|
226 | },
|
227 | /**
|
228 | * Setup serving of static files.
|
229 | *
|
230 | * @param dirPath The path to the directory that contains static files.
|
231 | */
|
232 | static: function (dirPath) {
|
233 | console.log("Serving static files from " + dirPath);
|
234 | _this.expressApp.use(express.static(dirPath));
|
235 | },
|
236 | };
|
237 | this.request = {
|
238 | /**
|
239 | * Make a HTTP get request to another service.
|
240 | *
|
241 | * @param serviceName The name (logical or host) of the service.
|
242 | * @param route The HTTP route on the service to make the request to.
|
243 | * @param params Query parameters for the request.
|
244 | */
|
245 | get: function (serviceName, route, body) { return __awaiter(_this, void 0, void 0, function () {
|
246 | var url;
|
247 | return __generator(this, function (_a) {
|
248 | switch (_a.label) {
|
249 | case 0:
|
250 | url = "http://" + serviceName + route;
|
251 | return [4 /*yield*/, axios_1.default.get(url, body)];
|
252 | case 1: return [2 /*return*/, _a.sent()];
|
253 | }
|
254 | });
|
255 | }); },
|
256 | /**
|
257 | * Make a HTTP get request to another service.
|
258 | *
|
259 | * @param serviceName The name (logical or host) of the service.
|
260 | * @param route The HTTP route on the service to make the request to.
|
261 | * @param params Query parameters for the request.
|
262 | */
|
263 | post: function (serviceName, route, body) { return __awaiter(_this, void 0, void 0, function () {
|
264 | var url;
|
265 | return __generator(this, function (_a) {
|
266 | switch (_a.label) {
|
267 | case 0:
|
268 | url = "http://" + serviceName + route;
|
269 | return [4 /*yield*/, axios_1.default.post(url, body)];
|
270 | case 1: return [2 /*return*/, _a.sent()];
|
271 | }
|
272 | });
|
273 | }); },
|
274 | /**
|
275 | * Forward HTTP get request to another named service.
|
276 | * The response from the forward requests is automatically piped into the passed in response.
|
277 | *
|
278 | * @param serviceName The name of the service to forward the request to.
|
279 | * @param route The HTTP GET route to forward to.
|
280 | * @param params Query parameters for the request.
|
281 | * @param res The stream to pipe response to.
|
282 | */
|
283 | forward: function (serviceName, route, req, res) {
|
284 | var url = "http://" + serviceName + route;
|
285 | req.pipe(request(url)).pipe(res);
|
286 | }
|
287 | };
|
288 | }
|
289 | //
|
290 | // Helper method for verbose logging.
|
291 | //
|
292 | MicroService.prototype.verbose = function (msg) {
|
293 | if (this.config.verbose) {
|
294 | console.log(msg);
|
295 | }
|
296 | };
|
297 | /**
|
298 | * Get the name that identifies the service.
|
299 | */
|
300 | MicroService.prototype.getServiceName = function () {
|
301 | return this.config.serviceName;
|
302 | };
|
303 | /**
|
304 | * Get the instance ID for the particular instance of the service.
|
305 | */
|
306 | MicroService.prototype.getInstanceId = function () {
|
307 | return this.id;
|
308 | };
|
309 | /**
|
310 | * Returns true if the messaging system is currently available.
|
311 | */
|
312 | MicroService.prototype.isMessagingAvailable = function () {
|
313 | return !!this.messagingConnection;
|
314 | };
|
315 | //
|
316 | // Setup a RabbitMQ message handler.
|
317 | //
|
318 | MicroService.prototype.internalOn = function (eventHandler) {
|
319 | return __awaiter(this, void 0, void 0, function () {
|
320 | var eventName, queueName, messagingChannel, consumeCallback;
|
321 | var _this = this;
|
322 | return __generator(this, function (_a) {
|
323 | switch (_a.label) {
|
324 | case 0:
|
325 | eventName = eventHandler.eventName;
|
326 | // http://www.squaremobius.net/amqp.node/channel_api.html#channel_assertExchange
|
327 | return [4 /*yield*/, this.messagingChannel.assertExchange(eventName, "fanout", { durable: true })];
|
328 | case 1:
|
329 | // http://www.squaremobius.net/amqp.node/channel_api.html#channel_assertExchange
|
330 | _a.sent();
|
331 | return [4 /*yield*/, this.messagingChannel.assertQueue("", { durable: true, exclusive: true })];
|
332 | case 2:
|
333 | queueName = (_a.sent()).queue;
|
334 | eventHandler.queueName = queueName;
|
335 | this.messagingChannel.bindQueue(queueName, eventName, "");
|
336 | messagingChannel = this.messagingChannel;
|
337 | this.verbose("Bound queue " + queueName + " to " + eventName + ".");
|
338 | consumeCallback = function (msg) { return __awaiter(_this, void 0, void 0, function () {
|
339 | var args, eventResponse;
|
340 | return __generator(this, function (_a) {
|
341 | switch (_a.label) {
|
342 | case 0:
|
343 | this.verbose("Handling event " + eventName);
|
344 | args = JSON.parse(msg.content.toString());
|
345 | eventResponse = {
|
346 | ack: function () {
|
347 | return __awaiter(this, void 0, void 0, function () {
|
348 | return __generator(this, function (_a) {
|
349 | messagingChannel.ack(msg);
|
350 | return [2 /*return*/];
|
351 | });
|
352 | });
|
353 | }
|
354 | };
|
355 | return [4 /*yield*/, eventHandler.eventHandlerFn(args, eventResponse)];
|
356 | case 1:
|
357 | _a.sent();
|
358 | this.verbose(eventName + " handler done.");
|
359 | return [2 /*return*/];
|
360 | }
|
361 | });
|
362 | }); };
|
363 | // http://www.squaremobius.net/amqp.node/channel_api.html#channel_consume
|
364 | this.messagingChannel.consume(queueName, utils_1.asyncHandler(this, "ASYNC: " + eventName, consumeCallback), {
|
365 | noAck: false,
|
366 | });
|
367 | this.verbose("Receiving events on queue " + eventName);
|
368 | return [2 /*return*/];
|
369 | }
|
370 | });
|
371 | });
|
372 | };
|
373 | //
|
374 | // Unwind a RabbitMQ message handler.
|
375 | //
|
376 | MicroService.prototype.internalOff = function (eventHandler) {
|
377 | this.messagingChannel.unbindQueue(eventHandler.queueName, eventHandler.eventName, "");
|
378 | delete eventHandler.queueName;
|
379 | };
|
380 | /**
|
381 | * Create an ongoing handler for a named incoming event.
|
382 | * Implemented by Rabbitmq under the hood for reliable messaging.
|
383 | *
|
384 | * @param eventName The name of the event to handle.
|
385 | * @param eventHandler Callback to be invoke when the incoming event is received.
|
386 | */
|
387 | MicroService.prototype.on = function (eventName, eventHandlerFn) {
|
388 | return __awaiter(this, void 0, void 0, function () {
|
389 | var eventHandler;
|
390 | return __generator(this, function (_a) {
|
391 | switch (_a.label) {
|
392 | case 0:
|
393 | eventHandler = new EventHandler(eventName, eventHandlerFn);
|
394 | this.registeredEventHandlers.add(eventHandler);
|
395 | if (!this.messagingConnection) return [3 /*break*/, 2];
|
396 | //
|
397 | // Message system already started.
|
398 | //
|
399 | return [4 /*yield*/, this.internalOn(eventHandler)];
|
400 | case 1:
|
401 | //
|
402 | // Message system already started.
|
403 | //
|
404 | _a.sent();
|
405 | _a.label = 2;
|
406 | case 2: return [2 /*return*/, eventHandler];
|
407 | }
|
408 | });
|
409 | });
|
410 | };
|
411 | /**
|
412 | * Unregister a previously register event handler.
|
413 | *
|
414 | * @param handler The event handler to unregister.
|
415 | */
|
416 | MicroService.prototype.off = function (handler) {
|
417 | var eventHandler = handler;
|
418 | if (this.messagingConnection) {
|
419 | this.internalOff(eventHandler);
|
420 | }
|
421 | this.registeredEventHandlers.delete(eventHandler);
|
422 | };
|
423 | /**
|
424 | * Create a once-off handler for a named incoming event.
|
425 | * The event handler will only be invoke once before the event is unregistered.
|
426 | * Implemented by Rabbitmq under the hood for reliable messaging.
|
427 | *
|
428 | * @param eventName The name of the event to handle.
|
429 | * @param eventHandler Callback to be invoke when the incoming event is received.
|
430 | */
|
431 | MicroService.prototype.once = function (eventName, eventHandlerFn) {
|
432 | return __awaiter(this, void 0, void 0, function () {
|
433 | var eventHandler;
|
434 | var _this = this;
|
435 | return __generator(this, function (_a) {
|
436 | switch (_a.label) {
|
437 | case 0: return [4 /*yield*/, this.on(eventName, function (args, res) { return __awaiter(_this, void 0, void 0, function () {
|
438 | return __generator(this, function (_a) {
|
439 | switch (_a.label) {
|
440 | case 0:
|
441 | this.off(eventHandler); // Unregister before we receive any more events.
|
442 | return [4 /*yield*/, eventHandlerFn(args, res)];
|
443 | case 1:
|
444 | _a.sent(); // Trigger user callback.
|
445 | return [2 /*return*/];
|
446 | }
|
447 | });
|
448 | }); })];
|
449 | case 1:
|
450 | eventHandler = _a.sent();
|
451 | return [2 /*return*/];
|
452 | }
|
453 | });
|
454 | });
|
455 | };
|
456 | /***
|
457 | * Wait for a single incoming event, returns the events arguments and then unregister the event handler.
|
458 | *
|
459 | * @param eventName The name of the event to handle.
|
460 | *
|
461 | * @returns A promise to resolve the incoming event's arguments.
|
462 | */
|
463 | MicroService.prototype.waitForOneEvent = function (eventName) {
|
464 | var _this = this;
|
465 | return new Promise(function (resolve) {
|
466 | _this.once(eventName, function (args, res) { return __awaiter(_this, void 0, void 0, function () {
|
467 | return __generator(this, function (_a) {
|
468 | res.ack(); // Ack the response.
|
469 | resolve(args); // Resolve event args through the promise.
|
470 | return [2 /*return*/];
|
471 | });
|
472 | }); });
|
473 | });
|
474 | };
|
475 | /**
|
476 | * Emit a named outgoing event.
|
477 | * Implemented by Rabbitmq under the hood for reliable messaging.
|
478 | *
|
479 | * @param eventName The name of the event to emit.
|
480 | * @param eventArgs Event args to publish with the event and be received at the other end.
|
481 | */
|
482 | MicroService.prototype.emit = function (eventName, eventArgs) {
|
483 | return __awaiter(this, void 0, void 0, function () {
|
484 | return __generator(this, function (_a) {
|
485 | switch (_a.label) {
|
486 | case 0:
|
487 | if (!this.messagingConnection) {
|
488 | throw new Error("Messaging system currently unavailable.");
|
489 | }
|
490 | // http://www.squaremobius.net/amqp.node/channel_api.html#channel_assertExchange
|
491 | return [4 /*yield*/, this.messagingChannel.assertExchange(eventName, "fanout", { durable: true, })];
|
492 | case 1:
|
493 | // http://www.squaremobius.net/amqp.node/channel_api.html#channel_assertExchange
|
494 | _a.sent();
|
495 | this.verbose("Sending message: " + eventName);
|
496 | this.verbose(JSON.stringify(eventArgs, null, 4));
|
497 | // http://www.squaremobius.net/amqp.node/channel_api.html#channel_publish
|
498 | this.messagingChannel.publish(eventName, '', new Buffer(JSON.stringify(eventArgs)), {
|
499 | persistent: true,
|
500 | }); //TODO: Probably a more efficient way to do this! Maybe BSON?
|
501 | return [2 /*return*/];
|
502 | }
|
503 | });
|
504 | });
|
505 | };
|
506 | /**
|
507 | * Start the HTTP server.
|
508 | * ! No need to call this if you already called 'start'.
|
509 | */
|
510 | MicroService.prototype.startHttpServer = function () {
|
511 | return __awaiter(this, void 0, void 0, function () {
|
512 | var _this = this;
|
513 | return __generator(this, function (_a) {
|
514 | return [2 /*return*/, new Promise(function (resolve, reject) {
|
515 | var host;
|
516 | if (_this.config.host !== undefined) {
|
517 | host = _this.config.host;
|
518 | }
|
519 | else {
|
520 | host = process.env.HOST || '0.0.0.0';
|
521 | }
|
522 | var port;
|
523 | if (_this.config.port !== undefined) {
|
524 | port = _this.config.port;
|
525 | }
|
526 | else {
|
527 | port = (process.env.PORT && parseInt(process.env.PORT)) || 3000;
|
528 | }
|
529 | _this.httpServer.listen(port, host, function (err) {
|
530 | if (err) {
|
531 | reject(err);
|
532 | }
|
533 | else {
|
534 | _this.verbose("Running on http://" + port + ":" + host);
|
535 | resolve();
|
536 | }
|
537 | });
|
538 | })];
|
539 | });
|
540 | });
|
541 | };
|
542 | /**
|
543 | * Start the RabbitMQ message queue.
|
544 | * ! No need to call this if you already called 'start'.
|
545 | */
|
546 | MicroService.prototype.startMessaging = function () {
|
547 | return __awaiter(this, void 0, void 0, function () {
|
548 | var initMessaging;
|
549 | var _this = this;
|
550 | return __generator(this, function (_a) {
|
551 | switch (_a.label) {
|
552 | case 0:
|
553 | initMessaging = function () { return __awaiter(_this, void 0, void 0, function () {
|
554 | var e_1, _a, messagingHost, _b, _c, _d, _e, eventHandler, e_1_1;
|
555 | var _this = this;
|
556 | return __generator(this, function (_f) {
|
557 | switch (_f.label) {
|
558 | case 0:
|
559 | if (this.config.messagingHost) {
|
560 | messagingHost = this.config.messagingHost;
|
561 | }
|
562 | else {
|
563 | messagingHost = process.env.MESSAGING_HOST || "amqp://guest:guest@localhost:5672";
|
564 | }
|
565 | this.verbose("Connecting to messaging server at: " + messagingHost);
|
566 | _b = this;
|
567 | return [4 /*yield*/, utils_1.retry(function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
|
568 | switch (_a.label) {
|
569 | case 0: return [4 /*yield*/, amqp.connect(messagingHost)];
|
570 | case 1: return [2 /*return*/, _a.sent()];
|
571 | }
|
572 | }); }); }, 10000, 1000)];
|
573 | case 1:
|
574 | _b.messagingConnection = _f.sent();
|
575 | this.messagingConnection.on("error", function (err) {
|
576 | console.error("Error from message system.");
|
577 | console.error(err && err.stack || err);
|
578 | });
|
579 | this.messagingConnection.on("close", function (err) {
|
580 | _this.messagingConnection = undefined;
|
581 | _this.messagingChannel = undefined;
|
582 | console.log("Lost connection to rabbit, waiting for restart.");
|
583 | initMessaging()
|
584 | .then(function () { return console.log("Restarted messaging."); })
|
585 | .catch(function (err) {
|
586 | console.error("Failed to restart messaging.");
|
587 | console.error(err && err.stack || err);
|
588 | });
|
589 | });
|
590 | _c = this;
|
591 | return [4 /*yield*/, this.messagingConnection.createChannel()];
|
592 | case 2:
|
593 | _c.messagingChannel = _f.sent();
|
594 | _f.label = 3;
|
595 | case 3:
|
596 | _f.trys.push([3, 8, 9, 10]);
|
597 | _d = __values(this.registeredEventHandlers.values()), _e = _d.next();
|
598 | _f.label = 4;
|
599 | case 4:
|
600 | if (!!_e.done) return [3 /*break*/, 7];
|
601 | eventHandler = _e.value;
|
602 | return [4 /*yield*/, this.internalOn(eventHandler)];
|
603 | case 5:
|
604 | _f.sent();
|
605 | _f.label = 6;
|
606 | case 6:
|
607 | _e = _d.next();
|
608 | return [3 /*break*/, 4];
|
609 | case 7: return [3 /*break*/, 10];
|
610 | case 8:
|
611 | e_1_1 = _f.sent();
|
612 | e_1 = { error: e_1_1 };
|
613 | return [3 /*break*/, 10];
|
614 | case 9:
|
615 | try {
|
616 | if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
|
617 | }
|
618 | finally { if (e_1) throw e_1.error; }
|
619 | return [7 /*endfinally*/];
|
620 | case 10: return [2 /*return*/];
|
621 | }
|
622 | });
|
623 | }); };
|
624 | return [4 /*yield*/, initMessaging()];
|
625 | case 1:
|
626 | _a.sent();
|
627 | return [2 /*return*/];
|
628 | }
|
629 | });
|
630 | });
|
631 | };
|
632 | /**
|
633 | * Starts the microservice.
|
634 | * It starts listening for incoming HTTP requests and events.
|
635 | */
|
636 | MicroService.prototype.start = function () {
|
637 | return __awaiter(this, void 0, void 0, function () {
|
638 | return __generator(this, function (_a) {
|
639 | switch (_a.label) {
|
640 | case 0: return [4 /*yield*/, this.startHttpServer()];
|
641 | case 1:
|
642 | _a.sent();
|
643 | return [4 /*yield*/, this.startMessaging()];
|
644 | case 2:
|
645 | _a.sent();
|
646 | return [2 /*return*/];
|
647 | }
|
648 | });
|
649 | });
|
650 | };
|
651 | return MicroService;
|
652 | }());
|
653 | exports.MicroService = MicroService;
|
654 | /**
|
655 | * Instantiates a microservice.
|
656 | *
|
657 | * @param [config] Optional configuration for the microservice.
|
658 | */
|
659 | function micro(config) {
|
660 | return new MicroService(config);
|
661 | }
|
662 | exports.micro = micro;
|
663 | //# sourceMappingURL=index.js.map |
\ | No newline at end of file |