@nocobase/plugin-workflow-javascript 3.0.0-alpha.6 → 3.0.0-alpha.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,105 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
10
+ var __defProp = Object.defineProperty;
11
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
12
+ var __getOwnPropNames = Object.getOwnPropertyNames;
13
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
14
+ var __export = (target, all) => {
15
+ for (var name in all)
16
+ __defProp(target, name, { get: all[name], enumerable: true });
17
+ };
18
+ var __copyProps = (to, from, except, desc) => {
19
+ if (from && typeof from === "object" || typeof from === "function") {
20
+ for (let key of __getOwnPropNames(from))
21
+ if (!__hasOwnProp.call(to, key) && key !== except)
22
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
23
+ }
24
+ return to;
25
+ };
26
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
27
+ var RunningJobs_exports = {};
28
+ __export(RunningJobs_exports, {
29
+ ABORT_JAVASCRIPT_JOB_SYNC_MESSAGE_TYPE: () => ABORT_JAVASCRIPT_JOB_SYNC_MESSAGE_TYPE,
30
+ JAVASCRIPT_SYNC_MESSAGE_CHANNEL: () => JAVASCRIPT_SYNC_MESSAGE_CHANNEL,
31
+ RunningJobs: () => RunningJobs,
32
+ getAbortReason: () => getAbortReason
33
+ });
34
+ module.exports = __toCommonJS(RunningJobs_exports);
35
+ const JAVASCRIPT_SYNC_MESSAGE_CHANNEL = "@nocobase/plugin-workflow-javascript";
36
+ const ABORT_JAVASCRIPT_JOB_SYNC_MESSAGE_TYPE = "abortJavaScriptJob";
37
+ function getAbortReason(reason) {
38
+ if (reason instanceof Error) {
39
+ return reason.message;
40
+ }
41
+ if (typeof reason === "string") {
42
+ return reason;
43
+ }
44
+ return void 0;
45
+ }
46
+ class RunningJobs {
47
+ jobs = /* @__PURE__ */ new Map();
48
+ executionJobs = /* @__PURE__ */ new Map();
49
+ register(job) {
50
+ const jobId = String(job.jobId);
51
+ const executionId = String(job.executionId);
52
+ const executionJobs = this.executionJobs.get(executionId) ?? /* @__PURE__ */ new Set();
53
+ this.jobs.set(jobId, job);
54
+ executionJobs.add(jobId);
55
+ this.executionJobs.set(executionId, executionJobs);
56
+ return () => this.unregister(job.jobId);
57
+ }
58
+ unregister(jobId) {
59
+ const key = String(jobId);
60
+ const job = this.jobs.get(key);
61
+ if (!job) {
62
+ return;
63
+ }
64
+ this.jobs.delete(key);
65
+ const executionId = String(job.executionId);
66
+ const executionJobs = this.executionJobs.get(executionId);
67
+ executionJobs == null ? void 0 : executionJobs.delete(key);
68
+ if (!(executionJobs == null ? void 0 : executionJobs.size)) {
69
+ this.executionJobs.delete(executionId);
70
+ }
71
+ }
72
+ abortJob(jobId, reason) {
73
+ const job = this.jobs.get(String(jobId));
74
+ if (!job) {
75
+ return false;
76
+ }
77
+ job.abort(reason);
78
+ return true;
79
+ }
80
+ abortExecution(executionId, reason) {
81
+ var _a;
82
+ const jobIds = this.executionJobs.get(String(executionId));
83
+ if (!(jobIds == null ? void 0 : jobIds.size)) {
84
+ return false;
85
+ }
86
+ for (const jobId of jobIds) {
87
+ (_a = this.jobs.get(jobId)) == null ? void 0 : _a.abort(reason);
88
+ }
89
+ return true;
90
+ }
91
+ async abortAcrossInstances(workflowPlugin, message) {
92
+ if (this.abortJob(message.jobId, message.reason)) {
93
+ return true;
94
+ }
95
+ await workflowPlugin.app.syncMessageManager.publish(JAVASCRIPT_SYNC_MESSAGE_CHANNEL, message);
96
+ return false;
97
+ }
98
+ }
99
+ // Annotate the CommonJS export names for ESM import in node:
100
+ 0 && (module.exports = {
101
+ ABORT_JAVASCRIPT_JOB_SYNC_MESSAGE_TYPE,
102
+ JAVASCRIPT_SYNC_MESSAGE_CHANNEL,
103
+ RunningJobs,
104
+ getAbortReason
105
+ });
@@ -8,7 +8,9 @@
8
8
  */
