-
Notifications
You must be signed in to change notification settings - Fork 9.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: Encapsulate task runner startup to module (#11531)
- Loading branch information
Showing
13 changed files
with
224 additions
and
50 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 16 additions & 0 deletions
16
packages/cli/src/runners/default-task-runner-disconnect-analyzer.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { Service } from 'typedi'; | ||
|
||
import { TaskRunnerDisconnectedError } from './errors/task-runner-disconnected-error'; | ||
import type { DisconnectAnalyzer } from './runner-types'; | ||
import type { TaskRunner } from './task-broker.service'; | ||
|
||
/** | ||
* Analyzes the disconnect reason of a task runner to provide a more | ||
* meaningful error message to the user. | ||
*/ | ||
@Service() | ||
export class DefaultTaskRunnerDisconnectAnalyzer implements DisconnectAnalyzer { | ||
async determineDisconnectReason(runnerId: TaskRunner['id']): Promise<Error> { | ||
return new TaskRunnerDisconnectedError(runnerId); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import { TaskRunnersConfig } from '@n8n/config'; | ||
import * as a from 'node:assert/strict'; | ||
import Container, { Service } from 'typedi'; | ||
|
||
import type { TaskRunnerProcess } from '@/runners/task-runner-process'; | ||
|
||
import { TaskRunnerWsServer } from './runner-ws-server'; | ||
import type { LocalTaskManager } from './task-managers/local-task-manager'; | ||
import type { TaskRunnerServer } from './task-runner-server'; | ||
|
||
/** | ||
* Module responsible for loading and starting task runner. Task runner can be | ||
* run either internally (=launched by n8n as a child process) or externally | ||
* (=launched by some other orchestrator) | ||
*/ | ||
@Service() | ||
export class TaskRunnerModule { | ||
private taskRunnerHttpServer: TaskRunnerServer | undefined; | ||
|
||
private taskRunnerWsServer: TaskRunnerWsServer | undefined; | ||
|
||
private taskManager: LocalTaskManager | undefined; | ||
|
||
private taskRunnerProcess: TaskRunnerProcess | undefined; | ||
|
||
constructor(private readonly runnerConfig: TaskRunnersConfig) {} | ||
|
||
async start() { | ||
a.ok(!this.runnerConfig.disabled, 'Task runner is disabled'); | ||
|
||
await this.loadTaskManager(); | ||
await this.loadTaskRunnerServer(); | ||
|
||
if ( | ||
this.runnerConfig.mode === 'internal_childprocess' || | ||
this.runnerConfig.mode === 'internal_launcher' | ||
) { | ||
await this.startInternalTaskRunner(); | ||
} | ||
} | ||
|
||
async stop() { | ||
if (this.taskRunnerProcess) { | ||
await this.taskRunnerProcess.stop(); | ||
this.taskRunnerProcess = undefined; | ||
} | ||
|
||
if (this.taskRunnerHttpServer) { | ||
await this.taskRunnerHttpServer.stop(); | ||
this.taskRunnerHttpServer = undefined; | ||
} | ||
} | ||
|
||
private async loadTaskManager() { | ||
const { TaskManager } = await import('@/runners/task-managers/task-manager'); | ||
const { LocalTaskManager } = await import('@/runners/task-managers/local-task-manager'); | ||
this.taskManager = new LocalTaskManager(); | ||
Container.set(TaskManager, this.taskManager); | ||
} | ||
|
||
private async loadTaskRunnerServer() { | ||
// These are imported dynamically because we need to set the task manager | ||
// instance before importing them | ||
const { TaskRunnerServer } = await import('@/runners/task-runner-server'); | ||
this.taskRunnerHttpServer = Container.get(TaskRunnerServer); | ||
this.taskRunnerWsServer = Container.get(TaskRunnerWsServer); | ||
|
||
await this.taskRunnerHttpServer.start(); | ||
} | ||
|
||
private async startInternalTaskRunner() { | ||
a.ok(this.taskRunnerWsServer, 'Task Runner WS Server not loaded'); | ||
|
||
const { TaskRunnerProcess } = await import('@/runners/task-runner-process'); | ||
this.taskRunnerProcess = Container.get(TaskRunnerProcess); | ||
await this.taskRunnerProcess.start(); | ||
|
||
const { InternalTaskRunnerDisconnectAnalyzer } = await import( | ||
'@/runners/internal-task-runner-disconnect-analyzer' | ||
); | ||
this.taskRunnerWsServer.setDisconnectAnalyzer( | ||
Container.get(InternalTaskRunnerDisconnectAnalyzer), | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
40 changes: 40 additions & 0 deletions
40
packages/cli/test/integration/runners/task-runner-module.external.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import { TaskRunnersConfig } from '@n8n/config'; | ||
import Container from 'typedi'; | ||
|
||
import { TaskRunnerModule } from '@/runners/task-runner-module'; | ||
|
||
import { DefaultTaskRunnerDisconnectAnalyzer } from '../../../src/runners/default-task-runner-disconnect-analyzer'; | ||
import { TaskRunnerWsServer } from '../../../src/runners/runner-ws-server'; | ||
|
||
describe('TaskRunnerModule in external mode', () => { | ||
const runnerConfig = Container.get(TaskRunnersConfig); | ||
runnerConfig.mode = 'external'; | ||
runnerConfig.port = 0; | ||
const module = Container.get(TaskRunnerModule); | ||
|
||
afterEach(async () => { | ||
await module.stop(); | ||
}); | ||
|
||
describe('start', () => { | ||
it('should throw if the task runner is disabled', async () => { | ||
runnerConfig.disabled = true; | ||
|
||
// Act | ||
await expect(module.start()).rejects.toThrow('Task runner is disabled'); | ||
}); | ||
|
||
it('should start the task runner', async () => { | ||
runnerConfig.disabled = false; | ||
|
||
// Act | ||
await module.start(); | ||
}); | ||
|
||
it('should use DefaultTaskRunnerDisconnectAnalyzer', () => { | ||
const wsServer = Container.get(TaskRunnerWsServer); | ||
|
||
expect(wsServer.getDisconnectAnalyzer()).toBeInstanceOf(DefaultTaskRunnerDisconnectAnalyzer); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.