DC-067: harden shutdown per Codex C-grade feedback

- Logger validation now requires info/warn/error (was info-only)
- Force-exit timer now survives manager stop drain so a hung manager
  cannot trap the process in half-shutdown
- installSignalHandlers is now actually idempotent — tracks installed
  signals on coordinator and skips duplicates
This commit is contained in:
hermes
2026-08-12 03:52:34 -07:00
parent bb01a77ae7
commit 5b74536472
2 changed files with 55 additions and 7 deletions
@@ -70,12 +70,23 @@ describe('ShutdownCoordinator (DC-067)', () => {
test('throws if log is missing or invalid', () => {
expect(() => createShutdownCoordinator({ server: makeFakeServer(), managers: [] }))
.toThrow('log with info/warn is required');
.toThrow('log must have info');
expect(() => createShutdownCoordinator({
server: makeFakeServer(),
log: { foo: 'bar' },
managers: [],
})).toThrow('log with info/warn is required');
})).toThrow('log must have info');
expect(() => createShutdownCoordinator({
server: makeFakeServer(),
log: { info: () => {}, warn: () => {} }, // missing error
managers: [],
})).toThrow('log must have info');
// A log with all three methods should NOT throw.
expect(() => createShutdownCoordinator({
server: makeFakeServer(),
log: { info: () => {}, warn: () => {}, error: () => {} },
managers: [],
})).not.toThrow();
});
test('uses DEFAULT_DRAIN_TIMEOUT_MS when drainTimeoutMs is not finite positive', () => {
@@ -350,5 +361,24 @@ describe('ShutdownCoordinator (DC-067)', () => {
process.emit('SIGHUP');
expect(shutdownSpy).toHaveBeenCalledWith('SIGHUP');
});
test('is idempotent — calling installSignalHandlers twice does not double-register', () => {
const c = createShutdownCoordinator({
server: makeFakeServer(),
log: makeFakeLog(),
managers: [],
});
const shutdownSpy = jest.spyOn(c, 'shutdown');
installSignalHandlers(c);
installSignalHandlers(c); // second call
installSignalHandlers(c); // third call
// The installedSignals tracker should have one entry per signal.
expect(c._installedSignals).toEqual(['SIGTERM', 'SIGINT']);
process.emit('SIGTERM');
expect(shutdownSpy).toHaveBeenCalledTimes(1);
});
});
});