1 | ;
|
2 |
|
3 | Object.defineProperty(exports, "__esModule", {
|
4 | value: true
|
5 | });
|
6 | exports.default = void 0;
|
7 |
|
8 | var _autoBind = _interopRequireDefault(require("auto-bind"));
|
9 |
|
10 | var _System = _interopRequireDefault(require("./System"));
|
11 |
|
12 | var _Module = _interopRequireDefault(require("./Module"));
|
13 |
|
14 | var _asyncUtils = require("./asyncUtils");
|
15 |
|
16 | var _consts = require("./consts");
|
17 |
|
18 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
19 |
|
20 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
21 |
|
22 | const {
|
23 | MODULE_NAME,
|
24 | log,
|
25 | warn,
|
26 | error,
|
27 | noteGauge,
|
28 | noteCount,
|
29 | noteTimer,
|
30 | trackOp
|
31 | } = new _Module.default(__filename); // eslint-disable-line no-unused-vars
|
32 |
|
33 | class Execution {
|
34 | /**
|
35 | * An async function that is called AFTER a termination has accured and infra resources were released,
|
36 | * This handler is called after infra resources were flushed, so it should avoid using them.
|
37 | */
|
38 | constructor(options) {
|
39 | _defineProperty(this, "_options", void 0);
|
40 |
|
41 | _defineProperty(this, "_startTimeMS", void 0);
|
42 |
|
43 | _defineProperty(this, "_endTimeMS", void 0);
|
44 |
|
45 | _defineProperty(this, "_terminating", false);
|
46 |
|
47 | _defineProperty(this, "_onTerminateHandlers", []);
|
48 |
|
49 | _defineProperty(this, "terminationHandler", void 0);
|
50 |
|
51 | this._options = options || {
|
52 | dontTerminateOnCompletion: false
|
53 | };
|
54 | (0, _autoBind.default)(this);
|
55 | }
|
56 |
|
57 | async run(runFunc) {
|
58 | try {
|
59 | noteCount(`execution.start`); // Catches ctrl+c and PM2 shutdown
|
60 |
|
61 | process.on('SIGINT', async () => await this._terminate(new Error('SIGINT')));
|
62 |
|
63 | if (_System.default.getConfig().trackVitalsIntervalMS) {
|
64 | this._trackVitals();
|
65 | }
|
66 |
|
67 | this._startTimeMS = Date.now();
|
68 | log('Execution started');
|
69 | const returnValue = await runFunc();
|
70 |
|
71 | if (!this._options.dontTerminateOnCompletion) {
|
72 | await this._terminate(null, returnValue);
|
73 | }
|
74 | } catch (err) {
|
75 | await this._terminate(err);
|
76 | }
|
77 | }
|
78 | /**
|
79 | * Allows adding an async function that is called BEFORE a termination has accured.
|
80 | * @param {*} terminationHandler
|
81 | */
|
82 |
|
83 |
|
84 | addOnTerminateHandler(onTerminateHandler) {
|
85 | this._onTerminateHandlers.push(onTerminateHandler);
|
86 | }
|
87 |
|
88 | async _trackVitals() {
|
89 | while (!this._terminating) {
|
90 | try {
|
91 | const used = process.memoryUsage();
|
92 |
|
93 | for (const key in used) {
|
94 | noteGauge(`memory.${key}MB`, Math.round(used[key] / 1024 / 1024 * 100) / 100);
|
95 | }
|
96 |
|
97 | await (0, _asyncUtils.sleep)(_System.default.getConfig().trackVitalsIntervalMS || 10 * _consts.SECOND_MS);
|
98 | } catch (err) {
|
99 | error('Failed to track vitals', {
|
100 | err
|
101 | });
|
102 | await (0, _asyncUtils.sleep)(1 * _consts.MINUTE_MS);
|
103 | }
|
104 | }
|
105 | }
|
106 |
|
107 | async _terminate(terminationError, data) {
|
108 | if (this._terminating) return;
|
109 | this._terminating = true;
|
110 | this._endTimeMS = Date.now(); // $FlowIgnore
|
111 |
|
112 | const durationMS = this._endTimeMS - this._startTimeMS;
|
113 |
|
114 | if (terminationError == null) {
|
115 | await noteCount(`execution.succeed`);
|
116 | await noteTimer('execution.succeed_duration', durationMS);
|
117 | log('Execution ended successfully', {
|
118 | durationMS
|
119 | });
|
120 | } else if (terminationError.message === 'SIGINT') {
|
121 | await noteCount(`execution.terminate`);
|
122 | await noteTimer('execution.terminate_duration', durationMS);
|
123 | warn('Execution terminated by SIGINT signal, terminating...', {
|
124 | durationMS
|
125 | });
|
126 | } else {
|
127 | await noteCount(`execution.fail`);
|
128 | await noteTimer('execution.fail_duration', durationMS);
|
129 | error('Execution threw an unhandled exception, terminating...', {
|
130 | durationMS,
|
131 | err: terminationError
|
132 | });
|
133 | }
|
134 |
|
135 | await noteCount('execution.end');
|
136 | await noteTimer('execution.end_duration', durationMS); // onTerniate handlers
|
137 |
|
138 | for (const onTerminateHandler of this._onTerminateHandlers) {
|
139 | try {
|
140 | await onTerminateHandler(terminationError, data);
|
141 | } catch (err) {
|
142 | error('one of the onTerminate handlers threw an error', {
|
143 | err
|
144 | });
|
145 | }
|
146 | }
|
147 |
|
148 | await _System.default.flush(); // NOTE: logging or tracking behind this point are not guaranteed to be transmitted
|
149 |
|
150 | if (!this.terminationHandler) {
|
151 | process.exit(terminationError == null ? 0 : 1);
|
152 | } else {
|
153 | // terminationHandler
|
154 | try {
|
155 | await this.terminationHandler(terminationError, data);
|
156 | } catch (err) {
|
157 | error('terminationHandler threw an error', {
|
158 | err
|
159 | });
|
160 | await _System.default.flush();
|
161 | process.exit(1);
|
162 | }
|
163 | }
|
164 | }
|
165 |
|
166 | }
|
167 |
|
168 | exports.default = Execution;
|
169 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9FeGVjdXRpb24uanMiXSwibmFtZXMiOlsiTU9EVUxFX05BTUUiLCJsb2ciLCJ3YXJuIiwiZXJyb3IiLCJub3RlR2F1Z2UiLCJub3RlQ291bnQiLCJub3RlVGltZXIiLCJ0cmFja09wIiwiTW9kdWxlIiwiX19maWxlbmFtZSIsIkV4ZWN1dGlvbiIsImNvbnN0cnVjdG9yIiwib3B0aW9ucyIsIl9vcHRpb25zIiwiZG9udFRlcm1pbmF0ZU9uQ29tcGxldGlvbiIsInJ1biIsInJ1bkZ1bmMiLCJwcm9jZXNzIiwib24iLCJfdGVybWluYXRlIiwiRXJyb3IiLCJTeXN0ZW0iLCJnZXRDb25maWciLCJ0cmFja1ZpdGFsc0ludGVydmFsTVMiLCJfdHJhY2tWaXRhbHMiLCJfc3RhcnRUaW1lTVMiLCJEYXRlIiwibm93IiwicmV0dXJuVmFsdWUiLCJlcnIiLCJhZGRPblRlcm1pbmF0ZUhhbmRsZXIiLCJvblRlcm1pbmF0ZUhhbmRsZXIiLCJfb25UZXJtaW5hdGVIYW5kbGVycyIsInB1c2giLCJfdGVybWluYXRpbmciLCJ1c2VkIiwibWVtb3J5VXNhZ2UiLCJrZXkiLCJNYXRoIiwicm91bmQiLCJTRUNPTkRfTVMiLCJNSU5VVEVfTVMiLCJ0ZXJtaW5hdGlvbkVycm9yIiwiZGF0YSIsIl9lbmRUaW1lTVMiLCJkdXJhdGlvbk1TIiwibWVzc2FnZSIsImZsdXNoIiwidGVybWluYXRpb25IYW5kbGVyIiwiZXhpdCJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUVBOztBQUVBOztBQUNBOztBQUNBOztBQUNBOzs7Ozs7QUFFQSxNQUFNO0FBQUVBLEVBQUFBLFdBQUY7QUFBZUMsRUFBQUEsR0FBZjtBQUFvQkMsRUFBQUEsSUFBcEI7QUFBMEJDLEVBQUFBLEtBQTFCO0FBQWlDQyxFQUFBQSxTQUFqQztBQUE0Q0MsRUFBQUEsU0FBNUM7QUFBdURDLEVBQUFBLFNBQXZEO0FBQWtFQyxFQUFBQTtBQUFsRSxJQUE4RSxJQUFJQyxlQUFKLENBQVdDLFVBQVgsQ0FBcEYsQyxDQUEy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QUFMLENBQXdCTixnQkFBeEIsRUFBMENDLElBQTFDLENBQU47QUFDRCxPQUZELENBRUUsT0FBT2QsR0FBUCxFQUFZO0FBQ1oxQixRQUFBQSxLQUFLLENBQUMsbUNBQUQsRUFBc0M7QUFBRTBCLFVBQUFBO0FBQUYsU0FBdEMsQ0FBTDtBQUNBLGNBQU1SLGdCQUFPMEIsS0FBUCxFQUFOO0FBQ0E5QixRQUFBQSxPQUFPLENBQUNnQyxJQUFSLENBQWEsQ0FBYjtBQUNEO0FBQ0Y7QUFDRjs7QUF4SCtCIiwic291cmNlc0NvbnRlbnQiOlsiLy9AZmxvd1xuXG5pbXBvcnQgYXV0b0JpbmQgZnJvbSAnYXV0by1iaW5kJ1xuXG5pbXBvcnQgU3lzdGVtIGZyb20gJy4vU3lzdGVtJ1xuaW1wb3J0IE1vZHVsZSBmcm9tICcuL01vZHVsZSdcbmltcG9ydCB7IHNsZWVwIH0gZnJvbSAnLi9hc3luY1V0aWxzJ1xuaW1wb3J0IHsgU0VDT05EX01TLCBNSU5VVEVfTVMgfSBmcm9tICcuL2NvbnN0cydcblxuY29uc3QgeyBNT0RVTEVfTkFNRSwgbG9nLCB3YXJuLCBlcnJvciwgbm90ZUdhdWdlLCBub3RlQ291bnQsIG5vdGVUaW1lciwgdHJhY2tPcCB9ID0gbmV3IE1vZHVsZShfX2ZpbGVuYW1lKSAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVudXNlZC12YXJzXG5cbnR5cGUgRXhlY3V0aW9uT3B0aW9ucyA9IHt8XG4gIGRvbnRUZXJtaW5hdGVPbkNvbXBsZXRpb24/OiA/Ym9vbGVhbiwgLy8gVXNlZCBmb3IgY2FzZXMgd2hlcmUgY29kZSByZXR1cm5zIGJ1dCBzb21lIGNhbGxiYWNrcyBzdGlsbCBrZWVwIHRoZSBwcm9jZXNzIGFsaXZlIChsaWtlIHdlYiBzZXJ2ZXIpXG58fVxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBFeGVjdXRpb248VD4ge1xuXG4gIF9vcHRpb25zOiBFeGVjdXRpb25PcHRpb25zXG4gIF9zdGFydFRpbWVNUzogP251bWJlclxuICBfZW5kVGltZU1TOiA/bnVtYmVyXG4gIF90ZXJtaW5hdGluZzogYm9vbGVhbiA9IGZhbHNlXG4gIF9vblRlcm1pbmF0ZUhhbmRsZXJzOiBBcnJheTwoZXJyOiA/RXJyb3IsIGRhdGE6ID9UKSA9PiBQcm9taXNlPHZvaWQ+PiA9IFtdXG5cbiAgLyoqXG4gICogQW4gYXN5bmMgZnVuY3Rpb24gdGhhdCBpcyBjYWxsZWQgQUZURVIgYSB0ZXJtaW5hdGlvbiBoYXMgYWNjdXJlZCBhbmQgaW5mcmEgcmVzb3VyY2VzIHdlcmUgcmVsZWFzZWQsXG4gICogVGhpcyBoYW5kbGVyIGlzIGNhbGxlZCBhZnRlciBpbmZyYSByZXNvdXJjZXMgd2VyZSBmbHVzaGVkLCBzbyBpdCBzaG91bGQgYXZvaWQgdXNpbmcgdGhlbS5cbiAgKi9cbiAgdGVybWluYXRpb25IYW5kbGVyOiA/KGVycjogP0Vycm9yLCBkYXRhOiA/VCkgPT4gUHJvbWlzZTx2b2lkPlxuXG5cbiAgY29uc3RydWN0b3Iob3B0aW9ucz86ID9FeGVjdXRpb25PcHRpb25zKSB7XG4gICAgdGhpcy5fb3B0aW9ucyA9IG9wdGlvbnMgfHwge1xuICAgICAgZG9udFRlcm1pbmF0ZU9uQ29tcGxldGlvbjogZmFsc2UsXG4gICAgfVxuXG4gICAgYXV0b0JpbmQodGhpcylcbiAgfVxuXG5cbiAgYXN5bmMgcnVuKHJ1bkZ1bmM6ICgpID0+IFByb21pc2U8VD4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0cnkge1xuICAgICAgbm90ZUNvdW50KGBleGVjdXRpb24uc3RhcnRgKVxuXG4gICAgICAvLyBDYXRjaGVzIGN0cmwrYyBhbmQgUE0yIHNodXRkb3duXG4gICAgICBwcm9jZXNzLm9uKCdTSUdJTlQnLCBhc3luYyAoKSA9PiBhd2FpdCB0aGlzLl90ZXJtaW5hdGUobmV3IEVycm9yKCdTSUdJTlQnKSkpXG5cbiAgICAgIGlmIChTeXN0ZW0uZ2V0Q29uZmlnKCkudHJhY2tWaXRhbHNJbnRlcnZhbE1TKSB7XG4gICAgICAgIHRoaXMuX3RyYWNrVml0YWxzKClcbiAgICAgIH1cblxuICAgICAgdGhpcy5fc3RhcnRUaW1lTVMgPSBEYXRlLm5vdygpXG4gICAgICBsb2coJ0V4ZWN1dGlvbiBzdGFydGVkJylcbiAgICAgIGNvbnN0IHJldHVyblZhbHVlID0gYXdhaXQgcnVuRnVuYygpXG5cbiAgICAgIGlmICghdGhpcy5fb3B0aW9ucy5kb250VGVybWluYXRlT25Db21wbGV0aW9uKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuX3Rlcm1pbmF0ZShudWxsLCByZXR1cm5WYWx1ZSlcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGF3YWl0IHRoaXMuX3Rlcm1pbmF0ZShlcnIpXG4gICAgfSBcbiAgfVxuXG4gIC8qKlxuICAqIEFsbG93cyBhZGRpbmcgYW4gYXN5bmMgZnVuY3Rpb24gdGhhdCBpcyBjYWxsZWQgQkVGT1JFIGEgdGVybWluYXRpb24gaGFzIGFjY3VyZWQuXG4gICogQHBhcmFtIHsqfSB0ZXJtaW5hdGlvbkhhbmRsZXJcbiAgKi9cbiAgYWRkT25UZXJtaW5hdGVIYW5kbGVyKG9uVGVybWluYXRlSGFuZGxlcjogKGVycjogP0Vycm9yLCBkYXRhOiA/VCkgPT4gUHJvbWlzZTx2b2lkPik6IHZvaWQge1xuICAgIHRoaXMuX29uVGVybWluYXRlSGFuZGxlcnMucHVzaChvblRlcm1pbmF0ZUhhbmRsZXIpXG4gIH1cblxuXG4gIGFzeW5jIF90cmFja1ZpdGFscygpIHtcbiAgICB3aGlsZSAoIXRoaXMuX3Rlcm1pbmF0aW5nKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCB1c2VkID0gcHJvY2Vzcy5tZW1vcnlVc2FnZSgpXG4gICAgICAgIGZvciAoY29uc3Qga2V5IGluIHVzZWQpIHtcbiAgICAgICAgICBub3RlR2F1Z2UoYG1lbW9yeS4ke2tleX1NQmAsIE1hdGgucm91bmQodXNlZFtrZXldIC8gMTAyNCAvIDEwMjQgKiAxMDApIC8gMTAwKVxuICAgICAgICB9XG4gICAgICAgIGF3YWl0IHNsZWVwKFN5c3RlbS5nZXRDb25maWcoKS50cmFja1ZpdGFsc0ludGVydmFsTVMgfHwgMTAgKiBTRUNPTkRfTVMpXG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgZXJyb3IoJ0ZhaWxlZCB0byB0cmFjayB2aXRhbHMnLCB7IGVyciB9KVxuICAgICAgICBhd2FpdCBzbGVlcCgxICogTUlOVVRFX01TKVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGFzeW5jIF90ZXJtaW5hdGUodGVybWluYXRpb25FcnJvcjogP0Vycm9yLCBkYXRhOiA/VCkge1xuICAgIGlmICh0aGlzLl90ZXJtaW5hdGluZylcbiAgICAgIHJldHVyblxuICAgIHRoaXMuX3Rlcm1pbmF0aW5nID0gdHJ1ZVxuICAgIFxuICAgIHRoaXMuX2VuZFRpbWVNUyA9IERhdGUubm93KClcbiAgICAvLyAkRmxvd0lnbm9yZVxuICAgIGNvbnN0IGR1cmF0aW9uTVMgPSB0aGlzLl9lbmRUaW1lTVMgLSB0aGlzLl9zdGFydFRpbWVNU1xuXG4gICAgaWYgKHRlcm1pbmF0aW9uRXJyb3IgPT0gbnVsbCkge1xuICAgICAgYXdhaXQgbm90ZUNvdW50KGBleGVjdXRpb24uc3VjY2VlZGApXG4gICAgICBhd2FpdCBub3RlVGltZXIoJ2V4ZWN1dGlvbi5zdWNjZWVkX2R1cmF0aW9uJywgZHVyYXRpb25NUylcbiAgICAgIGxvZygnRXhlY3V0aW9uIGVuZGVkIHN1Y2Nlc3NmdWxseScsIHsgZHVyYXRpb25NUyB9KVxuICAgIH0gZWxzZSBpZiAodGVybWluYXRpb25FcnJvci5tZXNzYWdlID09PSAnU0lHSU5UJykge1xuICAgICAgYXdhaXQgbm90ZUNvdW50KGBleGVjdXRpb24udGVybWluYXRlYClcbiAgICAgIGF3YWl0IG5vdGVUaW1lcignZXhlY3V0aW9uLnRlcm1pbmF0ZV9kdXJhdGlvbicsIGR1cmF0aW9uTVMpXG4gICAgICB3YXJuKCdFeGVjdXRpb24gdGVybWluYXRlZCBieSBTSUdJTlQgc2lnbmFsLCB0ZXJtaW5hdGluZy4uLicsIHsgZHVyYXRpb25NUyB9KVxuICAgIH0gZWxzZSB7XG4gICAgICBhd2FpdCBub3RlQ291bnQoYGV4ZWN1dGlvbi5mYWlsYClcbiAgICAgIGF3YWl0IG5vdGVUaW1lcignZXhlY3V0aW9uLmZhaWxfZHVyYXRpb24nLCBkdXJhdGlvbk1TKVxuICAgICAgZXJyb3IoJ0V4ZWN1dGlvbiB0aHJldyBhbiB1bmhhbmRsZWQgZXhjZXB0aW9uLCB0ZXJtaW5hdGluZy4uLicsIHsgZHVyYXRpb25NUywgZXJyOiB0ZXJtaW5hdGlvbkVycm9yIH0pXG4gICAgfVxuICAgIGF3YWl0IG5vdGVDb3VudCgnZXhlY3V0aW9uLmVuZCcpXG4gICAgYXdhaXQgbm90ZVRpbWVyKCdleGVjdXRpb24uZW5kX2R1cmF0aW9uJywgZHVyYXRpb25NUylcblxuICAgIC8vIG9uVGVybmlhdGUgaGFuZGxlcnNcbiAgICBmb3IgKGNvbnN0IG9uVGVybWluYXRlSGFuZGxlciBvZiB0aGlzLl9vblRlcm1pbmF0ZUhhbmRsZXJzKSB7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBvblRlcm1pbmF0ZUhhbmRsZXIodGVybWluYXRpb25FcnJvciwgZGF0YSlcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBlcnJvcignb25lIG9mIHRoZSBvblRlcm1pbmF0ZSBoYW5kbGVycyB0aHJldyBhbiBlcnJvcicsIHsgZXJyIH0pXG4gICAgICB9XG4gICAgfVxuXG4gICAgYXdhaXQgU3lzdGVtLmZsdXNoKClcbiAgICAvLyBOT1RFOiBsb2dnaW5nIG9yIHRyYWNraW5nIGJlaGluZCB0aGlzIHBvaW50IGFyZSBub3QgZ3VhcmFudGVlZCB0byBiZSB0cmFuc21pdHRlZFxuXG4gICAgaWYgKCF0aGlzLnRlcm1pbmF0aW9uSGFuZGxlcikge1xuICAgICAgcHJvY2Vzcy5leGl0KHRlcm1pbmF0aW9uRXJyb3IgPT0gbnVsbCA/IDAgOiAxKVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyB0ZXJtaW5hdGlvbkhhbmRsZXJcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHRoaXMudGVybWluYXRpb25IYW5kbGVyKHRlcm1pbmF0aW9uRXJyb3IsIGRhdGEpXG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgZXJyb3IoJ3Rlcm1pbmF0aW9uSGFuZGxlciB0aHJldyBhbiBlcnJvcicsIHsgZXJyIH0pXG4gICAgICAgIGF3YWl0IFN5c3RlbS5mbHVzaCgpXG4gICAgICAgIHByb2Nlc3MuZXhpdCgxKVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG59XG4iXX0= |
\ | No newline at end of file |