@splitsoftware/splitio-commons
Version:
Split JavaScript SDK common components
79 lines (66 loc) • 2.51 kB
text/typescript
// @TODO eventually migrate to Node.js SDK package.
import { ISignalListener } from './types';
import { thenable } from '../utils/promise/thenable';
import { MaybeThenable } from '../dtos/types';
import { ISettings } from '../types';
import { LOG_PREFIX_CLEANUP, CLEANUP_REGISTERING, CLEANUP_DEREGISTERING } from '../logger/constants';
import { ISdkFactoryContext } from '../sdkFactory/types';
const SIGTERM = 'SIGTERM';
const EVENT_NAME = 'for SIGTERM signal.';
/**
* We'll listen for SIGTERM since it's the standard signal for server shutdown.
*
* If you're stopping the execution yourself via the keyboard, or by calling process.exit,
* you should call the cleanup logic yourself, since we cannot ensure the data is sent after
* the process is already exiting.
*/
export class NodeSignalListener implements ISignalListener {
private handler: () => MaybeThenable<any>;
private settings: ISettings;
constructor({ syncManager, settings }: ISdkFactoryContext) {
// @TODO review handler logic when implementing Node.js SDK
this.handler = function () {
if (syncManager) {
// syncManager.stop();
return syncManager.flush();
}
};
this.settings = settings;
this._sigtermHandler = this._sigtermHandler.bind(this);
}
start() {
this.settings.log.debug(CLEANUP_REGISTERING, [EVENT_NAME]);
// eslint-disable-next-line no-undef
process.on(SIGTERM, this._sigtermHandler);
}
stop() {
this.settings.log.debug(CLEANUP_DEREGISTERING, [EVENT_NAME]);
// eslint-disable-next-line no-undef
process.removeListener(SIGTERM, this._sigtermHandler);
}
/**
* Call the handler, clean up listeners and emit the signal again.
*/
private _sigtermHandler(): MaybeThenable<void> {
const wrapUp = () => {
// Cleaned up, remove handlers.
this.stop();
// This handler prevented the default behavior, start again.
// eslint-disable-next-line no-undef
process.kill(process.pid, SIGTERM);
};
this.settings.log.debug(`${LOG_PREFIX_CLEANUP}SDK graceful shutdown after SIGTERM.`);
let handlerResult = null;
try {
handlerResult = this.handler();
} catch (err) {
this.settings.log.error(`${LOG_PREFIX_CLEANUP}Error with SDK graceful shutdown: ${err}`);
}
if (thenable(handlerResult)) {
// Always exit, even with errors. The promise is returned for UT purposes.
return handlerResult.then(wrapUp).catch(wrapUp);
} else {
wrapUp();
}
}
}