n8n/packages/@n8n/task-runner/src/start.ts

77 lines
2 KiB
TypeScript

import { ensureError, setGlobalState } from 'n8n-workflow';
import Container from 'typedi';
import { MainConfig } from './config/main-config';
import type { ErrorReporter } from './error-reporter';
import type { HealthcheckServer } from './healthcheck-server';
import { JsTaskRunner } from './js-task-runner/js-task-runner';
let healthcheckServer: HealthcheckServer | undefined;
let runner: JsTaskRunner | undefined;
let isShuttingDown = false;
let errorReporter: ErrorReporter | undefined;
function createSignalHandler(signal: string) {
return async function onSignal() {
if (isShuttingDown) {
return;
}
console.log(`Received ${signal} signal, shutting down...`);
isShuttingDown = true;
try {
if (runner) {
await runner.stop();
runner = undefined;
void healthcheckServer?.stop();
}
if (errorReporter) {
await errorReporter.stop();
errorReporter = undefined;
}
} catch (e) {
const error = ensureError(e);
console.error('Error stopping task runner', { error });
} finally {
console.log('Task runner stopped');
process.exit(0);
}
};
}
void (async function start() {
const config = Container.get(MainConfig);
setGlobalState({
defaultTimezone: config.baseRunnerConfig.timezone,
});
if (config.sentryConfig.sentryDsn) {
const { ErrorReporter } = await import('@/error-reporter');
errorReporter = new ErrorReporter(config.sentryConfig);
await errorReporter.start();
}
runner = new JsTaskRunner(config);
runner.on('runner:reached-idle-timeout', () => {
void createSignalHandler('IDLE_TIMEOUT')();
});
const { enabled, host, port } = config.baseRunnerConfig.healthcheckServer;
if (enabled) {
const { HealthcheckServer } = await import('./healthcheck-server');
healthcheckServer = new HealthcheckServer();
await healthcheckServer.start(host, port);
}
process.on('SIGINT', createSignalHandler('SIGINT'));
process.on('SIGTERM', createSignalHandler('SIGTERM'));
})().catch((e) => {
const error = ensureError(e);
console.error('Task runner failed to start', { error });
process.exit(1);
});