@nocobase/plugin-workflow 2.2.0-beta.15 → 2.2.0-beta.16
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.
- package/dist/client/{67.56a3d15a55ab7d5c.js → 67.92c849b5dbe07c33.js} +1 -1
- package/dist/client/WorkflowTasks.d.ts +26 -3
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.js +1 -1
- package/dist/common/collections/userWorkflowTaskStats.d.ts +54 -0
- package/dist/common/collections/userWorkflowTaskStats.js +87 -0
- package/dist/externalVersion.js +13 -13
- package/dist/locale/en-US.json +4 -0
- package/dist/locale/zh-CN.json +4 -0
- package/dist/node_modules/cron-parser/package.json +1 -1
- package/dist/node_modules/joi/package.json +1 -1
- package/dist/node_modules/lru-cache/package.json +1 -1
- package/dist/node_modules/nodejs-snowflake/package.json +1 -1
- package/dist/server/Dispatcher.d.ts +24 -13
- package/dist/server/Dispatcher.js +160 -143
- package/dist/server/Plugin.d.ts +57 -11
- package/dist/server/Plugin.js +355 -15
- package/dist/server/Processor.d.ts +1 -7
- package/dist/server/Processor.js +11 -7
- package/dist/server/actions/executions.js +3 -6
- package/dist/server/actions/index.js +3 -1
- package/dist/server/actions/jobs.js +1 -2
- package/dist/server/{migrations/20260713000000-remove-workflow-validation.d.ts → actions/userWorkflowTaskStats.d.ts} +2 -5
- package/dist/server/actions/userWorkflowTaskStats.js +112 -0
- package/dist/server/actions/workflows.js +17 -0
- package/dist/server/collections/userWorkflowTaskStats.d.ts +11 -0
- package/dist/server/collections/userWorkflowTaskStats.js +43 -0
- package/dist/server/index.d.ts +1 -0
- package/dist/server/types/Execution.d.ts +2 -0
- package/dist/server/types/Job.d.ts +5 -0
- package/dist/server/utils.d.ts +1 -0
- package/dist/server/utils.js +5 -0
- package/dist/swagger/index.d.ts +68 -1
- package/dist/swagger/index.js +61 -1
- package/package.json +2 -2
- package/dist/server/migrations/20260713000000-remove-workflow-validation.js +0 -56
|
@@ -35,30 +35,52 @@ var import_constants = require("./constants");
|
|
|
35
35
|
var import_Plugin = require("./Plugin");
|
|
36
36
|
var import_utils = require("./utils");
|
|
37
37
|
const EXECUTION_ACQUIRE_MAX_ATTEMPTS = 5;
|
|
38
|
-
const
|
|
38
|
+
const QUEUE_TASK_MAX_ATTEMPTS = 3;
|
|
39
|
+
const RECOVERY_BATCH_SIZE = 100;
|
|
40
|
+
const RECOVERY_LOCK_TTL = 3e5;
|
|
39
41
|
class Dispatcher {
|
|
40
42
|
constructor(plugin) {
|
|
41
43
|
this.plugin = plugin;
|
|
42
44
|
}
|
|
43
45
|
ready = false;
|
|
44
46
|
executing = null;
|
|
47
|
+
recovering = null;
|
|
45
48
|
saving = null;
|
|
46
|
-
pending = [];
|
|
47
49
|
events = [];
|
|
48
50
|
eventsCount = 0;
|
|
49
51
|
get idle() {
|
|
50
|
-
return this.ready && !this.executing && !this.saving && !this.
|
|
52
|
+
return this.ready && !this.executing && !this.saving && !this.events.length;
|
|
51
53
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
54
|
+
onQueueTask = async (event) => {
|
|
55
|
+
var _a;
|
|
56
|
+
const task = event;
|
|
57
|
+
let next = null;
|
|
58
|
+
const previous = this.executing;
|
|
59
|
+
const executing = (async () => {
|
|
60
|
+
await (previous == null ? void 0 : previous.catch(() => void 0));
|
|
61
|
+
this.plugin.getLogger("dispatcher").info(`workflow queue task for execution (${task.executionId}) received from queue`);
|
|
62
|
+
next = await this.resolveTask(task);
|
|
63
|
+
if (!next) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
this.plugin.getLogger(next[0].workflowId).info(`queued execution (${next[0].id}) ready to process`);
|
|
67
|
+
await this.process(next[0], next[1], { rerun: next[2] });
|
|
68
|
+
})();
|
|
69
|
+
this.executing = executing;
|
|
70
|
+
try {
|
|
71
|
+
await executing;
|
|
72
|
+
} catch (error) {
|
|
73
|
+
const workflowId = ((_a = next == null ? void 0 : next[0]) == null ? void 0 : _a.workflowId) ?? task.executionId;
|
|
74
|
+
this.plugin.getLogger(workflowId).error(`workflow queue task failed`, { error });
|
|
75
|
+
throw error;
|
|
76
|
+
} finally {
|
|
77
|
+
if (this.executing === executing) {
|
|
78
|
+
this.executing = null;
|
|
79
|
+
}
|
|
80
|
+
if (this.events.length) {
|
|
81
|
+
this.saveEvent();
|
|
82
|
+
}
|
|
59
83
|
}
|
|
60
|
-
this.plugin.getLogger(execution.workflowId).info(`execution (${execution.id}) received from queue, adding to pending list`);
|
|
61
|
-
await this.run({ execution });
|
|
62
84
|
};
|
|
63
85
|
setReady(ready) {
|
|
64
86
|
this.ready = ready;
|
|
@@ -118,20 +140,12 @@ class Dispatcher {
|
|
|
118
140
|
try {
|
|
119
141
|
const execution = await this.createExecution(...event);
|
|
120
142
|
if (!execution.dispatched) {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
);
|
|
128
|
-
try {
|
|
129
|
-
await this.plugin.app.eventQueue.publish(this.plugin.channelPendingExecution, {
|
|
130
|
-
executionId: execution.id
|
|
131
|
-
});
|
|
132
|
-
} catch (qErr) {
|
|
133
|
-
logger.error(`publishing execution (${execution.id}) to queue failed:`, { error: qErr });
|
|
134
|
-
}
|
|
143
|
+
try {
|
|
144
|
+
await this.enqueue({
|
|
145
|
+
executionId: execution.id
|
|
146
|
+
});
|
|
147
|
+
} catch (qErr) {
|
|
148
|
+
logger.error(`publishing execution (${execution.id}) to queue failed:`, { error: qErr });
|
|
135
149
|
}
|
|
136
150
|
}
|
|
137
151
|
} catch (error) {
|
|
@@ -142,31 +156,17 @@ class Dispatcher {
|
|
|
142
156
|
this.saving = null;
|
|
143
157
|
if (this.events.length) {
|
|
144
158
|
this.saveEvent();
|
|
145
|
-
} else {
|
|
146
|
-
this.dispatch();
|
|
147
159
|
}
|
|
148
160
|
}
|
|
149
161
|
})();
|
|
150
162
|
}
|
|
151
|
-
async resume(job) {
|
|
152
|
-
let { execution } = job;
|
|
153
|
-
if (!execution) {
|
|
154
|
-
execution = await job.getExecution();
|
|
155
|
-
}
|
|
156
|
-
this.plugin.getLogger(execution.workflowId).info(`execution (${execution.id}) resuming from job (${job.id}) added to pending list`);
|
|
157
|
-
await this.run({ execution, job });
|
|
158
|
-
}
|
|
159
|
-
async start(execution) {
|
|
160
|
-
if (execution.status) {
|
|
161
|
-
return;
|
|
162
|
-
}
|
|
163
|
-
this.plugin.getLogger(execution.workflowId).info(`starting deferred execution (${execution.id})`);
|
|
164
|
-
await this.run({ execution });
|
|
165
|
-
}
|
|
166
163
|
async beforeStop() {
|
|
167
164
|
this.ready = false;
|
|
168
165
|
this.plugin.getLogger("dispatcher").info("app is stopping, draining local queues...");
|
|
169
|
-
|
|
166
|
+
if (this.recovering) {
|
|
167
|
+
await this.recovering;
|
|
168
|
+
}
|
|
169
|
+
while (this.saving || this.executing || this.events.length) {
|
|
170
170
|
if (this.saving) {
|
|
171
171
|
await this.saving;
|
|
172
172
|
}
|
|
@@ -176,85 +176,131 @@ class Dispatcher {
|
|
|
176
176
|
if (this.events.length && !this.saving) {
|
|
177
177
|
this.saveEvent();
|
|
178
178
|
}
|
|
179
|
-
if (this.pending.length && !this.executing) {
|
|
180
|
-
this.dispatch();
|
|
181
|
-
}
|
|
182
179
|
await new Promise((resolve) => setImmediate(resolve));
|
|
183
180
|
}
|
|
184
181
|
this.plugin.getLogger("dispatcher").info("local queues drained");
|
|
185
182
|
}
|
|
186
|
-
|
|
187
|
-
if (!this.ready
|
|
183
|
+
async recover(options = {}) {
|
|
184
|
+
if (!this.ready) {
|
|
188
185
|
return;
|
|
189
186
|
}
|
|
190
|
-
if (this.
|
|
191
|
-
this.
|
|
187
|
+
if (this.recovering) {
|
|
188
|
+
await this.recovering;
|
|
192
189
|
return;
|
|
193
190
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
191
|
+
const recovering = this.recoverQueueTasks(options.gracePeriod ?? 0);
|
|
192
|
+
this.recovering = recovering;
|
|
193
|
+
try {
|
|
194
|
+
await recovering;
|
|
195
|
+
} finally {
|
|
196
|
+
if (this.recovering === recovering) {
|
|
197
|
+
this.recovering = null;
|
|
198
|
+
}
|
|
197
199
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
200
|
+
}
|
|
201
|
+
async recoverQueueTasks(gracePeriod) {
|
|
202
|
+
const logger = this.plugin.getLogger("dispatcher");
|
|
203
|
+
try {
|
|
204
|
+
if (!this.plugin.serving()) {
|
|
205
|
+
logger.warn(
|
|
206
|
+
`${import_Plugin.WORKER_JOB_WORKFLOW_PROCESS} is not serving on this instance, workflow queue recovery will be ignored`
|
|
207
|
+
);
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
let lock;
|
|
201
211
|
try {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
if (execution) {
|
|
208
|
-
next = [execution, pending == null ? void 0 : pending.job, pending == null ? void 0 : pending.rerun];
|
|
209
|
-
}
|
|
210
|
-
if (pending && next) {
|
|
211
|
-
this.plugin.getLogger(next[0].workflowId).info(`pending execution (${next[0].id}) ready to process`);
|
|
212
|
-
}
|
|
213
|
-
} else {
|
|
214
|
-
this.plugin.getLogger("dispatcher").warn(
|
|
215
|
-
`${import_Plugin.WORKER_JOB_WORKFLOW_PROCESS} is not serving on this instance or app not ready, new dispatching will be ignored`
|
|
216
|
-
);
|
|
212
|
+
lock = await this.plugin.app.lockManager.tryAcquire(`workflow:recover:${this.plugin.app.name}`);
|
|
213
|
+
} catch (error) {
|
|
214
|
+
if ((0, import_utils.isLockAcquireError)(error)) {
|
|
215
|
+
logger.debug(`workflow queue recovery is already running on another instance`);
|
|
216
|
+
return;
|
|
217
217
|
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
218
|
+
throw error;
|
|
219
|
+
}
|
|
220
|
+
await lock.runExclusive(async () => {
|
|
221
|
+
let executionCursor = null;
|
|
222
|
+
while (this.ready) {
|
|
223
|
+
const executions = await this.findQueueingExecutions(executionCursor, gracePeriod);
|
|
224
|
+
if (!executions.length) {
|
|
225
|
+
break;
|
|
226
226
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
if (dispatchAttempts < PENDING_DISPATCH_MAX_ATTEMPTS) {
|
|
233
|
-
this.pending.push({ ...pending, dispatchAttempts });
|
|
234
|
-
} else {
|
|
235
|
-
this.plugin.getLogger(pending.execution.workflowId).error(`pending execution (${pending.execution.id}) dispatch failed, local retry limit reached`, {
|
|
236
|
-
error,
|
|
237
|
-
dispatchAttempts
|
|
238
|
-
});
|
|
227
|
+
for (const execution of executions) {
|
|
228
|
+
if (!this.ready) {
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
await this.enqueue({ executionId: execution.id });
|
|
239
232
|
}
|
|
233
|
+
executionCursor = executions[executions.length - 1].id;
|
|
240
234
|
}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
})();
|
|
235
|
+
}, RECOVERY_LOCK_TTL);
|
|
236
|
+
} catch (error) {
|
|
237
|
+
logger.error(`workflow queue recovery failed`, { error });
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
async enqueue(task) {
|
|
241
|
+
await this.plugin.app.eventQueue.publish(this.plugin.channelPendingExecution, task, {
|
|
242
|
+
maxRetries: QUEUE_TASK_MAX_ATTEMPTS - 1
|
|
243
|
+
});
|
|
251
244
|
}
|
|
252
|
-
async
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
245
|
+
async loadJob(jobId) {
|
|
246
|
+
if (jobId == null) {
|
|
247
|
+
return null;
|
|
248
|
+
}
|
|
249
|
+
return this.plugin.db.getRepository("jobs").findOne({
|
|
250
|
+
filterByTk: jobId
|
|
256
251
|
});
|
|
257
|
-
|
|
252
|
+
}
|
|
253
|
+
async findQueueingExecutions(afterId, gracePeriod) {
|
|
254
|
+
const executions = await this.plugin.db.getRepository("executions").find({
|
|
255
|
+
filter: {
|
|
256
|
+
...afterId == null ? {} : { id: { $gt: afterId } },
|
|
257
|
+
...gracePeriod > 0 ? { createdAt: { $lt: new Date(Date.now() - gracePeriod) } } : {},
|
|
258
|
+
dispatched: false,
|
|
259
|
+
status: import_constants.EXECUTION_STATUS.QUEUEING,
|
|
260
|
+
startedAt: null,
|
|
261
|
+
"workflow.enabled": true
|
|
262
|
+
},
|
|
263
|
+
sort: "id",
|
|
264
|
+
limit: RECOVERY_BATCH_SIZE
|
|
265
|
+
});
|
|
266
|
+
for (const execution of executions) {
|
|
267
|
+
this.plugin.getLogger(execution.workflowId).info(`queueing execution (${execution.id}) found, publishing task`);
|
|
268
|
+
}
|
|
269
|
+
return executions;
|
|
270
|
+
}
|
|
271
|
+
async resolveTask(task) {
|
|
272
|
+
const executionInput = await this.plugin.db.getRepository("executions").findOne({
|
|
273
|
+
filterByTk: task.executionId
|
|
274
|
+
});
|
|
275
|
+
if (!executionInput) {
|
|
276
|
+
this.plugin.getLogger("dispatcher").warn(`execution (${task.executionId}) not found, queue task ignored`);
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
279
|
+
if (task.jobId == null && task.rerun == null && executionInput.status === import_constants.EXECUTION_STATUS.STARTED && executionInput.startedAt) {
|
|
280
|
+
this.plugin.getLogger(executionInput.workflowId).warn(`execution (${executionInput.id}) has already started, start task ignored`);
|
|
281
|
+
return null;
|
|
282
|
+
}
|
|
283
|
+
let job = null;
|
|
284
|
+
if (task.jobId != null) {
|
|
285
|
+
job = await this.loadJob(task.jobId);
|
|
286
|
+
if (!job) {
|
|
287
|
+
this.plugin.getLogger(executionInput.workflowId).warn(`job (${task.jobId}) not found, resume ignored`);
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
290
|
+
if (String(job.executionId) !== String(executionInput.id)) {
|
|
291
|
+
this.plugin.getLogger(executionInput.workflowId).warn(`job (${job.id}) does not belong to execution (${executionInput.id}), resume ignored`);
|
|
292
|
+
return null;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
const execution = await this.prepare(executionInput);
|
|
296
|
+
if (!execution) {
|
|
297
|
+
return null;
|
|
298
|
+
}
|
|
299
|
+
if (job) {
|
|
300
|
+
job.execution = execution;
|
|
301
|
+
return [execution, job];
|
|
302
|
+
}
|
|
303
|
+
return [execution, void 0, task.rerun];
|
|
258
304
|
}
|
|
259
305
|
async triggerSync(workflow, context, { deferred, ...options } = {}) {
|
|
260
306
|
let execution;
|
|
@@ -367,7 +413,7 @@ class Dispatcher {
|
|
|
367
413
|
return execution;
|
|
368
414
|
}
|
|
369
415
|
async prepare(input, options = {}) {
|
|
370
|
-
const logger =
|
|
416
|
+
const logger = this.plugin.getLogger(input.workflowId);
|
|
371
417
|
if (options.transaction) {
|
|
372
418
|
try {
|
|
373
419
|
return await this.acquireExecution(input, options, options.transaction);
|
|
@@ -402,8 +448,8 @@ class Dispatcher {
|
|
|
402
448
|
},
|
|
403
449
|
{
|
|
404
450
|
logger,
|
|
405
|
-
conflictMessage:
|
|
406
|
-
maxAttemptsMessage:
|
|
451
|
+
conflictMessage: `acquiring queue task execution (${input.id}) conflicted with another worker, retrying`,
|
|
452
|
+
maxAttemptsMessage: `acquiring queue task execution (${input.id}) reached max retry attempts`
|
|
407
453
|
}
|
|
408
454
|
);
|
|
409
455
|
} catch (error) {
|
|
@@ -415,39 +461,10 @@ class Dispatcher {
|
|
|
415
461
|
return result;
|
|
416
462
|
}
|
|
417
463
|
async acquireExecution(input, options, transaction) {
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
if (!options.immediate || execution.status !== import_constants.EXECUTION_STATUS.QUEUEING) {
|
|
421
|
-
await execution.reload({ transaction });
|
|
422
|
-
}
|
|
423
|
-
} else {
|
|
424
|
-
const workflowIds = [...this.plugin.enabledCache.keys()];
|
|
425
|
-
if (!workflowIds.length) {
|
|
426
|
-
this.plugin.getLogger("dispatcher").debug(`no enabled workflow to process`);
|
|
427
|
-
return null;
|
|
428
|
-
}
|
|
429
|
-
execution = await this.plugin.db.getRepository("executions").findOne({
|
|
430
|
-
filter: {
|
|
431
|
-
dispatched: false,
|
|
432
|
-
status: import_constants.EXECUTION_STATUS.QUEUEING,
|
|
433
|
-
startedAt: null,
|
|
434
|
-
workflowId: workflowIds
|
|
435
|
-
},
|
|
436
|
-
sort: "id",
|
|
437
|
-
transaction,
|
|
438
|
-
lock: transaction.LOCK.UPDATE,
|
|
439
|
-
skipLocked: true
|
|
440
|
-
});
|
|
441
|
-
if (execution) {
|
|
442
|
-
this.plugin.getLogger(execution.workflowId).info(`execution (${execution.id}) fetched from db`);
|
|
443
|
-
} else {
|
|
444
|
-
this.plugin.getLogger("dispatcher").debug(`no execution in db queued to process`);
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
if (!execution) {
|
|
448
|
-
return null;
|
|
464
|
+
if (!options.immediate || input.status !== import_constants.EXECUTION_STATUS.QUEUEING) {
|
|
465
|
+
await input.reload({ transaction });
|
|
449
466
|
}
|
|
450
|
-
return this.enter(
|
|
467
|
+
return this.enter(input, transaction);
|
|
451
468
|
}
|
|
452
469
|
async acquireWithRetry(acquire, options) {
|
|
453
470
|
for (let attempt = 1; attempt <= EXECUTION_ACQUIRE_MAX_ATTEMPTS; attempt++) {
|
|
@@ -528,7 +545,7 @@ class Dispatcher {
|
|
|
528
545
|
var _a, _b, _c;
|
|
529
546
|
if (!execution.dispatched) {
|
|
530
547
|
await execution.update({ dispatched: true, status: import_constants.EXECUTION_STATUS.STARTED });
|
|
531
|
-
logger.info(`execution (${execution.id}) from
|
|
548
|
+
logger.info(`execution (${execution.id}) from workflow queue updated to started`);
|
|
532
549
|
}
|
|
533
550
|
this.plugin.timeoutManager.scheduleExecutionTimeout(execution);
|
|
534
551
|
const processor = this.plugin.createProcessor(execution, processorOptions);
|
package/dist/server/Plugin.d.ts
CHANGED
|
@@ -11,16 +11,39 @@ import { Transactionable } from 'sequelize';
|
|
|
11
11
|
import { Plugin } from '@nocobase/server';
|
|
12
12
|
import { Registry } from '@nocobase/utils';
|
|
13
13
|
import { Logger } from '@nocobase/logger';
|
|
14
|
-
import
|
|
15
|
-
import Processor from './Processor';
|
|
14
|
+
import { EventOptions } from './Dispatcher';
|
|
15
|
+
import Processor, { ProcessorRerunOptions } from './Processor';
|
|
16
16
|
import ExecutionTimeoutManager from './ExecutionTimeoutManager';
|
|
17
17
|
import RunningExecutionRegistry from './RunningExecutionRegistry';
|
|
18
18
|
import { CustomFunction } from './functions';
|
|
19
19
|
import Trigger from './triggers';
|
|
20
20
|
import { InstructionInterface } from './instructions';
|
|
21
|
-
import type { ExecutionModel, WorkflowModel } from './types';
|
|
21
|
+
import type { ExecutionModel, JobModel, WorkflowModel } from './types';
|
|
22
22
|
import type { Transaction } from '@nocobase/database';
|
|
23
23
|
type ID = number | string;
|
|
24
|
+
type TaskStats = {
|
|
25
|
+
pending: number;
|
|
26
|
+
all: number;
|
|
27
|
+
};
|
|
28
|
+
export type TaskStatsRow = {
|
|
29
|
+
userId: number;
|
|
30
|
+
workflowKey: string;
|
|
31
|
+
type: string;
|
|
32
|
+
pending: number;
|
|
33
|
+
all: number;
|
|
34
|
+
};
|
|
35
|
+
export type RepairTaskStatsOptions = {
|
|
36
|
+
userIds?: number[];
|
|
37
|
+
workflowKeys?: string[];
|
|
38
|
+
types?: string[];
|
|
39
|
+
transaction?: Transaction;
|
|
40
|
+
silent?: boolean;
|
|
41
|
+
};
|
|
42
|
+
export type TaskStatsProvider = {
|
|
43
|
+
collectTaskStats: (options: RepairTaskStatsOptions, context: {
|
|
44
|
+
plugin: PluginWorkflowServer;
|
|
45
|
+
}) => Promise<TaskStatsRow[]>;
|
|
46
|
+
};
|
|
24
47
|
export declare const WORKER_JOB_WORKFLOW_PROCESS = "workflow:process";
|
|
25
48
|
export default class PluginWorkflowServer extends Plugin {
|
|
26
49
|
instructions: Registry<InstructionInterface>;
|
|
@@ -35,6 +58,7 @@ export default class PluginWorkflowServer extends Plugin {
|
|
|
35
58
|
private loggerCache;
|
|
36
59
|
private meter;
|
|
37
60
|
private checker;
|
|
61
|
+
private taskStatsProviders;
|
|
38
62
|
private onBeforeSave;
|
|
39
63
|
private onAfterCreate;
|
|
40
64
|
private onAfterUpdate;
|
|
@@ -75,15 +99,24 @@ export default class PluginWorkflowServer extends Plugin {
|
|
|
75
99
|
load(): Promise<void>;
|
|
76
100
|
private toggle;
|
|
77
101
|
trigger(workflow: WorkflowModel, context: object, options?: EventOptions): void | Promise<Processor | null | void>;
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
102
|
+
rerun(execution: ExecutionModel | ID, rerun?: ProcessorRerunOptions): Promise<void>;
|
|
103
|
+
recover(): Promise<void>;
|
|
104
|
+
/**
|
|
105
|
+
* Persist the current job state and publish a poke that evaluates that state.
|
|
106
|
+
*
|
|
107
|
+
* PENDING resume calls are valid for instructions such as delay and sequential approval.
|
|
108
|
+
* Callers that aggregate multiple user actions must only call this method when their
|
|
109
|
+
* atomic update changes the job from PENDING to a terminal status.
|
|
110
|
+
* Persistence and queue publication failures are logged and rethrown to awaiting callers.
|
|
111
|
+
*/
|
|
112
|
+
resume(job: JobModel): Promise<void>;
|
|
81
113
|
/**
|
|
82
114
|
* Start a deferred execution
|
|
83
115
|
* @experimental
|
|
84
116
|
*/
|
|
85
|
-
start(execution: ExecutionModel): Promise<void>;
|
|
117
|
+
start(execution: ExecutionModel | ID): Promise<void>;
|
|
86
118
|
createProcessor(execution: ExecutionModel, options?: {}): Processor;
|
|
119
|
+
private getModelId;
|
|
87
120
|
execute(workflow: WorkflowModel, values: any, options?: EventOptions): Promise<void | Processor>;
|
|
88
121
|
/**
|
|
89
122
|
* @experimental
|
|
@@ -94,12 +127,25 @@ export default class PluginWorkflowServer extends Plugin {
|
|
|
94
127
|
*/
|
|
95
128
|
useDataSourceTransaction(dataSourceName?: string, transaction?: Transaction | null, create?: false): Transaction | undefined;
|
|
96
129
|
useDataSourceTransaction(dataSourceName: string | undefined, transaction: Transaction | null | undefined, create: true): Transaction | Promise<Transaction> | undefined;
|
|
130
|
+
registerTaskStatsProvider(type: string, provider: TaskStatsProvider): void;
|
|
131
|
+
getWorkflowIdsByKey(workflowKey: string, transaction?: Transaction): Promise<any>;
|
|
132
|
+
private buildTaskStatsFilter;
|
|
133
|
+
private normalizeTaskStats;
|
|
134
|
+
private upsertTaskStatsRow;
|
|
135
|
+
refreshUserWorkflowTaskTypeStats(userId: number, type: string, { transaction }?: Transactionable): Promise<any>;
|
|
136
|
+
refreshUserWorkflowTaskWorkflowStats(userId: number, workflowKey: string, { transaction }?: Transactionable): Promise<any>;
|
|
137
|
+
private sendTaskWorkflowStatsUpdated;
|
|
138
|
+
updateTaskStatsByWorkflow(input: {
|
|
139
|
+
userId: number;
|
|
140
|
+
workflowKey: string;
|
|
141
|
+
type: string;
|
|
142
|
+
stats: TaskStats;
|
|
143
|
+
}, { transaction }?: Transactionable): Promise<void>;
|
|
144
|
+
repairTaskStats(options?: RepairTaskStatsOptions): Promise<void>;
|
|
97
145
|
/**
|
|
98
146
|
* @experimental
|
|
147
|
+
* @deprecated Use updateTaskStatsByWorkflow() when workflowKey is available.
|
|
99
148
|
*/
|
|
100
|
-
updateTasksStats(userId: number, type: string, stats: {
|
|
101
|
-
pending: number;
|
|
102
|
-
all: number;
|
|
103
|
-
}, { transaction }: Transactionable): Promise<void>;
|
|
149
|
+
updateTasksStats(userId: number, type: string, stats: TaskStats, { transaction }: Transactionable): Promise<void>;
|
|
104
150
|
}
|
|
105
151
|
export {};
|