9
9
  import { Logger } from 'winston';
10
10
  import Joi from 'joi';
11
- import { Processor, Instruction, FlowNodeModel } from '@nocobase/plugin-workflow';
11
+ import WorkflowPlugin, { Processor, Instruction, FlowNodeModel } from '@nocobase/plugin-workflow';
12
+ import { RunningJobs } from './RunningJobs';
13
+ import { ScriptArguments, ScriptRunResult } from './ScriptWorkerRunner';
12
14
  type ScriptArgument = {
13
15
  name: string;
14
16
  value?: unknown;
@@ -19,41 +21,27 @@ type ScriptConfig = {
19
21
  continue?: boolean;
20
22
  arguments?: ScriptArgument[];
21
23
  };
22
- type ScriptArguments = Record<string, unknown> | unknown[];
23
24
  export default class ScriptInstruction extends Instruction {
24
- /**
25
- * Returns the worker script path based on whether WORKFLOW_SCRIPT_MODULES is configured.
26
- * - WORKFLOW_SCRIPT_MODULES set: uses Node.js vm with require support (unsafe; not a security boundary)
27
- * - WORKFLOW_SCRIPT_MODULES unset: uses QuickJS (WASM) for maximum security (no require, no Node.js APIs)
28
- */
25
+ private readonly runningJobs;
29
26
  static get workerScript(): string;
30
27
  static run(source: string, args: ScriptArguments, options: {
31
28
  logger: Logger;
32
29
  timeout?: number;
33
30
  signal?: AbortSignal;
34
- }): Promise<{
35
- status: -2;
36
- result: string;
37
- } | {
38
- status: 1;
39
- result: unknown;
40
- }>;
31
+ }): Promise<ScriptRunResult>;
32
+ constructor(workflow: WorkflowPlugin, runningJobs: RunningJobs);
41
33
  configSchema: Joi.ObjectSchema<any>;
42
34
  run(node: FlowNodeModel, prevJob: any, processor: Processor, options?: {
43
35
  signal?: AbortSignal;
44
36
  }): Promise<{
45
37
  result: unknown;
46
- status: -2 | 1;
38
+ status: 1 | -2;
47
39
  }>;
48
40
  resume(node: FlowNodeModel, job: any, processor: Processor): Promise<any>;
49
41
  test(config?: ScriptConfig): Promise<{
50
42
  log: string;
51
- status: -2;
52
- result: string;
53
- } | {
54
- log: string;
55
- status: 1;
56
- result: unknown;
43
+ status: number;
44
+ result?: unknown;
57
45
  }>;
58
46
  }
59
47
  export {};
@@ -39,102 +39,23 @@ __export(ScriptInstruction_exports, {
39
39
  default: () => ScriptInstruction
40
40
  });
41
41
  module.exports = __toCommonJS(ScriptInstruction_exports);
42
- var import_node_events = require("node:events");
43
- var import_node_path = __toESM(require("node:path"));
44
- var import_node_worker_threads = require("node:worker_threads");
45
42
  var import_winston = __toESM(require("winston"));
46
43
  var import_joi = __toESM(require("joi"));
47
44
  var import_plugin_workflow = require("@nocobase/plugin-workflow");
48
45
  var import_cache_logger = require("./cache-logger");
