mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-24 20:24:05 -08:00
refactor: Move runner types to runner package (#11552)
This commit is contained in:
parent
6854f94875
commit
3edecffd71
|
@ -17,10 +17,22 @@
|
||||||
},
|
},
|
||||||
"main": "dist/start.js",
|
"main": "dist/start.js",
|
||||||
"module": "src/start.ts",
|
"module": "src/start.ts",
|
||||||
"types": "dist/start.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
"files": [
|
"files": [
|
||||||
"dist/**/*"
|
"dist/**/*"
|
||||||
],
|
],
|
||||||
|
"exports": {
|
||||||
|
"./start": {
|
||||||
|
"require": "./dist/start.js",
|
||||||
|
"import": "./src/start.ts",
|
||||||
|
"types": "./dist/start.d.ts"
|
||||||
|
},
|
||||||
|
".": {
|
||||||
|
"require": "./dist/index.js",
|
||||||
|
"import": "./src/index.ts",
|
||||||
|
"types": "./dist/index.d.ts"
|
||||||
|
}
|
||||||
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@n8n/config": "workspace:*",
|
"@n8n/config": "workspace:*",
|
||||||
"acorn": "8.14.0",
|
"acorn": "8.14.0",
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
export * from './task-runner';
|
export * from './task-runner';
|
||||||
export * from './runner-types';
|
export * from './runner-types';
|
||||||
|
export * from './message-types';
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import type { N8nMessage } from '../../runner-types';
|
import type { BrokerMessage } from '@/message-types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to keep track of which built-in variables are accessed in the code
|
* Class to keep track of which built-in variables are accessed in the code
|
||||||
|
@ -53,7 +53,7 @@ export class BuiltInsParserState {
|
||||||
this.needs$prevNode = true;
|
this.needs$prevNode = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
toDataRequestParams(): N8nMessage.ToRequester.TaskDataRequest['requestParams'] {
|
toDataRequestParams(): BrokerMessage.ToRequester.TaskDataRequest['requestParams'] {
|
||||||
return {
|
return {
|
||||||
dataOfNodes: this.needsAllNodes ? 'all' : Array.from(this.neededNodeNames),
|
dataOfNodes: this.needsAllNodes ? 'all' : Array.from(this.neededNodeNames),
|
||||||
env: this.needs$env,
|
env: this.needs$env,
|
||||||
|
|
204
packages/@n8n/task-runner/src/message-types.ts
Normal file
204
packages/@n8n/task-runner/src/message-types.ts
Normal file
|
@ -0,0 +1,204 @@
|
||||||
|
import type { INodeTypeBaseDescription } from 'n8n-workflow';
|
||||||
|
|
||||||
|
import type { RPC_ALLOW_LIST, TaskDataRequestParams, TaskResultData } from './runner-types';
|
||||||
|
|
||||||
|
export namespace BrokerMessage {
|
||||||
|
export namespace ToRunner {
|
||||||
|
export interface InfoRequest {
|
||||||
|
type: 'broker:inforequest';
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RunnerRegistered {
|
||||||
|
type: 'broker:runnerregistered';
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TaskOfferAccept {
|
||||||
|
type: 'broker:taskofferaccept';
|
||||||
|
taskId: string;
|
||||||
|
offerId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TaskCancel {
|
||||||
|
type: 'broker:taskcancel';
|
||||||
|
taskId: string;
|
||||||
|
reason: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TaskSettings {
|
||||||
|
type: 'broker:tasksettings';
|
||||||
|
taskId: string;
|
||||||
|
settings: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RPCResponse {
|
||||||
|
type: 'broker:rpcresponse';
|
||||||
|
callId: string;
|
||||||
|
taskId: string;
|
||||||
|
status: 'success' | 'error';
|
||||||
|
data: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TaskDataResponse {
|
||||||
|
type: 'broker:taskdataresponse';
|
||||||
|
taskId: string;
|
||||||
|
requestId: string;
|
||||||
|
data: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NodeTypes {
|
||||||
|
type: 'broker:nodetypes';
|
||||||
|
nodeTypes: INodeTypeBaseDescription[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export type All =
|
||||||
|
| InfoRequest
|
||||||
|
| TaskOfferAccept
|
||||||
|
| TaskCancel
|
||||||
|
| TaskSettings
|
||||||
|
| RunnerRegistered
|
||||||
|
| RPCResponse
|
||||||
|
| TaskDataResponse
|
||||||
|
| NodeTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace ToRequester {
|
||||||
|
export interface TaskReady {
|
||||||
|
type: 'broker:taskready';
|
||||||
|
requestId: string;
|
||||||
|
taskId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TaskDone {
|
||||||
|
type: 'broker:taskdone';
|
||||||
|
taskId: string;
|
||||||
|
data: TaskResultData;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TaskError {
|
||||||
|
type: 'broker:taskerror';
|
||||||
|
taskId: string;
|
||||||
|
error: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TaskDataRequest {
|
||||||
|
type: 'broker:taskdatarequest';
|
||||||
|
taskId: string;
|
||||||
|
requestId: string;
|
||||||
|
requestParams: TaskDataRequestParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RPC {
|
||||||
|
type: 'broker:rpc';
|
||||||
|
callId: string;
|
||||||
|
taskId: string;
|
||||||
|
name: (typeof RPC_ALLOW_LIST)[number];
|
||||||
|
params: unknown[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export type All = TaskReady | TaskDone | TaskError | TaskDataRequest | RPC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace RequesterMessage {
|
||||||
|
export namespace ToBroker {
|
||||||
|
export interface TaskSettings {
|
||||||
|
type: 'requester:tasksettings';
|
||||||
|
taskId: string;
|
||||||
|
settings: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TaskCancel {
|
||||||
|
type: 'requester:taskcancel';
|
||||||
|
taskId: string;
|
||||||
|
reason: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TaskDataResponse {
|
||||||
|
type: 'requester:taskdataresponse';
|
||||||
|
taskId: string;
|
||||||
|
requestId: string;
|
||||||
|
data: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RPCResponse {
|
||||||
|
type: 'requester:rpcresponse';
|
||||||
|
taskId: string;
|
||||||
|
callId: string;
|
||||||
|
status: 'success' | 'error';
|
||||||
|
data: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TaskRequest {
|
||||||
|
type: 'requester:taskrequest';
|
||||||
|
requestId: string;
|
||||||
|
taskType: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type All = TaskSettings | TaskCancel | RPCResponse | TaskDataResponse | TaskRequest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace RunnerMessage {
|
||||||
|
export namespace ToBroker {
|
||||||
|
export interface Info {
|
||||||
|
type: 'runner:info';
|
||||||
|
name: string;
|
||||||
|
types: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TaskAccepted {
|
||||||
|
type: 'runner:taskaccepted';
|
||||||
|
taskId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TaskRejected {
|
||||||
|
type: 'runner:taskrejected';
|
||||||
|
taskId: string;
|
||||||
|
reason: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TaskDone {
|
||||||
|
type: 'runner:taskdone';
|
||||||
|
taskId: string;
|
||||||
|
data: TaskResultData;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TaskError {
|
||||||
|
type: 'runner:taskerror';
|
||||||
|
taskId: string;
|
||||||
|
error: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TaskOffer {
|
||||||
|
type: 'runner:taskoffer';
|
||||||
|
offerId: string;
|
||||||
|
taskType: string;
|
||||||
|
validFor: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TaskDataRequest {
|
||||||
|
type: 'runner:taskdatarequest';
|
||||||
|
taskId: string;
|
||||||
|
requestId: string;
|
||||||
|
requestParams: TaskDataRequestParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RPC {
|
||||||
|
type: 'runner:rpc';
|
||||||
|
callId: string;
|
||||||
|
taskId: string;
|
||||||
|
name: (typeof RPC_ALLOW_LIST)[number];
|
||||||
|
params: unknown[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export type All =
|
||||||
|
| Info
|
||||||
|
| TaskDone
|
||||||
|
| TaskError
|
||||||
|
| TaskAccepted
|
||||||
|
| TaskRejected
|
||||||
|
| TaskOffer
|
||||||
|
| RPC
|
||||||
|
| TaskDataRequest;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,216 +1,90 @@
|
||||||
import type { INodeExecutionData, INodeTypeBaseDescription } from 'n8n-workflow';
|
import type {
|
||||||
|
EnvProviderState,
|
||||||
|
IDataObject,
|
||||||
|
IExecuteData,
|
||||||
|
IExecuteFunctions,
|
||||||
|
INode,
|
||||||
|
INodeExecutionData,
|
||||||
|
INodeParameters,
|
||||||
|
IRunExecutionData,
|
||||||
|
ITaskDataConnections,
|
||||||
|
IWorkflowExecuteAdditionalData,
|
||||||
|
Workflow,
|
||||||
|
WorkflowExecuteMode,
|
||||||
|
WorkflowParameters,
|
||||||
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies what data should be included for a task data request.
|
||||||
|
*/
|
||||||
export interface TaskDataRequestParams {
|
export interface TaskDataRequestParams {
|
||||||
dataOfNodes: string[] | 'all';
|
dataOfNodes: string[] | 'all';
|
||||||
prevNode: boolean;
|
prevNode: boolean;
|
||||||
|
/** Whether input data for the node should be included */
|
||||||
input: boolean;
|
input: boolean;
|
||||||
|
/** Whether env provider's state should be included */
|
||||||
env: boolean;
|
env: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface DataRequestResponse {
|
||||||
|
workflow: Omit<WorkflowParameters, 'nodeTypes'>;
|
||||||
|
inputData: ITaskDataConnections;
|
||||||
|
node: INode;
|
||||||
|
|
||||||
|
runExecutionData: IRunExecutionData;
|
||||||
|
runIndex: number;
|
||||||
|
itemIndex: number;
|
||||||
|
activeNodeName: string;
|
||||||
|
connectionInputData: INodeExecutionData[];
|
||||||
|
siblingParameters: INodeParameters;
|
||||||
|
mode: WorkflowExecuteMode;
|
||||||
|
envProviderState: EnvProviderState;
|
||||||
|
executeData?: IExecuteData;
|
||||||
|
defaultReturnRunIndex: number;
|
||||||
|
selfData: IDataObject;
|
||||||
|
contextNodeName: string;
|
||||||
|
additionalData: PartialAdditionalData;
|
||||||
|
}
|
||||||
|
|
||||||
export interface TaskResultData {
|
export interface TaskResultData {
|
||||||
result: INodeExecutionData[];
|
result: INodeExecutionData[];
|
||||||
customData?: Record<string, string>;
|
customData?: Record<string, string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export namespace N8nMessage {
|
export interface TaskData {
|
||||||
export namespace ToRunner {
|
executeFunctions: IExecuteFunctions;
|
||||||
export interface InfoRequest {
|
inputData: ITaskDataConnections;
|
||||||
type: 'broker:inforequest';
|
node: INode;
|
||||||
}
|
|
||||||
|
|
||||||
export interface RunnerRegistered {
|
workflow: Workflow;
|
||||||
type: 'broker:runnerregistered';
|
runExecutionData: IRunExecutionData;
|
||||||
}
|
runIndex: number;
|
||||||
|
itemIndex: number;
|
||||||
export interface TaskOfferAccept {
|
activeNodeName: string;
|
||||||
type: 'broker:taskofferaccept';
|
connectionInputData: INodeExecutionData[];
|
||||||
taskId: string;
|
siblingParameters: INodeParameters;
|
||||||
offerId: string;
|
mode: WorkflowExecuteMode;
|
||||||
}
|
envProviderState: EnvProviderState;
|
||||||
|
executeData?: IExecuteData;
|
||||||
export interface TaskCancel {
|
defaultReturnRunIndex: number;
|
||||||
type: 'broker:taskcancel';
|
selfData: IDataObject;
|
||||||
taskId: string;
|
contextNodeName: string;
|
||||||
reason: string;
|
additionalData: IWorkflowExecuteAdditionalData;
|
||||||
}
|
|
||||||
|
|
||||||
export interface TaskSettings {
|
|
||||||
type: 'broker:tasksettings';
|
|
||||||
taskId: string;
|
|
||||||
settings: unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RPCResponse {
|
|
||||||
type: 'broker:rpcresponse';
|
|
||||||
callId: string;
|
|
||||||
taskId: string;
|
|
||||||
status: 'success' | 'error';
|
|
||||||
data: unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TaskDataResponse {
|
|
||||||
type: 'broker:taskdataresponse';
|
|
||||||
taskId: string;
|
|
||||||
requestId: string;
|
|
||||||
data: unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface NodeTypes {
|
|
||||||
type: 'broker:nodetypes';
|
|
||||||
nodeTypes: INodeTypeBaseDescription[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export type All =
|
|
||||||
| InfoRequest
|
|
||||||
| TaskOfferAccept
|
|
||||||
| TaskCancel
|
|
||||||
| TaskSettings
|
|
||||||
| RunnerRegistered
|
|
||||||
| RPCResponse
|
|
||||||
| TaskDataResponse
|
|
||||||
| NodeTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
export namespace ToRequester {
|
|
||||||
export interface TaskReady {
|
|
||||||
type: 'broker:taskready';
|
|
||||||
requestId: string;
|
|
||||||
taskId: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TaskDone {
|
|
||||||
type: 'broker:taskdone';
|
|
||||||
taskId: string;
|
|
||||||
data: TaskResultData;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TaskError {
|
|
||||||
type: 'broker:taskerror';
|
|
||||||
taskId: string;
|
|
||||||
error: unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TaskDataRequest {
|
|
||||||
type: 'broker:taskdatarequest';
|
|
||||||
taskId: string;
|
|
||||||
requestId: string;
|
|
||||||
requestParams: TaskDataRequestParams;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RPC {
|
|
||||||
type: 'broker:rpc';
|
|
||||||
callId: string;
|
|
||||||
taskId: string;
|
|
||||||
name: (typeof RPC_ALLOW_LIST)[number];
|
|
||||||
params: unknown[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export type All = TaskReady | TaskDone | TaskError | TaskDataRequest | RPC;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export namespace RequesterMessage {
|
export interface PartialAdditionalData {
|
||||||
export namespace ToN8n {
|
executionId?: string;
|
||||||
export interface TaskSettings {
|
restartExecutionId?: string;
|
||||||
type: 'requester:tasksettings';
|
restApiUrl: string;
|
||||||
taskId: string;
|
instanceBaseUrl: string;
|
||||||
settings: unknown;
|
formWaitingBaseUrl: string;
|
||||||
}
|
webhookBaseUrl: string;
|
||||||
|
webhookWaitingBaseUrl: string;
|
||||||
export interface TaskCancel {
|
webhookTestBaseUrl: string;
|
||||||
type: 'requester:taskcancel';
|
currentNodeParameters?: INodeParameters;
|
||||||
taskId: string;
|
executionTimeoutTimestamp?: number;
|
||||||
reason: string;
|
userId?: string;
|
||||||
}
|
variables: IDataObject;
|
||||||
|
|
||||||
export interface TaskDataResponse {
|
|
||||||
type: 'requester:taskdataresponse';
|
|
||||||
taskId: string;
|
|
||||||
requestId: string;
|
|
||||||
data: unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RPCResponse {
|
|
||||||
type: 'requester:rpcresponse';
|
|
||||||
taskId: string;
|
|
||||||
callId: string;
|
|
||||||
status: 'success' | 'error';
|
|
||||||
data: unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TaskRequest {
|
|
||||||
type: 'requester:taskrequest';
|
|
||||||
requestId: string;
|
|
||||||
taskType: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type All = TaskSettings | TaskCancel | RPCResponse | TaskDataResponse | TaskRequest;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export namespace RunnerMessage {
|
|
||||||
export namespace ToN8n {
|
|
||||||
export interface Info {
|
|
||||||
type: 'runner:info';
|
|
||||||
name: string;
|
|
||||||
types: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TaskAccepted {
|
|
||||||
type: 'runner:taskaccepted';
|
|
||||||
taskId: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TaskRejected {
|
|
||||||
type: 'runner:taskrejected';
|
|
||||||
taskId: string;
|
|
||||||
reason: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TaskDone {
|
|
||||||
type: 'runner:taskdone';
|
|
||||||
taskId: string;
|
|
||||||
data: TaskResultData;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TaskError {
|
|
||||||
type: 'runner:taskerror';
|
|
||||||
taskId: string;
|
|
||||||
error: unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TaskOffer {
|
|
||||||
type: 'runner:taskoffer';
|
|
||||||
offerId: string;
|
|
||||||
taskType: string;
|
|
||||||
validFor: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TaskDataRequest {
|
|
||||||
type: 'runner:taskdatarequest';
|
|
||||||
taskId: string;
|
|
||||||
requestId: string;
|
|
||||||
requestParams: TaskDataRequestParams;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RPC {
|
|
||||||
type: 'runner:rpc';
|
|
||||||
callId: string;
|
|
||||||
taskId: string;
|
|
||||||
name: (typeof RPC_ALLOW_LIST)[number];
|
|
||||||
params: unknown[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export type All =
|
|
||||||
| Info
|
|
||||||
| TaskDone
|
|
||||||
| TaskError
|
|
||||||
| TaskAccepted
|
|
||||||
| TaskRejected
|
|
||||||
| TaskOffer
|
|
||||||
| RPC
|
|
||||||
| TaskDataRequest;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const RPC_ALLOW_LIST = [
|
export const RPC_ALLOW_LIST = [
|
||||||
|
|
|
@ -2,14 +2,10 @@ import { ApplicationError, type INodeTypeDescription } from 'n8n-workflow';
|
||||||
import { nanoid } from 'nanoid';
|
import { nanoid } from 'nanoid';
|
||||||
import { type MessageEvent, WebSocket } from 'ws';
|
import { type MessageEvent, WebSocket } from 'ws';
|
||||||
|
|
||||||
import type { BaseRunnerConfig } from './config/base-runner-config';
|
import type { BaseRunnerConfig } from '@/config/base-runner-config';
|
||||||
import { TaskRunnerNodeTypes } from './node-types';
|
import type { BrokerMessage, RunnerMessage } from '@/message-types';
|
||||||
import {
|
import { TaskRunnerNodeTypes } from '@/node-types';
|
||||||
RPC_ALLOW_LIST,
|
import { RPC_ALLOW_LIST, type TaskResultData } from '@/runner-types';
|
||||||
type RunnerMessage,
|
|
||||||
type N8nMessage,
|
|
||||||
type TaskResultData,
|
|
||||||
} from './runner-types';
|
|
||||||
|
|
||||||
export interface Task<T = unknown> {
|
export interface Task<T = unknown> {
|
||||||
taskId: string;
|
taskId: string;
|
||||||
|
@ -90,7 +86,7 @@ export abstract class TaskRunner {
|
||||||
|
|
||||||
private receiveMessage = (message: MessageEvent) => {
|
private receiveMessage = (message: MessageEvent) => {
|
||||||
// eslint-disable-next-line n8n-local-rules/no-uncaught-json-parse
|
// eslint-disable-next-line n8n-local-rules/no-uncaught-json-parse
|
||||||
const data = JSON.parse(message.data as string) as N8nMessage.ToRunner.All;
|
const data = JSON.parse(message.data as string) as BrokerMessage.ToRunner.All;
|
||||||
void this.onMessage(data);
|
void this.onMessage(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -140,11 +136,11 @@ export abstract class TaskRunner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
send(message: RunnerMessage.ToN8n.All) {
|
send(message: RunnerMessage.ToBroker.All) {
|
||||||
this.ws.send(JSON.stringify(message));
|
this.ws.send(JSON.stringify(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
onMessage(message: N8nMessage.ToRunner.All) {
|
onMessage(message: BrokerMessage.ToRunner.All) {
|
||||||
switch (message.type) {
|
switch (message.type) {
|
||||||
case 'broker:inforequest':
|
case 'broker:inforequest':
|
||||||
this.send({
|
this.send({
|
||||||
|
@ -252,7 +248,7 @@ export abstract class TaskRunner {
|
||||||
this.sendOffers();
|
this.sendOffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
taskDone(taskId: string, data: RunnerMessage.ToN8n.TaskDone['data']) {
|
taskDone(taskId: string, data: RunnerMessage.ToBroker.TaskDone['data']) {
|
||||||
this.send({
|
this.send({
|
||||||
type: 'runner:taskdone',
|
type: 'runner:taskdone',
|
||||||
taskId,
|
taskId,
|
||||||
|
@ -288,7 +284,7 @@ export abstract class TaskRunner {
|
||||||
|
|
||||||
async requestData<T = unknown>(
|
async requestData<T = unknown>(
|
||||||
taskId: Task['taskId'],
|
taskId: Task['taskId'],
|
||||||
requestParams: RunnerMessage.ToN8n.TaskDataRequest['requestParams'],
|
requestParams: RunnerMessage.ToBroker.TaskDataRequest['requestParams'],
|
||||||
): Promise<T> {
|
): Promise<T> {
|
||||||
const requestId = nanoid();
|
const requestId = nanoid();
|
||||||
|
|
||||||
|
@ -314,7 +310,7 @@ export abstract class TaskRunner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async makeRpcCall(taskId: string, name: RunnerMessage.ToN8n.RPC['name'], params: unknown[]) {
|
async makeRpcCall(taskId: string, name: RunnerMessage.ToBroker.RPC['name'], params: unknown[]) {
|
||||||
const callId = nanoid();
|
const callId = nanoid();
|
||||||
|
|
||||||
const dataPromise = new Promise((resolve, reject) => {
|
const dataPromise = new Promise((resolve, reject) => {
|
||||||
|
@ -342,7 +338,7 @@ export abstract class TaskRunner {
|
||||||
|
|
||||||
handleRpcResponse(
|
handleRpcResponse(
|
||||||
callId: string,
|
callId: string,
|
||||||
status: N8nMessage.ToRunner.RPCResponse['status'],
|
status: BrokerMessage.ToRunner.RPCResponse['status'],
|
||||||
data: unknown,
|
data: unknown,
|
||||||
) {
|
) {
|
||||||
const call = this.rpcCalls.get(callId);
|
const call = this.rpcCalls.get(callId);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
import type { RunnerMessage, TaskResultData } from '@n8n/task-runner';
|
||||||
import { mock } from 'jest-mock-extended';
|
import { mock } from 'jest-mock-extended';
|
||||||
|
|
||||||
import { TaskRejectError } from '../errors';
|
import { TaskRejectError } from '../errors';
|
||||||
import type { RunnerMessage, TaskResultData } from '../runner-types';
|
|
||||||
import { TaskBroker } from '../task-broker.service';
|
import { TaskBroker } from '../task-broker.service';
|
||||||
import type { TaskOffer, TaskRequest, TaskRunner } from '../task-broker.service';
|
import type { TaskOffer, TaskRequest, TaskRunner } from '../task-broker.service';
|
||||||
|
|
||||||
|
@ -381,7 +381,7 @@ describe('TaskBroker', () => {
|
||||||
const runnerId = 'runner1';
|
const runnerId = 'runner1';
|
||||||
const taskId = 'task1';
|
const taskId = 'task1';
|
||||||
|
|
||||||
const message: RunnerMessage.ToN8n.TaskAccepted = {
|
const message: RunnerMessage.ToBroker.TaskAccepted = {
|
||||||
type: 'runner:taskaccepted',
|
type: 'runner:taskaccepted',
|
||||||
taskId,
|
taskId,
|
||||||
};
|
};
|
||||||
|
@ -406,7 +406,7 @@ describe('TaskBroker', () => {
|
||||||
const taskId = 'task1';
|
const taskId = 'task1';
|
||||||
const rejectionReason = 'Task execution failed';
|
const rejectionReason = 'Task execution failed';
|
||||||
|
|
||||||
const message: RunnerMessage.ToN8n.TaskRejected = {
|
const message: RunnerMessage.ToBroker.TaskRejected = {
|
||||||
type: 'runner:taskrejected',
|
type: 'runner:taskrejected',
|
||||||
taskId,
|
taskId,
|
||||||
reason: rejectionReason,
|
reason: rejectionReason,
|
||||||
|
@ -433,7 +433,7 @@ describe('TaskBroker', () => {
|
||||||
const requesterId = 'requester1';
|
const requesterId = 'requester1';
|
||||||
const data = mock<TaskResultData>();
|
const data = mock<TaskResultData>();
|
||||||
|
|
||||||
const message: RunnerMessage.ToN8n.TaskDone = {
|
const message: RunnerMessage.ToBroker.TaskDone = {
|
||||||
type: 'runner:taskdone',
|
type: 'runner:taskdone',
|
||||||
taskId,
|
taskId,
|
||||||
data,
|
data,
|
||||||
|
@ -464,7 +464,7 @@ describe('TaskBroker', () => {
|
||||||
const requesterId = 'requester1';
|
const requesterId = 'requester1';
|
||||||
const errorMessage = 'Task execution failed';
|
const errorMessage = 'Task execution failed';
|
||||||
|
|
||||||
const message: RunnerMessage.ToN8n.TaskError = {
|
const message: RunnerMessage.ToBroker.TaskError = {
|
||||||
type: 'runner:taskerror',
|
type: 'runner:taskerror',
|
||||||
taskId,
|
taskId,
|
||||||
error: errorMessage,
|
error: errorMessage,
|
||||||
|
@ -494,14 +494,14 @@ describe('TaskBroker', () => {
|
||||||
const taskId = 'task1';
|
const taskId = 'task1';
|
||||||
const requesterId = 'requester1';
|
const requesterId = 'requester1';
|
||||||
const requestId = 'request1';
|
const requestId = 'request1';
|
||||||
const requestParams: RunnerMessage.ToN8n.TaskDataRequest['requestParams'] = {
|
const requestParams: RunnerMessage.ToBroker.TaskDataRequest['requestParams'] = {
|
||||||
dataOfNodes: 'all',
|
dataOfNodes: 'all',
|
||||||
env: true,
|
env: true,
|
||||||
input: true,
|
input: true,
|
||||||
prevNode: true,
|
prevNode: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
const message: RunnerMessage.ToN8n.TaskDataRequest = {
|
const message: RunnerMessage.ToBroker.TaskDataRequest = {
|
||||||
type: 'runner:taskdatarequest',
|
type: 'runner:taskdatarequest',
|
||||||
taskId,
|
taskId,
|
||||||
requestId,
|
requestId,
|
||||||
|
@ -534,7 +534,7 @@ describe('TaskBroker', () => {
|
||||||
const rpcName = 'helpers.httpRequestWithAuthentication';
|
const rpcName = 'helpers.httpRequestWithAuthentication';
|
||||||
const rpcParams = ['param1', 'param2'];
|
const rpcParams = ['param1', 'param2'];
|
||||||
|
|
||||||
const message: RunnerMessage.ToN8n.RPC = {
|
const message: RunnerMessage.ToBroker.RPC = {
|
||||||
type: 'runner:rpc',
|
type: 'runner:rpc',
|
||||||
taskId,
|
taskId,
|
||||||
callId,
|
callId,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import type { Response } from 'express';
|
import type { Response } from 'express';
|
||||||
import type { INodeExecutionData, INodeTypeBaseDescription } from 'n8n-workflow';
|
import type { INodeExecutionData } from 'n8n-workflow';
|
||||||
import type WebSocket from 'ws';
|
import type WebSocket from 'ws';
|
||||||
|
|
||||||
import type { TaskRunner } from './task-broker.service';
|
import type { TaskRunner } from './task-broker.service';
|
||||||
|
@ -34,230 +34,3 @@ export interface TaskRunnerServerInitRequest
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TaskRunnerServerInitResponse = Response & { req: TaskRunnerServerInitRequest };
|
export type TaskRunnerServerInitResponse = Response & { req: TaskRunnerServerInitRequest };
|
||||||
|
|
||||||
export namespace N8nMessage {
|
|
||||||
export namespace ToRunner {
|
|
||||||
export interface InfoRequest {
|
|
||||||
type: 'broker:inforequest';
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RunnerRegistered {
|
|
||||||
type: 'broker:runnerregistered';
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TaskOfferAccept {
|
|
||||||
type: 'broker:taskofferaccept';
|
|
||||||
taskId: string;
|
|
||||||
offerId: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TaskCancel {
|
|
||||||
type: 'broker:taskcancel';
|
|
||||||
taskId: string;
|
|
||||||
reason: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TaskSettings {
|
|
||||||
type: 'broker:tasksettings';
|
|
||||||
taskId: string;
|
|
||||||
settings: unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RPCResponse {
|
|
||||||
type: 'broker:rpcresponse';
|
|
||||||
callId: string;
|
|
||||||
taskId: string;
|
|
||||||
status: 'success' | 'error';
|
|
||||||
data: unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TaskDataResponse {
|
|
||||||
type: 'broker:taskdataresponse';
|
|
||||||
taskId: string;
|
|
||||||
requestId: string;
|
|
||||||
data: unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface NodeTypes {
|
|
||||||
type: 'broker:nodetypes';
|
|
||||||
nodeTypes: INodeTypeBaseDescription[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export type All =
|
|
||||||
| InfoRequest
|
|
||||||
| TaskOfferAccept
|
|
||||||
| TaskCancel
|
|
||||||
| TaskSettings
|
|
||||||
| RunnerRegistered
|
|
||||||
| RPCResponse
|
|
||||||
| TaskDataResponse
|
|
||||||
| NodeTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
export namespace ToRequester {
|
|
||||||
export interface TaskReady {
|
|
||||||
type: 'broker:taskready';
|
|
||||||
requestId: string;
|
|
||||||
taskId: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TaskDone {
|
|
||||||
type: 'broker:taskdone';
|
|
||||||
taskId: string;
|
|
||||||
data: TaskResultData;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TaskError {
|
|
||||||
type: 'broker:taskerror';
|
|
||||||
taskId: string;
|
|
||||||
error: unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TaskDataRequest {
|
|
||||||
type: 'broker:taskdatarequest';
|
|
||||||
taskId: string;
|
|
||||||
requestId: string;
|
|
||||||
requestParams: TaskDataRequestParams;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RPC {
|
|
||||||
type: 'broker:rpc';
|
|
||||||
callId: string;
|
|
||||||
taskId: string;
|
|
||||||
name: (typeof RPC_ALLOW_LIST)[number];
|
|
||||||
params: unknown[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export type All = TaskReady | TaskDone | TaskError | TaskDataRequest | RPC;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export namespace RequesterMessage {
|
|
||||||
export namespace ToN8n {
|
|
||||||
export interface TaskSettings {
|
|
||||||
type: 'requester:tasksettings';
|
|
||||||
taskId: string;
|
|
||||||
settings: unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TaskCancel {
|
|
||||||
type: 'requester:taskcancel';
|
|
||||||
taskId: string;
|
|
||||||
reason: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TaskDataResponse {
|
|
||||||
type: 'requester:taskdataresponse';
|
|
||||||
taskId: string;
|
|
||||||
requestId: string;
|
|
||||||
data: unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RPCResponse {
|
|
||||||
type: 'requester:rpcresponse';
|
|
||||||
taskId: string;
|
|
||||||
callId: string;
|
|
||||||
status: 'success' | 'error';
|
|
||||||
data: unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TaskRequest {
|
|
||||||
type: 'requester:taskrequest';
|
|
||||||
requestId: string;
|
|
||||||
taskType: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type All = TaskSettings | TaskCancel | RPCResponse | TaskDataResponse | TaskRequest;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export namespace RunnerMessage {
|
|
||||||
export namespace ToN8n {
|
|
||||||
export interface Info {
|
|
||||||
type: 'runner:info';
|
|
||||||
name: string;
|
|
||||||
types: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TaskAccepted {
|
|
||||||
type: 'runner:taskaccepted';
|
|
||||||
taskId: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TaskRejected {
|
|
||||||
type: 'runner:taskrejected';
|
|
||||||
taskId: string;
|
|
||||||
reason: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TaskDone {
|
|
||||||
type: 'runner:taskdone';
|
|
||||||
taskId: string;
|
|
||||||
data: TaskResultData;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TaskError {
|
|
||||||
type: 'runner:taskerror';
|
|
||||||
taskId: string;
|
|
||||||
error: unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TaskOffer {
|
|
||||||
type: 'runner:taskoffer';
|
|
||||||
offerId: string;
|
|
||||||
taskType: string;
|
|
||||||
validFor: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TaskDataRequest {
|
|
||||||
type: 'runner:taskdatarequest';
|
|
||||||
taskId: string;
|
|
||||||
requestId: string;
|
|
||||||
requestParams: TaskDataRequestParams;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RPC {
|
|
||||||
type: 'runner:rpc';
|
|
||||||
callId: string;
|
|
||||||
taskId: string;
|
|
||||||
name: (typeof RPC_ALLOW_LIST)[number];
|
|
||||||
params: unknown[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export type All =
|
|
||||||
| Info
|
|
||||||
| TaskDone
|
|
||||||
| TaskError
|
|
||||||
| TaskAccepted
|
|
||||||
| TaskRejected
|
|
||||||
| TaskOffer
|
|
||||||
| RPC
|
|
||||||
| TaskDataRequest;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const RPC_ALLOW_LIST = [
|
|
||||||
'logNodeOutput',
|
|
||||||
'helpers.httpRequestWithAuthentication',
|
|
||||||
'helpers.requestWithAuthenticationPaginated',
|
|
||||||
// "helpers.normalizeItems"
|
|
||||||
// "helpers.constructExecutionMetaData"
|
|
||||||
// "helpers.assertBinaryData"
|
|
||||||
'helpers.getBinaryDataBuffer',
|
|
||||||
// "helpers.copyInputItems"
|
|
||||||
// "helpers.returnJsonArray"
|
|
||||||
'helpers.getSSHClient',
|
|
||||||
'helpers.createReadStream',
|
|
||||||
// "helpers.getStoragePath"
|
|
||||||
'helpers.writeContentToFile',
|
|
||||||
'helpers.prepareBinaryData',
|
|
||||||
'helpers.setBinaryDataBuffer',
|
|
||||||
'helpers.copyBinaryFile',
|
|
||||||
'helpers.binaryToBuffer',
|
|
||||||
// "helpers.binaryToString"
|
|
||||||
// "helpers.getBinaryPath"
|
|
||||||
'helpers.getBinaryStream',
|
|
||||||
'helpers.getBinaryMetadata',
|
|
||||||
'helpers.createDeferredPromise',
|
|
||||||
'helpers.httpRequest',
|
|
||||||
] as const;
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import type { BrokerMessage, RunnerMessage } from '@n8n/task-runner';
|
||||||
import { Service } from 'typedi';
|
import { Service } from 'typedi';
|
||||||
import type WebSocket from 'ws';
|
import type WebSocket from 'ws';
|
||||||
|
|
||||||
|
@ -5,11 +6,9 @@ import { Logger } from '@/logging/logger.service';
|
||||||
|
|
||||||
import { DefaultTaskRunnerDisconnectAnalyzer } from './default-task-runner-disconnect-analyzer';
|
import { DefaultTaskRunnerDisconnectAnalyzer } from './default-task-runner-disconnect-analyzer';
|
||||||
import type {
|
import type {
|
||||||
RunnerMessage,
|
DisconnectAnalyzer,
|
||||||
N8nMessage,
|
|
||||||
TaskRunnerServerInitRequest,
|
TaskRunnerServerInitRequest,
|
||||||
TaskRunnerServerInitResponse,
|
TaskRunnerServerInitResponse,
|
||||||
DisconnectAnalyzer,
|
|
||||||
} from './runner-types';
|
} from './runner-types';
|
||||||
import { TaskBroker, type MessageCallback, type TaskRunner } from './task-broker.service';
|
import { TaskBroker, type MessageCallback, type TaskRunner } from './task-broker.service';
|
||||||
|
|
||||||
|
@ -35,7 +34,7 @@ export class TaskRunnerWsServer {
|
||||||
return this.disconnectAnalyzer;
|
return this.disconnectAnalyzer;
|
||||||
}
|
}
|
||||||
|
|
||||||
sendMessage(id: TaskRunner['id'], message: N8nMessage.ToRunner.All) {
|
sendMessage(id: TaskRunner['id'], message: BrokerMessage.ToRunner.All) {
|
||||||
this.runnerConnections.get(id)?.send(JSON.stringify(message));
|
this.runnerConnections.get(id)?.send(JSON.stringify(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,9 +48,9 @@ export class TaskRunnerWsServer {
|
||||||
try {
|
try {
|
||||||
const buffer = Array.isArray(data) ? Buffer.concat(data) : Buffer.from(data);
|
const buffer = Array.isArray(data) ? Buffer.concat(data) : Buffer.from(data);
|
||||||
|
|
||||||
const message: RunnerMessage.ToN8n.All = JSON.parse(
|
const message: RunnerMessage.ToBroker.All = JSON.parse(
|
||||||
buffer.toString('utf8'),
|
buffer.toString('utf8'),
|
||||||
) as RunnerMessage.ToN8n.All;
|
) as RunnerMessage.ToBroker.All;
|
||||||
|
|
||||||
if (!isConnected && message.type !== 'runner:info') {
|
if (!isConnected && message.type !== 'runner:info') {
|
||||||
return;
|
return;
|
||||||
|
@ -94,7 +93,7 @@ export class TaskRunnerWsServer {
|
||||||
|
|
||||||
connection.on('message', onMessage);
|
connection.on('message', onMessage);
|
||||||
connection.send(
|
connection.send(
|
||||||
JSON.stringify({ type: 'broker:inforequest' } as N8nMessage.ToRunner.InfoRequest),
|
JSON.stringify({ type: 'broker:inforequest' } as BrokerMessage.ToRunner.InfoRequest),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
import type {
|
||||||
|
BrokerMessage,
|
||||||
|
RequesterMessage,
|
||||||
|
RunnerMessage,
|
||||||
|
TaskResultData,
|
||||||
|
} from '@n8n/task-runner';
|
||||||
import { ApplicationError } from 'n8n-workflow';
|
import { ApplicationError } from 'n8n-workflow';
|
||||||
import { nanoid } from 'nanoid';
|
import { nanoid } from 'nanoid';
|
||||||
import { Service } from 'typedi';
|
import { Service } from 'typedi';
|
||||||
|
@ -6,7 +12,6 @@ import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials';
|
||||||
import { Logger } from '@/logging/logger.service';
|
import { Logger } from '@/logging/logger.service';
|
||||||
|
|
||||||
import { TaskRejectError } from './errors';
|
import { TaskRejectError } from './errors';
|
||||||
import type { N8nMessage, RunnerMessage, RequesterMessage, TaskResultData } from './runner-types';
|
|
||||||
|
|
||||||
export interface TaskRunner {
|
export interface TaskRunner {
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -38,13 +43,15 @@ export interface TaskRequest {
|
||||||
acceptInProgress?: boolean;
|
acceptInProgress?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type MessageCallback = (message: N8nMessage.ToRunner.All) => Promise<void> | void;
|
export type MessageCallback = (message: BrokerMessage.ToRunner.All) => Promise<void> | void;
|
||||||
export type RequesterMessageCallback = (
|
export type RequesterMessageCallback = (
|
||||||
message: N8nMessage.ToRequester.All,
|
message: BrokerMessage.ToRequester.All,
|
||||||
) => Promise<void> | void;
|
) => Promise<void> | void;
|
||||||
|
|
||||||
type RunnerAcceptCallback = () => void;
|
type RunnerAcceptCallback = () => void;
|
||||||
type RequesterAcceptCallback = (settings: RequesterMessage.ToN8n.TaskSettings['settings']) => void;
|
type RequesterAcceptCallback = (
|
||||||
|
settings: RequesterMessage.ToBroker.TaskSettings['settings'],
|
||||||
|
) => void;
|
||||||
type TaskRejectCallback = (reason: TaskRejectError) => void;
|
type TaskRejectCallback = (reason: TaskRejectError) => void;
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
|
@ -134,11 +141,11 @@ export class TaskBroker {
|
||||||
this.requesters.delete(requesterId);
|
this.requesters.delete(requesterId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async messageRunner(runnerId: TaskRunner['id'], message: N8nMessage.ToRunner.All) {
|
private async messageRunner(runnerId: TaskRunner['id'], message: BrokerMessage.ToRunner.All) {
|
||||||
await this.knownRunners.get(runnerId)?.messageCallback(message);
|
await this.knownRunners.get(runnerId)?.messageCallback(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async messageAllRunners(message: N8nMessage.ToRunner.All) {
|
private async messageAllRunners(message: BrokerMessage.ToRunner.All) {
|
||||||
await Promise.allSettled(
|
await Promise.allSettled(
|
||||||
[...this.knownRunners.values()].map(async (runner) => {
|
[...this.knownRunners.values()].map(async (runner) => {
|
||||||
await runner.messageCallback(message);
|
await runner.messageCallback(message);
|
||||||
|
@ -146,11 +153,11 @@ export class TaskBroker {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async messageRequester(requesterId: string, message: N8nMessage.ToRequester.All) {
|
private async messageRequester(requesterId: string, message: BrokerMessage.ToRequester.All) {
|
||||||
await this.requesters.get(requesterId)?.(message);
|
await this.requesters.get(requesterId)?.(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
async onRunnerMessage(runnerId: TaskRunner['id'], message: RunnerMessage.ToN8n.All) {
|
async onRunnerMessage(runnerId: TaskRunner['id'], message: RunnerMessage.ToBroker.All) {
|
||||||
const runner = this.knownRunners.get(runnerId);
|
const runner = this.knownRunners.get(runnerId);
|
||||||
if (!runner) {
|
if (!runner) {
|
||||||
return;
|
return;
|
||||||
|
@ -193,7 +200,7 @@ export class TaskBroker {
|
||||||
async handleRpcRequest(
|
async handleRpcRequest(
|
||||||
taskId: Task['id'],
|
taskId: Task['id'],
|
||||||
callId: string,
|
callId: string,
|
||||||
name: RunnerMessage.ToN8n.RPC['name'],
|
name: RunnerMessage.ToBroker.RPC['name'],
|
||||||
params: unknown[],
|
params: unknown[],
|
||||||
) {
|
) {
|
||||||
const task = this.tasks.get(taskId);
|
const task = this.tasks.get(taskId);
|
||||||
|
@ -227,8 +234,8 @@ export class TaskBroker {
|
||||||
|
|
||||||
async handleDataRequest(
|
async handleDataRequest(
|
||||||
taskId: Task['id'],
|
taskId: Task['id'],
|
||||||
requestId: RunnerMessage.ToN8n.TaskDataRequest['requestId'],
|
requestId: RunnerMessage.ToBroker.TaskDataRequest['requestId'],
|
||||||
requestParams: RunnerMessage.ToN8n.TaskDataRequest['requestParams'],
|
requestParams: RunnerMessage.ToBroker.TaskDataRequest['requestParams'],
|
||||||
) {
|
) {
|
||||||
const task = this.tasks.get(taskId);
|
const task = this.tasks.get(taskId);
|
||||||
if (!task) {
|
if (!task) {
|
||||||
|
@ -244,7 +251,7 @@ export class TaskBroker {
|
||||||
|
|
||||||
async handleResponse(
|
async handleResponse(
|
||||||
taskId: Task['id'],
|
taskId: Task['id'],
|
||||||
requestId: RunnerMessage.ToN8n.TaskDataRequest['requestId'],
|
requestId: RunnerMessage.ToBroker.TaskDataRequest['requestId'],
|
||||||
data: unknown,
|
data: unknown,
|
||||||
) {
|
) {
|
||||||
const task = this.tasks.get(taskId);
|
const task = this.tasks.get(taskId);
|
||||||
|
@ -259,7 +266,7 @@ export class TaskBroker {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async onRequesterMessage(requesterId: string, message: RequesterMessage.ToN8n.All) {
|
async onRequesterMessage(requesterId: string, message: RequesterMessage.ToBroker.All) {
|
||||||
switch (message.type) {
|
switch (message.type) {
|
||||||
case 'requester:tasksettings':
|
case 'requester:tasksettings':
|
||||||
this.handleRequesterAccept(message.taskId, message.settings);
|
this.handleRequesterAccept(message.taskId, message.settings);
|
||||||
|
@ -291,7 +298,7 @@ export class TaskBroker {
|
||||||
async handleRequesterRpcResponse(
|
async handleRequesterRpcResponse(
|
||||||
taskId: string,
|
taskId: string,
|
||||||
callId: string,
|
callId: string,
|
||||||
status: RequesterMessage.ToN8n.RPCResponse['status'],
|
status: RequesterMessage.ToBroker.RPCResponse['status'],
|
||||||
data: unknown,
|
data: unknown,
|
||||||
) {
|
) {
|
||||||
const runner = await this.getRunnerOrFailTask(taskId);
|
const runner = await this.getRunnerOrFailTask(taskId);
|
||||||
|
@ -317,7 +324,7 @@ export class TaskBroker {
|
||||||
|
|
||||||
handleRequesterAccept(
|
handleRequesterAccept(
|
||||||
taskId: Task['id'],
|
taskId: Task['id'],
|
||||||
settings: RequesterMessage.ToN8n.TaskSettings['settings'],
|
settings: RequesterMessage.ToBroker.TaskSettings['settings'],
|
||||||
) {
|
) {
|
||||||
const acceptReject = this.requesterAcceptRejects.get(taskId);
|
const acceptReject = this.requesterAcceptRejects.get(taskId);
|
||||||
if (acceptReject) {
|
if (acceptReject) {
|
||||||
|
@ -467,10 +474,12 @@ export class TaskBroker {
|
||||||
this.pendingTaskRequests.splice(requestIndex, 1);
|
this.pendingTaskRequests.splice(requestIndex, 1);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const acceptPromise = new Promise<RequesterMessage.ToN8n.TaskSettings['settings']>(
|
const acceptPromise = new Promise<RequesterMessage.ToBroker.TaskSettings['settings']>(
|
||||||
(resolve, reject) => {
|
(resolve, reject) => {
|
||||||
this.requesterAcceptRejects.set(taskId, {
|
this.requesterAcceptRejects.set(taskId, {
|
||||||
accept: resolve as (settings: RequesterMessage.ToN8n.TaskSettings['settings']) => void,
|
accept: resolve as (
|
||||||
|
settings: RequesterMessage.ToBroker.TaskSettings['settings'],
|
||||||
|
) => void,
|
||||||
reject,
|
reject,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
|
import type { TaskData } from '@n8n/task-runner';
|
||||||
import { mock } from 'jest-mock-extended';
|
import { mock } from 'jest-mock-extended';
|
||||||
import type { IExecuteFunctions, IWorkflowExecuteAdditionalData } from 'n8n-workflow';
|
import type { IExecuteFunctions, IWorkflowExecuteAdditionalData } from 'n8n-workflow';
|
||||||
import { type INode, type INodeExecutionData, type Workflow } from 'n8n-workflow';
|
import { type INode, type INodeExecutionData, type Workflow } from 'n8n-workflow';
|
||||||
|
|
||||||
import { DataRequestResponseBuilder } from '../data-request-response-builder';
|
import { DataRequestResponseBuilder } from '../data-request-response-builder';
|
||||||
import type { TaskData } from '../task-manager';
|
|
||||||
|
|
||||||
const triggerNode: INode = mock<INode>({
|
const triggerNode: INode = mock<INode>({
|
||||||
name: 'Trigger',
|
name: 'Trigger',
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
import type {
|
||||||
|
DataRequestResponse,
|
||||||
|
BrokerMessage,
|
||||||
|
PartialAdditionalData,
|
||||||
|
TaskData,
|
||||||
|
} from '@n8n/task-runner';
|
||||||
import type {
|
import type {
|
||||||
EnvProviderState,
|
EnvProviderState,
|
||||||
IExecuteData,
|
IExecuteData,
|
||||||
|
@ -11,9 +17,6 @@ import type {
|
||||||
WorkflowParameters,
|
WorkflowParameters,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
import type { DataRequestResponse, PartialAdditionalData, TaskData } from './task-manager';
|
|
||||||
import type { N8nMessage } from '../runner-types';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds the response to a data request coming from a Task Runner. Tries to minimize
|
* Builds the response to a data request coming from a Task Runner. Tries to minimize
|
||||||
* the amount of data that is sent to the runner by only providing what is requested.
|
* the amount of data that is sent to the runner by only providing what is requested.
|
||||||
|
@ -23,7 +26,7 @@ export class DataRequestResponseBuilder {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly taskData: TaskData,
|
private readonly taskData: TaskData,
|
||||||
private readonly requestParams: N8nMessage.ToRequester.TaskDataRequest['requestParams'],
|
private readonly requestParams: BrokerMessage.ToRequester.TaskDataRequest['requestParams'],
|
||||||
) {
|
) {
|
||||||
this.requestedNodeNames = new Set(requestParams.dataOfNodes);
|
this.requestedNodeNames = new Set(requestParams.dataOfNodes);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
import type { RequesterMessage } from '@n8n/task-runner';
|
||||||
import Container from 'typedi';
|
import Container from 'typedi';
|
||||||
|
|
||||||
import { TaskManager } from './task-manager';
|
import { TaskManager } from './task-manager';
|
||||||
import type { RequesterMessage } from '../runner-types';
|
|
||||||
import type { RequesterMessageCallback } from '../task-broker.service';
|
import type { RequesterMessageCallback } from '../task-broker.service';
|
||||||
import { TaskBroker } from '../task-broker.service';
|
import { TaskBroker } from '../task-broker.service';
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ export class LocalTaskManager extends TaskManager {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
sendMessage(message: RequesterMessage.ToN8n.All) {
|
sendMessage(message: RequesterMessage.ToBroker.All) {
|
||||||
void this.taskBroker.onRequesterMessage(this.id, message);
|
void this.taskBroker.onRequesterMessage(this.id, message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +1,24 @@
|
||||||
import {
|
import type { TaskResultData, RequesterMessage, BrokerMessage, TaskData } from '@n8n/task-runner';
|
||||||
type EnvProviderState,
|
import { RPC_ALLOW_LIST } from '@n8n/task-runner';
|
||||||
type IExecuteFunctions,
|
import type {
|
||||||
type Workflow,
|
EnvProviderState,
|
||||||
type IRunExecutionData,
|
IExecuteFunctions,
|
||||||
type INodeExecutionData,
|
Workflow,
|
||||||
type ITaskDataConnections,
|
IRunExecutionData,
|
||||||
type INode,
|
INodeExecutionData,
|
||||||
type WorkflowParameters,
|
ITaskDataConnections,
|
||||||
type INodeParameters,
|
INode,
|
||||||
type WorkflowExecuteMode,
|
INodeParameters,
|
||||||
type IExecuteData,
|
WorkflowExecuteMode,
|
||||||
type IDataObject,
|
IExecuteData,
|
||||||
type IWorkflowExecuteAdditionalData,
|
IDataObject,
|
||||||
type Result,
|
IWorkflowExecuteAdditionalData,
|
||||||
createResultOk,
|
Result,
|
||||||
createResultError,
|
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
|
import { createResultOk, createResultError } from 'n8n-workflow';
|
||||||
import { nanoid } from 'nanoid';
|
import { nanoid } from 'nanoid';
|
||||||
|
|
||||||
import { DataRequestResponseBuilder } from './data-request-response-builder';
|
import { DataRequestResponseBuilder } from './data-request-response-builder';
|
||||||
import {
|
|
||||||
RPC_ALLOW_LIST,
|
|
||||||
type TaskResultData,
|
|
||||||
type N8nMessage,
|
|
||||||
type RequesterMessage,
|
|
||||||
} from '../runner-types';
|
|
||||||
|
|
||||||
export type RequestAccept = (jobId: string) => void;
|
export type RequestAccept = (jobId: string) => void;
|
||||||
export type RequestReject = (reason: string) => void;
|
export type RequestReject = (reason: string) => void;
|
||||||
|
@ -32,62 +26,6 @@ export type RequestReject = (reason: string) => void;
|
||||||
export type TaskAccept = (data: TaskResultData) => void;
|
export type TaskAccept = (data: TaskResultData) => void;
|
||||||
export type TaskReject = (error: unknown) => void;
|
export type TaskReject = (error: unknown) => void;
|
||||||
|
|
||||||
export interface TaskData {
|
|
||||||
executeFunctions: IExecuteFunctions;
|
|
||||||
inputData: ITaskDataConnections;
|
|
||||||
node: INode;
|
|
||||||
|
|
||||||
workflow: Workflow;
|
|
||||||
runExecutionData: IRunExecutionData;
|
|
||||||
runIndex: number;
|
|
||||||
itemIndex: number;
|
|
||||||
activeNodeName: string;
|
|
||||||
connectionInputData: INodeExecutionData[];
|
|
||||||
siblingParameters: INodeParameters;
|
|
||||||
mode: WorkflowExecuteMode;
|
|
||||||
envProviderState: EnvProviderState;
|
|
||||||
executeData?: IExecuteData;
|
|
||||||
defaultReturnRunIndex: number;
|
|
||||||
selfData: IDataObject;
|
|
||||||
contextNodeName: string;
|
|
||||||
additionalData: IWorkflowExecuteAdditionalData;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PartialAdditionalData {
|
|
||||||
executionId?: string;
|
|
||||||
restartExecutionId?: string;
|
|
||||||
restApiUrl: string;
|
|
||||||
instanceBaseUrl: string;
|
|
||||||
formWaitingBaseUrl: string;
|
|
||||||
webhookBaseUrl: string;
|
|
||||||
webhookWaitingBaseUrl: string;
|
|
||||||
webhookTestBaseUrl: string;
|
|
||||||
currentNodeParameters?: INodeParameters;
|
|
||||||
executionTimeoutTimestamp?: number;
|
|
||||||
userId?: string;
|
|
||||||
variables: IDataObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DataRequestResponse {
|
|
||||||
workflow: Omit<WorkflowParameters, 'nodeTypes'>;
|
|
||||||
inputData: ITaskDataConnections;
|
|
||||||
node: INode;
|
|
||||||
|
|
||||||
runExecutionData: IRunExecutionData;
|
|
||||||
runIndex: number;
|
|
||||||
itemIndex: number;
|
|
||||||
activeNodeName: string;
|
|
||||||
connectionInputData: INodeExecutionData[];
|
|
||||||
siblingParameters: INodeParameters;
|
|
||||||
mode: WorkflowExecuteMode;
|
|
||||||
envProviderState: EnvProviderState;
|
|
||||||
executeData?: IExecuteData;
|
|
||||||
defaultReturnRunIndex: number;
|
|
||||||
selfData: IDataObject;
|
|
||||||
contextNodeName: string;
|
|
||||||
additionalData: PartialAdditionalData;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TaskRequest {
|
export interface TaskRequest {
|
||||||
requestId: string;
|
requestId: string;
|
||||||
taskType: string;
|
taskType: string;
|
||||||
|
@ -219,9 +157,9 @@ export class TaskManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sendMessage(_message: RequesterMessage.ToN8n.All) {}
|
sendMessage(_message: RequesterMessage.ToBroker.All) {}
|
||||||
|
|
||||||
onMessage(message: N8nMessage.ToRequester.All) {
|
onMessage(message: BrokerMessage.ToRequester.All) {
|
||||||
switch (message.type) {
|
switch (message.type) {
|
||||||
case 'broker:taskready':
|
case 'broker:taskready':
|
||||||
this.taskReady(message.requestId, message.taskId);
|
this.taskReady(message.requestId, message.taskId);
|
||||||
|
@ -282,7 +220,7 @@ export class TaskManager {
|
||||||
sendTaskData(
|
sendTaskData(
|
||||||
taskId: string,
|
taskId: string,
|
||||||
requestId: string,
|
requestId: string,
|
||||||
requestParams: N8nMessage.ToRequester.TaskDataRequest['requestParams'],
|
requestParams: BrokerMessage.ToRequester.TaskDataRequest['requestParams'],
|
||||||
) {
|
) {
|
||||||
const job = this.tasks.get(taskId);
|
const job = this.tasks.get(taskId);
|
||||||
if (!job) {
|
if (!job) {
|
||||||
|
@ -304,7 +242,7 @@ export class TaskManager {
|
||||||
async handleRpc(
|
async handleRpc(
|
||||||
taskId: string,
|
taskId: string,
|
||||||
callId: string,
|
callId: string,
|
||||||
name: N8nMessage.ToRequester.RPC['name'],
|
name: BrokerMessage.ToRequester.RPC['name'],
|
||||||
params: unknown[],
|
params: unknown[],
|
||||||
) {
|
) {
|
||||||
const job = this.tasks.get(taskId);
|
const job = this.tasks.get(taskId);
|
||||||
|
|
|
@ -92,7 +92,7 @@ export class TaskRunnerProcess extends TypedEmitter<TaskRunnerProcessEventMap> {
|
||||||
}
|
}
|
||||||
|
|
||||||
startNode(grantToken: string, n8nUri: string) {
|
startNode(grantToken: string, n8nUri: string) {
|
||||||
const startScript = require.resolve('@n8n/task-runner');
|
const startScript = require.resolve('@n8n/task-runner/start');
|
||||||
|
|
||||||
return spawn('node', [startScript], {
|
return spawn('node', [startScript], {
|
||||||
env: this.getProcessEnvVars(grantToken, n8nUri),
|
env: this.getProcessEnvVars(grantToken, n8nUri),
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { TaskRunnerWsServer } from '../../../src/runners/runner-ws-server';
|
||||||
|
|
||||||
describe('TaskRunnerModule in internal_childprocess mode', () => {
|
describe('TaskRunnerModule in internal_childprocess mode', () => {
|
||||||
const runnerConfig = Container.get(TaskRunnersConfig);
|
const runnerConfig = Container.get(TaskRunnersConfig);
|
||||||
|
runnerConfig.port = 0; // Random port
|
||||||
runnerConfig.mode = 'internal_childprocess';
|
runnerConfig.mode = 'internal_childprocess';
|
||||||
const module = Container.get(TaskRunnerModule);
|
const module = Container.get(TaskRunnerModule);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue