-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
127 lines (98 loc) · 3.15 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
process.chdir(__dirname);
require('dotenv').config();
const { spawn } = require('child_process');
const kue = require('kue');
const { promisify } = require('util');
const appState = require('./core/app-state');
const finalErrorHandler = require('./core/final-error-handler');
const blockedHandler = require('./core/blocked-handler');
const Uploader = require('./core/Uploader');
const loggerFactory = require('./core/loggerFactory');
const utils = require('./core/utils.js');
appState.mode = 'initiating';
global.logger = loggerFactory();
const uploader = Uploader.getInstance();
uploader.init();
uploader.getQueue().watchStuckJobs(5000); // ms
const consumer = uploader.createConsumer();
consumer.handle();
if (process.send) {
process.send('ready');
}
appState.mode = 'running';
const finalizeLogging = () => {
const loggingPromise = new Promise((resolve, reject) => {
const loggingTimeout = setTimeout(reject, 1500);
global.logger.on('finish', () => {
clearTimeout(loggingTimeout);
resolve();
});
});
global.logger.end();
return loggingPromise;
};
const shutdownProcess = async (options) => {
appState.mode = 'terminating';
let failed = false;
if (options.error) {
global.logger.error(options.error);
failed = true;
}
const exitHandler = (promise, ignoreFailure = false) =>
Promise.resolve(promise).catch((err) => {
if (!ignoreFailure) {
global.logger.error(err);
failed = true;
}
});
try {
await Promise.all([
// try to exit immediately in case of failure
// otherwise wait for some time to stop the currently active jobs
exitHandler(uploader.shutdownQueue(failed ? 0 : (options.uploadTasksTimeout || 1000))),
(() => {
if (options.error) {
global.logger.error(options.error);
}
})(),
]);
global.logger.debug('All kue workers shut down.');
await promisify(consumer.stop.bind(consumer))();
global.logger.debug('All thekdar workers shut down.');
await Promise.all([
exitHandler(utils.quitRedis(uploader.publisher)),
exitHandler(kue.redis.reset()), // Quits all the redis connection used internally by kue
]);
global.logger.debug('Redis connection closed(failure ignored).');
} catch (error) {
failed = true;
global.logger.error(error);
} finally {
try {
await exitHandler(finalizeLogging(), true);
if (options.preExitCallback) {
await options.preExitCallback();
}
} catch (e) {
failed = true;
console.error(e.stack); // eslint-disable-line
}
process.exit(failed ? 1 : 0);
}
};
process.on('SIGUSR1', () => {
global.logger.info('Received SIGUSR1 signal.');
uploader.stop();
return shutdownProcess({
uploadTasksTimeout: 5 * 60 * 60 * 1000,
preExitCallback: async () => {
if (process.env.NODE_ENV === 'production' && process.env.FOREVER_UID) {
await promisify(spawn)('forever', ['stop', process.env.FOREVER_UID], { detached: true });
// wait 2 sec for "Forever" to stop the process
utils.delay(2000);
}
},
});
});
finalErrorHandler(error => shutdownProcess({ error }));
blockedHandler();