49
- function isWorkerResult(message) {
50
- return typeof message === "object" && message !== null && "type" in message && message.type === "result";
51
- }
46
+ var import_constants = require("./constants");
47
+ var import_RunningJobs = require("./RunningJobs");
48
+ var import_ScriptWorkerRunner = require("./ScriptWorkerRunner");
52
49
  class ScriptInstruction extends import_plugin_workflow.Instruction {
53
- /**
54
- * Returns the worker script path based on whether WORKFLOW_SCRIPT_MODULES is configured.
55
- * - WORKFLOW_SCRIPT_MODULES set: uses Node.js vm with require support (unsafe; not a security boundary)
56
- * - WORKFLOW_SCRIPT_MODULES unset: uses QuickJS (WASM) for maximum security (no require, no Node.js APIs)
57
- */
50
+ constructor(workflow, runningJobs) {
51
+ super(workflow);
52
+ this.runningJobs = runningJobs;
53
+ }
58
54
  static get workerScript() {
59
- const hasModules = (process.env.WORKFLOW_SCRIPT_MODULES ?? "").split(",").filter(Boolean).length > 0;
60
- return import_node_path.default.join(__dirname, hasModules ? "Vm.js" : "QuickJs.js");
55
+ return import_ScriptWorkerRunner.ScriptWorkerRunner.workerScript;
61
56
  }
62
57
  static async run(source, args, options) {
63
- const { logger, timeout, signal } = options;
64
- const worker = new import_node_worker_threads.Worker(this.workerScript, {
65
- workerData: { source, args, options: timeout ? { timeout } : {} }
66
- });
67
- worker.stdout.on("data", (data) => {
68
- logger.info(data.toString());
69
- });
70
- worker.stderr.on("data", (data) => {
71
- logger.error(data.toString());
72
- });
73
- const outputClosed = Promise.all([(0, import_node_events.once)(worker.stdout, "close"), (0, import_node_events.once)(worker.stderr, "close")]);
74
- const outcomePromise = new Promise((resolve) => {
75
- const finish = (outcome2) => {
76
- worker.removeListener("message", messageListener);
77
- worker.removeListener("error", errorListener);
78
- worker.removeListener("exit", exitListener);
79
- signal == null ? void 0 : signal.removeEventListener("abort", abortListener);
80
- resolve(outcome2);
81
- };
82
- const messageListener = (message) => {
83
- if (isWorkerResult(message)) {
84
- finish({ type: "result", result: message.result });
85
- }
86
- };
87
- const errorListener = (error) => {
88
- finish({ type: "error", error });
89
- };
90
- const exitListener = (code) => {
91
- finish({ type: "exit", code });
92
- };
93
- const abortListener = () => {
94
- finish({ type: "aborted" });
95
- };
96
- worker.on("message", messageListener);
97
- worker.once("error", errorListener);
98
- worker.once("exit", exitListener);
99
- signal == null ? void 0 : signal.addEventListener("abort", abortListener, { once: true });
100
- if (signal == null ? void 0 : signal.aborted) {
101
- abortListener();
102
- }
103
- });
104
- const outcome = await outcomePromise;
105
- try {
106
- if (outcome.type !== "exit") {
107
- await worker.terminate();
108
- }
109
- await outputClosed;
110
- } catch (e) {
111
- if (outcome.type === "aborted" || (signal == null ? void 0 : signal.aborted)) {
112
- throw signal.reason instanceof Error ? signal.reason : new import_plugin_workflow.WorkflowTimeoutError();
113
- }
114
- return {
115
- status: import_plugin_workflow.JOB_STATUS.ERROR,
116
- result: e instanceof Error ? e.message : String(e)
117
- };
118
- }
119
- if (outcome.type === "aborted") {
120
- throw (signal == null ? void 0 : signal.reason) instanceof Error ? signal.reason : new import_plugin_workflow.WorkflowTimeoutError();
121
- }
122
- if (outcome.type === "error") {
123
- return {
124
- status: import_plugin_workflow.JOB_STATUS.ERROR,
125
- result: outcome.error.message
126
- };
127
- }
128
- if (outcome.type === "exit" && outcome.code !== 0) {
129
- return {
130
- status: import_plugin_workflow.JOB_STATUS.ERROR,
131
- result: `Worker stopped with exit code ${outcome.code}`
132
- };
133
- }
134
- return {
135
- status: import_plugin_workflow.JOB_STATUS.RESOLVED,
136
- result: outcome.type === "result" ? outcome.result : void 0
137
- };
58
+ return import_ScriptWorkerRunner.ScriptWorkerRunner.run(source, args, options);
138
59
  }
139
60
  configSchema = import_joi.default.object({
140
61
  content: import_joi.default.string(),
@@ -148,6 +69,7 @@ class ScriptInstruction extends import_plugin_workflow.Instruction {
148
69
  ).optional()
149
70
  });
150
71
  async run(node, prevJob, processor, options) {
72
+ var _a, _b;
151
73
  const { content = "", continue: cont, timeout } = node.config;
152
74
  const args = processor.getParsedValue(node.config.arguments ?? [], node.id);
153
75
  const _args = args.reduce((pre, item) => ({ ...pre, [item.name]: item.value }), {});
@@ -169,60 +91,48 @@ class ScriptInstruction extends import_plugin_workflow.Instruction {
169
91
  status: cont ? import_plugin_workflow.JOB_STATUS.RESOLVED : result.status === import_plugin_workflow.JOB_STATUS.RESOLVED ? import_plugin_workflow.JOB_STATUS.RESOLVED : import_plugin_workflow.JOB_STATUS.ERROR
170
92
  };
171
93
  }
94
+ const meta = {
95
+ args: _args
96
+ };
172
97
  const { id } = processor.saveJob({
173
98
  status: import_plugin_workflow.JOB_STATUS.PENDING,
174
99
  nodeId: node.id,
175
100
  nodeKey: node.key,
176
- upstreamId: (prevJob == null ? void 0 : prevJob.id) ?? null
101
+ upstreamId: (prevJob == null ? void 0 : prevJob.id) ?? null,
102
+ startedAt: null,
103
+ meta
177
104
  });
178
- processor.logger.info(`script (#${node.id}) has been started, waiting for response...`);
179
- const abortHandle = processor.createBackgroundAbortHandle();
105
+ const abortQueuedJob = async () => {
106
+ var _a2;
107
+ await this.runningJobs.abortAcrossInstances(this.workflow, {
108
+ type: import_RunningJobs.ABORT_JAVASCRIPT_JOB_SYNC_MESSAGE_TYPE,
109
+ jobId: id,
110
+ executionId: processor.execution.id,
111
+ reason: (0, import_RunningJobs.getAbortReason)((_a2 = options == null ? void 0 : options.signal) == null ? void 0 : _a2.reason)
112
+ });
113
+ };
114
+ if ((_a = options == null ? void 0 : options.signal) == null ? void 0 : _a.aborted) {
115
+ await abortQueuedJob();
116
+ } else {
117
+ (_b = options == null ? void 0 : options.signal) == null ? void 0 : _b.addEventListener(
118
+ "abort",
119
+ () => {
120
+ abortQueuedJob().catch((error) => {
121
+ processor.logger.error(`broadcasting JavaScript job (${id}) abort signal failed`, { error });
122
+ });
123
+ },
124
+ { once: true }
125
+ );
126
+ }
127
+ processor.logger.info(`script (#${node.id}) has been queued, waiting for JavaScript Worker resource...`);
128
+ await processor.exit();
180
129
  try {
181
- await processor.exit();
130
+ await this.workflow.app.eventQueue.publish(import_constants.PENDING_JAVASCRIPT_TASK_CHANNEL, {
131
+ jobId: id
132
+ });
182
133
  } catch (error) {
183
- abortHandle.dispose();
184
- throw error;
134
+ processor.logger.error(`publishing JavaScript job (${id}) failed, recovery will republish it`, { error });
185
135
  }
186
- const jobResult = {
187
- status: import_plugin_workflow.JOB_STATUS.PENDING
188
- };
189
- this.constructor.run(content, _args, { timeout, logger: processor.logger, signal: abortHandle.signal }).then((res) => {
190
- if (res.status === import_plugin_workflow.JOB_STATUS.RESOLVED) {
191
- processor.logger.info(`script (#${node.id}) get result success`);
192
- jobResult.status = import_plugin_workflow.JOB_STATUS.RESOLVED;
193
- jobResult.result = res.result;
194
- processor.logger.info(`run script execution success, node id: ${node.id},the result is ${res.result}`);
195
- return;
196
- }
197
- if (cont) {
198
- processor.logger.warn(`script (#${node.id}) get result failed, the reason is ${res.result}`);
199
- jobResult.status = import_plugin_workflow.JOB_STATUS.RESOLVED;
200
- jobResult.result = res.result;
201
- return;
202
- }
203
- processor.logger.info(`script (#${node.id}) get result failed, the reason is ${res.result}`);
204
- jobResult.status = import_plugin_workflow.JOB_STATUS.ERROR;
205
- jobResult.result = res.result;
206
- }).catch((e) => {
207
- const message = e instanceof Error ? e.message : String(e);
208
- processor.logger.error(`script (#${node.id}) get result failed, the reason is ${message}`);
209
- jobResult.status = import_plugin_workflow.JOB_STATUS.ERROR;
210
- jobResult.result = message;
211
- }).finally(() => {
212
- abortHandle.dispose();
213
- processor.logger.debug(`script (#${node.id}) ended, resume workflow...`);
214
- setImmediate(async () => {
215
- const job = await this.workflow.db.getRepository("jobs").findOne({ filterByTk: id });
216
- const execution = await job.getExecution();
217
- if (execution.status !== 0) {
218
- processor.logger.warn(`script (#${node.id}) result discarded because execution (${execution.id}) is ended`);
219
- return;
220
- }
221
- job.set(jobResult);
222
- await this.workflow.resume(job).catch(() => {
223
- });
224
- });
225
- });
226
136
  }
