2023-02-10 05:59:20 -08:00
|
|
|
import { flags } from '@oclif/command';
|
|
|
|
import { LoggerProxy, sleep } from 'n8n-workflow';
|
2022-11-09 06:25:00 -08:00
|
|
|
import config from '@/config';
|
2023-02-21 10:21:56 -08:00
|
|
|
import { ActiveExecutions } from '@/ActiveExecutions';
|
2023-01-04 02:38:48 -08:00
|
|
|
import { WebhookServer } from '@/WebhookServer';
|
2023-03-24 02:47:21 -07:00
|
|
|
import { Queue } from '@/Queue';
|
2023-02-10 05:59:20 -08:00
|
|
|
import { BaseCommand } from './BaseCommand';
|
2023-02-21 10:21:56 -08:00
|
|
|
import { Container } from 'typedi';
|
2021-02-09 14:32:40 -08:00
|
|
|
|
2023-02-10 05:59:20 -08:00
|
|
|
export class Webhook extends BaseCommand {
|
2021-02-09 14:32:40 -08:00
|
|
|
static description = 'Starts n8n webhook process. Intercepts only production URLs.';
|
|
|
|
|
2022-12-29 03:20:43 -08:00
|
|
|
static examples = ['$ n8n webhook'];
|
2021-02-09 14:32:40 -08:00
|
|
|
|
|
|
|
static flags = {
|
|
|
|
help: flags.help({ char: 'h' }),
|
|
|
|
};
|
|
|
|
|
2023-05-10 01:27:04 -07:00
|
|
|
protected server = new WebhookServer();
|
|
|
|
|
2021-02-09 14:32:40 -08:00
|
|
|
/**
|
2022-11-08 08:06:00 -08:00
|
|
|
* Stops n8n in a graceful way.
|
2021-02-09 14:32:40 -08:00
|
|
|
* Make for example sure that all the webhooks from third party services
|
|
|
|
* get removed.
|
|
|
|
*/
|
2023-02-10 05:59:20 -08:00
|
|
|
async stopProcess() {
|
2022-12-29 03:20:43 -08:00
|
|
|
LoggerProxy.info('\nStopping n8n...');
|
2021-02-09 14:32:40 -08:00
|
|
|
|
|
|
|
try {
|
2023-02-10 05:59:20 -08:00
|
|
|
await this.externalHooks.run('n8n.stop', []);
|
2021-02-09 14:32:40 -08:00
|
|
|
|
2023-01-11 09:28:35 -08:00
|
|
|
setTimeout(async () => {
|
2021-02-09 14:32:40 -08:00
|
|
|
// In case that something goes wrong with shutdown we
|
|
|
|
// kill after max. 30 seconds no matter what
|
2023-02-10 05:59:20 -08:00
|
|
|
await this.exitSuccessFully();
|
2021-02-09 14:32:40 -08:00
|
|
|
}, 30000);
|
|
|
|
|
|
|
|
// Wait for active workflow executions to finish
|
2023-02-21 10:21:56 -08:00
|
|
|
const activeExecutionsInstance = Container.get(ActiveExecutions);
|
2021-02-09 14:32:40 -08:00
|
|
|
let executingWorkflows = activeExecutionsInstance.getActiveExecutions();
|
|
|
|
|
|
|
|
let count = 0;
|
|
|
|
while (executingWorkflows.length !== 0) {
|
|
|
|
if (count++ % 4 === 0) {
|
2021-05-01 20:43:01 -07:00
|
|
|
LoggerProxy.info(
|
|
|
|
`Waiting for ${executingWorkflows.length} active executions to finish...`,
|
|
|
|
);
|
2021-02-09 14:32:40 -08:00
|
|
|
}
|
2023-07-31 02:00:48 -07:00
|
|
|
|
2022-11-08 08:06:00 -08:00
|
|
|
await sleep(500);
|
2021-02-09 14:32:40 -08:00
|
|
|
executingWorkflows = activeExecutionsInstance.getActiveExecutions();
|
|
|
|
}
|
|
|
|
} catch (error) {
|
2023-02-10 05:59:20 -08:00
|
|
|
await this.exitWithCrash('There was an error shutting down n8n.', error);
|
2021-02-09 14:32:40 -08:00
|
|
|
}
|
|
|
|
|
2023-02-10 05:59:20 -08:00
|
|
|
await this.exitSuccessFully();
|
2021-02-09 14:32:40 -08:00
|
|
|
}
|
|
|
|
|
2023-02-10 05:59:20 -08:00
|
|
|
async init() {
|
2023-01-04 02:38:48 -08:00
|
|
|
if (config.getEnv('executions.mode') !== 'queue') {
|
|
|
|
/**
|
|
|
|
* It is technically possible to run without queues but
|
|
|
|
* there are 2 known bugs when running in this mode:
|
|
|
|
* - Executions list will be problematic as the main process
|
|
|
|
* is not aware of current executions in the webhook processes
|
|
|
|
* and therefore will display all current executions as error
|
|
|
|
* as it is unable to determine if it is still running or crashed
|
|
|
|
* - You cannot stop currently executing jobs from webhook processes
|
|
|
|
* when running without queues as the main process cannot talk to
|
|
|
|
* the webhook processes to communicate workflow execution interruption.
|
|
|
|
*/
|
|
|
|
|
|
|
|
this.error('Webhook processes can only run with execution mode as queue.');
|
|
|
|
}
|
|
|
|
|
2023-02-10 05:59:20 -08:00
|
|
|
await this.initCrashJournal();
|
|
|
|
await super.init();
|
2021-02-09 14:32:40 -08:00
|
|
|
|
2023-09-17 02:05:54 -07:00
|
|
|
await this.initLicense('webhook');
|
2023-09-22 08:22:12 -07:00
|
|
|
await this.initBinaryDataService();
|
2023-02-10 05:59:20 -08:00
|
|
|
await this.initExternalHooks();
|
2023-08-25 01:33:46 -07:00
|
|
|
await this.initExternalSecrets();
|
2023-02-10 05:59:20 -08:00
|
|
|
}
|
2023-01-04 02:38:48 -08:00
|
|
|
|
2023-02-10 05:59:20 -08:00
|
|
|
async run() {
|
2023-03-24 02:47:21 -07:00
|
|
|
await Container.get(Queue).init();
|
2023-05-10 01:27:04 -07:00
|
|
|
await this.server.start();
|
2023-08-07 08:03:21 -07:00
|
|
|
this.logger.debug(`Webhook listener ID: ${this.server.uniqueInstanceId}`);
|
2023-02-10 05:59:20 -08:00
|
|
|
this.logger.info('Webhook listener waiting for requests.');
|
2023-02-11 07:46:10 -08:00
|
|
|
|
|
|
|
// Make sure that the process does not close
|
|
|
|
await new Promise(() => {});
|
2023-02-10 05:59:20 -08:00
|
|
|
}
|
2023-01-04 02:38:48 -08:00
|
|
|
|
2023-02-10 05:59:20 -08:00
|
|
|
async catch(error: Error) {
|
|
|
|
await this.exitWithCrash('Exiting due to an error.', error);
|
2021-02-09 14:32:40 -08:00
|
|
|
}
|
|
|
|
}
|