2023-02-10 05:59:20 -08:00
import { Command } from '@oclif/command' ;
2023-02-10 07:34:39 -08:00
import { ExitError } from '@oclif/errors' ;
2023-02-21 10:21:56 -08:00
import { Container } from 'typedi' ;
2023-02-10 05:59:20 -08:00
import { LoggerProxy , ErrorReporterProxy as ErrorReporter , sleep } from 'n8n-workflow' ;
import type { IUserSettings } from 'n8n-core' ;
import { BinaryDataManager , UserSettings } from 'n8n-core' ;
2023-05-10 01:27:04 -07:00
import type { AbstractServer } from '@/AbstractServer' ;
2023-01-27 05:56:56 -08:00
import { getLogger } from '@/Logger' ;
2023-02-10 05:59:20 -08:00
import config from '@/config' ;
2022-11-09 06:25:00 -08:00
import * as Db from '@/Db' ;
2023-02-10 05:59:20 -08:00
import * as CrashJournal from '@/CrashJournal' ;
2023-06-07 07:53:53 -07:00
import { inTest } from '@/constants' ;
2023-02-10 05:59:20 -08:00
import { CredentialTypes } from '@/CredentialTypes' ;
import { CredentialsOverwrites } from '@/CredentialsOverwrites' ;
import { initErrorHandling } from '@/ErrorReporting' ;
import { ExternalHooks } from '@/ExternalHooks' ;
import { NodeTypes } from '@/NodeTypes' ;
import { LoadNodesAndCredentials } from '@/LoadNodesAndCredentials' ;
import type { IExternalHooksClass } from '@/Interfaces' ;
2023-02-21 10:21:56 -08:00
import { InternalHooks } from '@/InternalHooks' ;
2023-02-21 00:35:35 -08:00
import { PostHogClient } from '@/posthog' ;
2023-05-23 04:01:50 -07:00
import { License } from '@/License' ;
2023-08-25 01:33:46 -07:00
import { ExternalSecretsManager } from '@/ExternalSecrets/ExternalSecretsManager.ee' ;
2023-02-10 05:59:20 -08:00
2022-06-25 21:03:46 -07:00
export abstract class BaseCommand extends Command {
2023-02-10 05:59:20 -08:00
protected logger = LoggerProxy . init ( getLogger ( ) ) ;
protected externalHooks : IExternalHooksClass ;
2023-02-21 10:21:56 -08:00
protected loadNodesAndCredentials : LoadNodesAndCredentials ;
2023-02-10 05:59:20 -08:00
2023-05-11 07:19:55 -07:00
protected nodeTypes : NodeTypes ;
2022-06-25 21:03:46 -07:00
2023-02-10 05:59:20 -08:00
protected userSettings : IUserSettings ;
2022-06-25 21:03:46 -07:00
2023-03-10 10:05:51 -08:00
protected instanceId : string ;
2023-05-10 01:27:04 -07:00
protected server? : AbstractServer ;
2022-06-25 21:03:46 -07:00
async init ( ) : Promise < void > {
2023-02-10 05:59:20 -08:00
await initErrorHandling ( ) ;
2022-06-25 21:03:46 -07:00
2023-02-10 07:34:39 -08:00
process . once ( 'SIGTERM' , async ( ) = > this . stopProcess ( ) ) ;
process . once ( 'SIGINT' , async ( ) = > this . stopProcess ( ) ) ;
2022-06-25 21:03:46 -07:00
2023-02-10 05:59:20 -08:00
// Make sure the settings exist
this . userSettings = await UserSettings . prepareUserSettings ( ) ;
2022-06-25 21:03:46 -07:00
2023-02-21 10:21:56 -08:00
this . loadNodesAndCredentials = Container . get ( LoadNodesAndCredentials ) ;
2023-02-10 05:59:20 -08:00
await this . loadNodesAndCredentials . init ( ) ;
2023-02-21 10:21:56 -08:00
this . nodeTypes = Container . get ( NodeTypes ) ;
2023-05-11 07:19:55 -07:00
this . nodeTypes . init ( ) ;
2023-02-21 10:21:56 -08:00
const credentialTypes = Container . get ( CredentialTypes ) ;
2023-02-10 05:59:20 -08:00
CredentialsOverwrites ( credentialTypes ) ;
2022-06-25 21:03:46 -07:00
2023-02-10 05:59:20 -08:00
await Db . init ( ) . catch ( async ( error : Error ) = >
this . exitWithCrash ( 'There was an error initializing DB' , error ) ,
) ;
2023-04-12 01:59:14 -07:00
2023-05-10 01:27:04 -07:00
await this . server ? . init ( ) ;
await Db . migrate ( ) . catch ( async ( error : Error ) = >
this . exitWithCrash ( 'There was an error running database migrations' , error ) ,
) ;
2023-05-08 03:16:20 -07:00
const dbType = config . getEnv ( 'database.type' ) ;
if ( [ 'mysqldb' , 'mariadb' ] . includes ( dbType ) ) {
LoggerProxy . warn (
'Support for MySQL/MariaDB has been deprecated and will be removed with an upcoming version of n8n. Please migrate to PostgreSQL.' ,
) ;
}
2023-05-08 06:03:44 -07:00
if ( process . env . EXECUTIONS_PROCESS === 'own' ) {
LoggerProxy . warn (
'Own mode has been deprecated and will be removed in a future version of n8n. If you need the isolation and performance gains, please consider using queue mode.' ,
) ;
}
2023-05-08 03:16:20 -07:00
2023-04-12 01:59:14 -07:00
this . instanceId = this . userSettings . instanceId ? ? '' ;
await Container . get ( PostHogClient ) . init ( this . instanceId ) ;
await Container . get ( InternalHooks ) . init ( this . instanceId ) ;
2023-02-10 05:59:20 -08:00
}
2022-06-25 21:03:46 -07:00
2023-02-10 05:59:20 -08:00
protected async stopProcess() {
// This needs to be overridden
}
2022-06-25 21:03:46 -07:00
2023-02-10 05:59:20 -08:00
protected async initCrashJournal() {
await CrashJournal . init ( ) ;
}
2022-06-25 21:03:46 -07:00
2023-02-10 05:59:20 -08:00
protected async exitSuccessFully() {
try {
await CrashJournal . cleanup ( ) ;
} finally {
process . exit ( ) ;
}
}
2022-06-25 21:03:46 -07:00
2023-02-10 05:59:20 -08:00
protected async exitWithCrash ( message : string , error : unknown ) {
ErrorReporter . error ( new Error ( message , { cause : error } ) , { level : 'fatal' } ) ;
await sleep ( 2000 ) ;
process . exit ( 1 ) ;
}
2022-06-25 21:03:46 -07:00
2023-02-10 05:59:20 -08:00
protected async initBinaryManager() {
const binaryDataConfig = config . getEnv ( 'binaryDataManager' ) ;
await BinaryDataManager . init ( binaryDataConfig , true ) ;
}
2022-06-25 21:03:46 -07:00
2023-02-10 05:59:20 -08:00
protected async initExternalHooks() {
2023-02-21 10:21:56 -08:00
this . externalHooks = Container . get ( ExternalHooks ) ;
2023-02-10 05:59:20 -08:00
await this . externalHooks . init ( ) ;
}
2022-06-25 21:03:46 -07:00
2023-05-23 04:01:50 -07:00
async initLicense ( ) : Promise < void > {
const license = Container . get ( License ) ;
await license . init ( this . instanceId ) ;
const activationKey = config . getEnv ( 'license.activationKey' ) ;
if ( activationKey ) {
const hasCert = ( await license . loadCertStr ( ) ) . length > 0 ;
if ( hasCert ) {
return LoggerProxy . debug ( 'Skipping license activation' ) ;
}
try {
LoggerProxy . debug ( 'Attempting license activation' ) ;
await license . activate ( activationKey ) ;
} catch ( e ) {
LoggerProxy . error ( 'Could not activate license' , e as Error ) ;
}
}
}
2023-08-25 01:33:46 -07:00
async initExternalSecrets() {
const secretsManager = Container . get ( ExternalSecretsManager ) ;
await secretsManager . init ( ) ;
}
2023-02-10 05:59:20 -08:00
async finally ( error : Error | undefined ) {
if ( inTest || this . id === 'start' ) return ;
2023-05-10 01:27:04 -07:00
if ( Db . connectionState . connected ) {
2023-02-10 07:34:39 -08:00
await sleep ( 100 ) ; // give any in-flight query some time to finish
2023-05-10 01:27:04 -07:00
await Db . close ( ) ;
2023-02-10 07:34:39 -08:00
}
const exitCode = error instanceof ExitError ? error.oclif.exit : error ? 1 : 0 ;
this . exit ( exitCode ) ;
2022-06-25 21:03:46 -07:00
}
}