Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ulixee
GitHub Repository: ulixee/secret-agent
Path: blob/main/commons/ShutdownHandler.ts
1028 views
1
import logger from './Logger';
2
import { CanceledPromiseError } from './interfaces/IPendingWaitEvent';
3
4
type ShutdownSignal = NodeJS.Signals | 'exit';
5
6
const { log } = logger(module);
7
8
export default class ShutdownHandler {
9
public static exitOnSignal = false;
10
11
private static isRegistered = false;
12
private static hasRunHandlers = false;
13
private static readonly onShutdownFns: {
14
fn: (signal?: ShutdownSignal) => Promise<any>;
15
callsite: string;
16
}[] = [];
17
18
public static register(onShutdownFn: (signal?: ShutdownSignal) => Promise<any>): void {
19
this.registerSignals();
20
const callsite = new Error().stack.split(/\r?\n/).slice(2, 3).shift().trim();
21
this.onShutdownFns.push({ fn: onShutdownFn, callsite });
22
}
23
24
public static async shutdown(exitProcess: boolean): Promise<void> {
25
await this.onSignal('exit');
26
if (exitProcess) process.exit(0);
27
}
28
29
private static registerSignals(): void {
30
if (!this.isRegistered) {
31
this.isRegistered = true;
32
process.once('exit' as any, code => ShutdownHandler.onSignal('exit', code));
33
process.once('SIGTERM', ShutdownHandler.onSignal.bind(this));
34
process.once('SIGINT', ShutdownHandler.onSignal.bind(this));
35
process.once('SIGQUIT', ShutdownHandler.onSignal.bind(this));
36
}
37
}
38
39
private static async onSignal(signal: ShutdownSignal, code?: number): Promise<void> {
40
if (this.hasRunHandlers) return;
41
this.hasRunHandlers = true;
42
const parentLogId = log.stats('ShutdownHandler.onSignal', {
43
signal,
44
sessionId: null,
45
});
46
47
while (this.onShutdownFns.length) {
48
const entry = this.onShutdownFns.shift();
49
50
log.stats('ShutdownHandler.execute', {
51
signal,
52
fn: entry.fn.toString(),
53
callsite: entry.callsite,
54
sessionId: null,
55
});
56
try {
57
await entry.fn(signal);
58
} catch (error) {
59
if (error instanceof CanceledPromiseError) continue;
60
log.warn('ShutdownHandler.errorShuttingDown', {
61
error,
62
sessionId: null,
63
});
64
}
65
}
66
67
log.stats('ShutdownHandler.shutdownComplete', {
68
signal,
69
exiting: this.exitOnSignal,
70
sessionId: null,
71
parentLogId,
72
});
73
74
if (this.exitOnSignal) {
75
process.exit(code ?? 1);
76
}
77
}
78
}
79
80