Skip to content

Commit a4e07ce

Browse files
committed
sentinel: Add process handling for uncaught exceptions
1 parent 71eca99 commit a4e07ce

4 files changed

Lines changed: 31 additions & 3 deletions

File tree

src/sentinel/hotpatch.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,14 @@ export async function hotpatch(this: Sentinel, hotpatchType: HotpatchType, by: s
4747
case 'sentinel': {
4848
cachebust('@/sentinel/create');
4949
cachebust('@/sentinel/hotpatch');
50+
cachebust('@/sentinel/process');
5051
await cachebustDir(fsPath('sentinel', 'registers'));
5152
const newSentinel = await import('@/sentinel/create');
5253
this.sentinel.close();
54+
this.process.kill();
5355
this.sentinel = newSentinel.create(this.emitter);
5456
this.hotpatch = (await import('@/sentinel/hotpatch')).hotpatch;
57+
this.process = (await import('@/sentinel/process')).processHandler();
5558
break;
5659
}
5760

src/sentinel/index.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import EventEmitter from 'events';
22

33
import { create } from '@/sentinel/create';
44
import { hotpatch } from '@/sentinel/hotpatch';
5+
import { processHandler } from '@/sentinel/process';
56
import { Sentinel } from '@/sentinel/types';
67
import { log } from '@/utils/logger';
78

@@ -13,11 +14,12 @@ const sentinel = create(emitter);
1314
emitter.on('complete', (label, files) => {
1415
log(`Reloaded ${label} with ${files.join(', ')}`);
1516
});
16-
1717
emitter.on('error', (err, label, files) => {
1818
log(`Ran into an error while reloading ${label} for ${files.join(', ')}`, err);
1919
});
2020

21-
const Sentinel: Sentinel = { hotpatch, sentinel, emitter };
21+
const process = processHandler();
22+
23+
const Sentinel: Sentinel = { hotpatch, sentinel, emitter, process };
2224

2325
export default Sentinel;

src/sentinel/process.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { errorLog, log } from '@/utils/logger';
2+
3+
export function processHandler(): { kill: () => void } {
4+
function errorHandler(err: Error, origin: NodeJS.UncaughtExceptionOrigin) {
5+
errorLog(err);
6+
log(`Error (${err.message}) thrown (${origin})`);
7+
// Everything I've read says this should exit the process
8+
// Unfortunately, I like living life on the edge
9+
// We stay alive!
10+
}
11+
function rejectionHandler(promise: unknown, reasonPromise: Promise<unknown>) {
12+
reasonPromise.then(reason => errorLog(new Error(`Promise failed with reason ${reason}`)));
13+
}
14+
process.on('uncaughtException', errorHandler);
15+
process.on('unhandledRejection', rejectionHandler);
16+
17+
return {
18+
kill: () => {
19+
process.removeListener('uncaughtException', errorHandler);
20+
process.removeListener('unhandledRejection', rejectionHandler);
21+
},
22+
};
23+
}

src/sentinel/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export interface Emitter extends EventEmitter {
1313
emit<K extends keyof EmitterEvents>(event: K, ...args: EmitterEvents[K]): boolean;
1414
on<K extends keyof EmitterEvents>(event: K, listener: (...args: EmitterEvents[K]) => void): this;
1515
}
16-
export type Sentinel = { emitter: Emitter; sentinel: FSWatcher; hotpatch: typeof hotpatch };
16+
export type Sentinel = { emitter: Emitter; sentinel: FSWatcher; hotpatch: typeof hotpatch; process: { kill: () => void } };
1717

1818
export type Register = { label: string; pattern: RegExp; reload: (filepaths: string[]) => Promise<void> | void; debounce?: number };
1919
export type Listener = { label: string; pattern: RegExp; reload: (filepaths: string) => Promise<void> | void };

0 commit comments

Comments
 (0)