227
137
  async resume(node, job, processor) {
228
138
  return job;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+ import { Logger } from 'winston';
10
+ export type ScriptArguments = Record<string, unknown> | unknown[] | null;
11
+ export type ScriptRunResult = {
12
+ status: number;
13
+ result?: unknown;
14
+ };
15
+ export declare class ScriptWorkerRunner {
16
+ /**
17
+ * Returns the worker script path based on whether WORKFLOW_SCRIPT_MODULES is configured.
18
+ * - WORKFLOW_SCRIPT_MODULES set: uses Node.js vm with require support (unsafe; not a security boundary)
19
+ * - WORKFLOW_SCRIPT_MODULES unset: uses QuickJS (WASM) for maximum security (no require, no Node.js APIs)
20
+ */
21
+ static get workerScript(): string;
22
+ static run(source: string, args: ScriptArguments, options: {
23
+ logger: Logger;
24
+ timeout?: number;
25
+ signal?: AbortSignal;
26
+ }): Promise<ScriptRunResult>;
27
+ }
@@ -0,0 +1,140 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
10
+ var __create = Object.create;
11
+ var __defProp = Object.defineProperty;
12
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
13
+ var __getOwnPropNames = Object.getOwnPropertyNames;
14
+ var __getProtoOf = Object.getPrototypeOf;
15
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
16
+ var __export = (target, all) => {
17
+ for (var name in all)
18
+ __defProp(target, name, { get: all[name], enumerable: true });
19
+ };
20
+ var __copyProps = (to, from, except, desc) => {
21
+ if (from && typeof from === "object" || typeof from === "function") {
22
+ for (let key of __getOwnPropNames(from))
23
+ if (!__hasOwnProp.call(to, key) && key !== except)
24
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
25
+ }
26
+ return to;
27
+ };
28
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
29
+ // If the importer is in node compatibility mode or this is not an ESM
30
+ // file that has been converted to a CommonJS file using a Babel-
31
+ // compatible transform (i.e. "__esModule" has not been set), then set
32
+ // "default" to the CommonJS "module.exports" for node compatibility.
33
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
34
+ mod
35
+ ));
36
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
37
+ var ScriptWorkerRunner_exports = {};
38
+ __export(ScriptWorkerRunner_exports, {
39
+ ScriptWorkerRunner: () => ScriptWorkerRunner
40
+ });
41
+ module.exports = __toCommonJS(ScriptWorkerRunner_exports);
42
+ var import_node_events = require("node:events");
43
+ var import_node_path = __toESM(require("node:path"));
44
+ var import_node_worker_threads = require("node:worker_threads");
45
+ var import_plugin_workflow = require("@nocobase/plugin-workflow");
46
+ function isWorkerResult(message) {
47
+ return typeof message === "object" && message !== null && "type" in message && message.type === "result";
48
+ }
49
+ class ScriptWorkerRunner {
50
+ /**
51
+ * Returns the worker script path based on whether WORKFLOW_SCRIPT_MODULES is configured.
52
+ * - WORKFLOW_SCRIPT_MODULES set: uses Node.js vm with require support (unsafe; not a security boundary)
53
+ * - WORKFLOW_SCRIPT_MODULES unset: uses QuickJS (WASM) for maximum security (no require, no Node.js APIs)
54
+ */
55
+ static get workerScript() {
56
+ const hasModules = (process.env.WORKFLOW_SCRIPT_MODULES ?? "").split(",").filter(Boolean).length > 0;
57
+ return import_node_path.default.join(__dirname, hasModules ? "Vm.js" : "QuickJs.js");
58
+ }
59
+ static async run(source, args, options) {
60
+ const { logger, timeout, signal } = options;
61
+ const worker = new import_node_worker_threads.Worker(this.workerScript, {
62
+ workerData: { source, args, options: timeout ? { timeout } : {} }
63
+ });
64
+ worker.stdout.on("data", (data) => {
65
+ logger.info(data.toString());
66
+ });
67
+ worker.stderr.on("data", (data) => {
68
+ logger.error(data.toString());
69
+ });
70
+ const outputClosed = Promise.all([(0, import_node_events.once)(worker.stdout, "close"), (0, import_node_events.once)(worker.stderr, "close")]);
71
+ const outcomePromise = new Promise((resolve) => {
72
+ const finish = (outcome2) => {
73
+ worker.removeListener("message", messageListener);
74
+ worker.removeListener("error", errorListener);
75
+ worker.removeListener("exit", exitListener);
76
+ signal == null ? void 0 : signal.removeEventListener("abort", abortListener);
77
+ resolve(outcome2);
78
+ };
79
+ const messageListener = (message) => {
80
+ if (isWorkerResult(message)) {
81
+ finish({ type: "result", result: message.result });
82
+ }
83
+ };
84
+ const errorListener = (error) => {
85
+ finish({ type: "error", error });
86
+ };
87
+ const exitListener = (code) => {
88
+ finish({ type: "exit", code });
89
+ };
90
+ const abortListener = () => {
91
+ finish({ type: "aborted" });
92
+ };
93
+ worker.on("message", messageListener);
94
+ worker.once("error", errorListener);
95
+ worker.once("exit", exitListener);
96
+ signal == null ? void 0 : signal.addEventListener("abort", abortListener, { once: true });
97
+ if (signal == null ? void 0 : signal.aborted) {
98
+ abortListener();
99
+ }
100
+ });
101
+ const outcome = await outcomePromise;
102
+ try {
103
+ if (outcome.type !== "exit") {
104
+ await worker.terminate();
105
+ }
106
+ await outputClosed;
107
+ } catch (error) {
108
+ if (outcome.type === "aborted" || (signal == null ? void 0 : signal.aborted)) {
109
+ throw signal.reason instanceof Error ? signal.reason : new import_plugin_workflow.WorkflowTimeoutError();
110
+ }
111
+ return {
112
+ status: import_plugin_workflow.JOB_STATUS.ERROR,
113
+ result: error instanceof Error ? error.message : String(error)
114
+ };
115
+ }
116
+ if (outcome.type === "aborted") {
117
+ throw (signal == null ? void 0 : signal.reason) instanceof Error ? signal.reason : new import_plugin_workflow.WorkflowTimeoutError();
118
+ }
119
+ if (outcome.type === "error") {
120
+ return {
121
+ status: import_plugin_workflow.JOB_STATUS.ERROR,
122
+ result: outcome.error.message
123
+ };
124
+ }
125
+ if (outcome.type === "exit" && outcome.code !== 0) {
126
+ return {
127
+ status: import_plugin_workflow.JOB_STATUS.ERROR,
128
+ result: `Worker stopped with exit code ${outcome.code}`
129
+ };
130
+ }
131
+ return {
132
+ status: import_plugin_workflow.JOB_STATUS.RESOLVED,
133
+ result: outcome.type === "result" ? outcome.result : void 0
134
+ };
135
+ }
136
+ }
137
+ // Annotate the CommonJS export names for ESM import in node:
138
+ 0 && (module.exports = {
139
+ ScriptWorkerRunner
140
+ });
@@ -0,0 +1,29 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+ import type WorkflowPlugin from '@nocobase/plugin-workflow';
10
+ import type { QueueEventOptions } from '@nocobase/server';
11
+ import { RunningJobs } from './RunningJobs';
12
+ export declare class TaskConsumer {
13
+ private readonly workflowPlugin;
14
+ private readonly runningJobs;
15
+ private ready;
16
+ private closing;
17
+ private readonly processing;
18
+ constructor(workflowPlugin: WorkflowPlugin, runningJobs: RunningJobs);
19
+ setReady(ready: boolean): void;
20
+ idle(): boolean;
21
+ beforeStop(): Promise<void>;
22
+ readonly process: QueueEventOptions['process'];
23
+ private processWithPermit;
24
+ private claimJob;
25
+ private finishClaimedJob;
26
+ private settleClaimedJob;
27
+ private updatePendingJob;
28
+ private startClaimHeartbeat;
29
+ }