@nocobase/plugin-workflow 1.5.0-beta.3 → 1.5.0-beta.30
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/112c72b90000c81b.js +10 -0
- package/dist/client/739d458621edf81f.js +10 -0
- package/dist/client/98864c2e0ff69ea1.js +10 -0
- package/dist/client/FlowContext.d.ts +2 -0
- package/dist/client/components/TriggerCollectionRecordSelect.d.ts +10 -0
- package/dist/client/components/index.d.ts +1 -0
- package/dist/client/constants.d.ts +1 -0
- package/dist/client/e7b9d67c6a964bec.js +10 -0
- package/dist/client/index.js +1 -566
- package/dist/client/triggers/collection.d.ts +14 -0
- package/dist/client/triggers/index.d.ts +3 -3
- package/dist/client/triggers/schedule/ScheduleModes.d.ts +170 -0
- package/dist/client/triggers/schedule/TriggerScheduleConfig.d.ts +10 -0
- package/dist/client/triggers/schedule/index.d.ts +13 -0
- package/dist/client/variable.d.ts +16 -1
- package/dist/externalVersion.js +11 -11
- package/dist/locale/zh-CN.json +19 -5
- package/dist/node_modules/cron-parser/package.json +1 -1
- package/dist/node_modules/lru-cache/package.json +1 -1
- package/dist/server/Plugin.d.ts +13 -6
- package/dist/server/Plugin.js +165 -83
- package/dist/server/Processor.js +3 -3
- package/dist/server/actions/workflows.d.ts +5 -0
- package/dist/server/actions/workflows.js +59 -61
- package/dist/server/collections/executions.js +8 -0
- package/dist/server/collections/workflows.js +2 -2
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +2 -0
- package/dist/server/instructions/CreateInstruction.js +1 -1
- package/dist/server/instructions/DestroyInstruction.js +1 -1
- package/dist/server/instructions/UpdateInstruction.js +1 -1
- package/dist/server/repositories/WorkflowRepository.d.ts +12 -0
- package/dist/server/repositories/WorkflowRepository.js +112 -0
- package/dist/server/triggers/CollectionTrigger.d.ts +7 -2
- package/dist/server/triggers/CollectionTrigger.js +104 -73
- package/dist/server/triggers/ScheduleTrigger/DateFieldScheduleTrigger.d.ts +3 -2
- package/dist/server/triggers/ScheduleTrigger/DateFieldScheduleTrigger.js +51 -17
- package/dist/server/triggers/ScheduleTrigger/StaticScheduleTrigger.d.ts +1 -0
- package/dist/server/triggers/ScheduleTrigger/StaticScheduleTrigger.js +3 -0
- package/dist/server/triggers/ScheduleTrigger/index.d.ts +1 -0
- package/dist/server/triggers/ScheduleTrigger/index.js +7 -0
- package/dist/server/triggers/index.d.ts +4 -2
- package/dist/server/triggers/index.js +4 -0
- package/package.json +3 -3
package/dist/server/Plugin.js
CHANGED
|
@@ -41,6 +41,7 @@ __export(Plugin_exports, {
|
|
|
41
41
|
module.exports = __toCommonJS(Plugin_exports);
|
|
42
42
|
var import_path = __toESM(require("path"));
|
|
43
43
|
var import_crypto = require("crypto");
|
|
44
|
+
var import_sequelize = require("sequelize");
|
|
44
45
|
var import_lru_cache = __toESM(require("lru-cache"));
|
|
45
46
|
var import_database = require("@nocobase/database");
|
|
46
47
|
var import_server = require("@nocobase/server");
|
|
@@ -58,6 +59,7 @@ var import_CreateInstruction = __toESM(require("./instructions/CreateInstruction
|
|
|
58
59
|
var import_DestroyInstruction = __toESM(require("./instructions/DestroyInstruction"));
|
|
59
60
|
var import_QueryInstruction = __toESM(require("./instructions/QueryInstruction"));
|
|
60
61
|
var import_UpdateInstruction = __toESM(require("./instructions/UpdateInstruction"));
|
|
62
|
+
var import_WorkflowRepository = __toESM(require("./repositories/WorkflowRepository"));
|
|
61
63
|
class PluginWorkflowServer extends import_server.Plugin {
|
|
62
64
|
instructions = new import_utils.Registry();
|
|
63
65
|
triggers = new import_utils.Registry();
|
|
@@ -71,23 +73,10 @@ class PluginWorkflowServer extends import_server.Plugin {
|
|
|
71
73
|
loggerCache;
|
|
72
74
|
meter = null;
|
|
73
75
|
checker = null;
|
|
74
|
-
onBeforeSave = async (instance,
|
|
76
|
+
onBeforeSave = async (instance, { transaction }) => {
|
|
75
77
|
const Model = instance.constructor;
|
|
76
78
|
if (instance.enabled) {
|
|
77
79
|
instance.set("current", true);
|
|
78
|
-
} else if (!instance.current) {
|
|
79
|
-
const count = await Model.count({
|
|
80
|
-
where: {
|
|
81
|
-
key: instance.key
|
|
82
|
-
},
|
|
83
|
-
transaction: options.transaction
|
|
84
|
-
});
|
|
85
|
-
if (!count) {
|
|
86
|
-
instance.set("current", true);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
if (!instance.changed("enabled") || !instance.enabled) {
|
|
90
|
-
return;
|
|
91
80
|
}
|
|
92
81
|
const previous = await Model.findOne({
|
|
93
82
|
where: {
|
|
@@ -97,39 +86,40 @@ class PluginWorkflowServer extends import_server.Plugin {
|
|
|
97
86
|
[import_database.Op.ne]: instance.id
|
|
98
87
|
}
|
|
99
88
|
},
|
|
100
|
-
transaction
|
|
89
|
+
transaction
|
|
101
90
|
});
|
|
102
|
-
if (previous) {
|
|
91
|
+
if (!previous) {
|
|
92
|
+
instance.set("current", true);
|
|
93
|
+
}
|
|
94
|
+
if (instance.current && previous) {
|
|
103
95
|
await previous.update(
|
|
104
96
|
{ enabled: false, current: null },
|
|
105
97
|
{
|
|
106
|
-
transaction
|
|
98
|
+
transaction,
|
|
107
99
|
hooks: false
|
|
108
100
|
}
|
|
109
101
|
);
|
|
110
|
-
this.toggle(previous, false);
|
|
102
|
+
this.toggle(previous, false, { transaction });
|
|
111
103
|
}
|
|
112
104
|
};
|
|
113
|
-
async
|
|
105
|
+
async handleSyncMessage(message) {
|
|
114
106
|
if (message.type === "statusChange") {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
if (enabled) {
|
|
118
|
-
let workflow = this.enabledCache.get(workflowId);
|
|
107
|
+
if (message.enabled) {
|
|
108
|
+
let workflow = this.enabledCache.get(message.workflowId);
|
|
119
109
|
if (workflow) {
|
|
120
110
|
await workflow.reload();
|
|
121
111
|
} else {
|
|
122
112
|
workflow = await this.db.getRepository("workflows").findOne({
|
|
123
|
-
filterByTk: workflowId
|
|
113
|
+
filterByTk: message.workflowId
|
|
124
114
|
});
|
|
125
115
|
}
|
|
126
116
|
if (workflow) {
|
|
127
|
-
this.toggle(workflow, true, true);
|
|
117
|
+
this.toggle(workflow, true, { silent: true });
|
|
128
118
|
}
|
|
129
119
|
} else {
|
|
130
|
-
const workflow = this.enabledCache.get(workflowId);
|
|
120
|
+
const workflow = this.enabledCache.get(message.workflowId);
|
|
131
121
|
if (workflow) {
|
|
132
|
-
this.toggle(workflow, false, true);
|
|
122
|
+
this.toggle(workflow, false, { silent: true });
|
|
133
123
|
}
|
|
134
124
|
}
|
|
135
125
|
}
|
|
@@ -137,7 +127,7 @@ class PluginWorkflowServer extends import_server.Plugin {
|
|
|
137
127
|
/**
|
|
138
128
|
* @experimental
|
|
139
129
|
*/
|
|
140
|
-
getLogger(workflowId) {
|
|
130
|
+
getLogger(workflowId = "dispatcher") {
|
|
141
131
|
const now = /* @__PURE__ */ new Date();
|
|
142
132
|
const date = `${now.getFullYear()}-${`0${now.getMonth() + 1}`.slice(-2)}-${`0${now.getDate()}`.slice(-2)}`;
|
|
143
133
|
const key = `${date}-${workflowId}}`;
|
|
@@ -200,6 +190,11 @@ class PluginWorkflowServer extends import_server.Plugin {
|
|
|
200
190
|
this.registerInstruction(name, instruction);
|
|
201
191
|
}
|
|
202
192
|
}
|
|
193
|
+
async beforeLoad() {
|
|
194
|
+
this.db.registerRepositories({
|
|
195
|
+
WorkflowRepository: import_WorkflowRepository.default
|
|
196
|
+
});
|
|
197
|
+
}
|
|
203
198
|
/**
|
|
204
199
|
* @internal
|
|
205
200
|
*/
|
|
@@ -248,31 +243,42 @@ class PluginWorkflowServer extends import_server.Plugin {
|
|
|
248
243
|
}
|
|
249
244
|
});
|
|
250
245
|
db.on("workflows.beforeSave", this.onBeforeSave);
|
|
251
|
-
db.on("workflows.afterCreate", (model) => {
|
|
246
|
+
db.on("workflows.afterCreate", (model, { transaction }) => {
|
|
252
247
|
if (model.enabled) {
|
|
253
|
-
this.toggle(model);
|
|
248
|
+
this.toggle(model, true, { transaction });
|
|
254
249
|
}
|
|
255
250
|
});
|
|
256
|
-
db.on(
|
|
257
|
-
|
|
251
|
+
db.on(
|
|
252
|
+
"workflows.afterUpdate",
|
|
253
|
+
(model, { transaction }) => this.toggle(model, model.enabled, { transaction })
|
|
254
|
+
);
|
|
255
|
+
db.on(
|
|
256
|
+
"workflows.afterDestroy",
|
|
257
|
+
(model, { transaction }) => this.toggle(model, false, { transaction })
|
|
258
|
+
);
|
|
258
259
|
this.app.on("afterStart", async () => {
|
|
259
|
-
this.app.setMaintainingMessage("check for not started executions");
|
|
260
260
|
this.ready = true;
|
|
261
261
|
const collection = db.getCollection("workflows");
|
|
262
262
|
const workflows = await collection.repository.find({
|
|
263
263
|
filter: { enabled: true }
|
|
264
264
|
});
|
|
265
265
|
workflows.forEach((workflow) => {
|
|
266
|
-
this.toggle(workflow);
|
|
266
|
+
this.toggle(workflow, true, { silent: true });
|
|
267
267
|
});
|
|
268
268
|
this.checker = setInterval(() => {
|
|
269
|
+
this.getLogger("dispatcher").info(`(cycling) check for queueing executions`);
|
|
269
270
|
this.dispatch();
|
|
270
271
|
}, 3e5);
|
|
272
|
+
this.app.on("workflow:dispatch", () => {
|
|
273
|
+
this.app.logger.info("workflow:dispatch");
|
|
274
|
+
this.dispatch();
|
|
275
|
+
});
|
|
276
|
+
this.getLogger("dispatcher").info("(starting) check for queueing executions");
|
|
271
277
|
this.dispatch();
|
|
272
278
|
});
|
|
273
279
|
this.app.on("beforeStop", async () => {
|
|
274
280
|
for (const workflow of this.enabledCache.values()) {
|
|
275
|
-
this.toggle(workflow, false);
|
|
281
|
+
this.toggle(workflow, false, { silent: true });
|
|
276
282
|
}
|
|
277
283
|
this.ready = false;
|
|
278
284
|
if (this.events.length) {
|
|
@@ -286,7 +292,7 @@ class PluginWorkflowServer extends import_server.Plugin {
|
|
|
286
292
|
}
|
|
287
293
|
});
|
|
288
294
|
}
|
|
289
|
-
toggle(workflow, enable, silent =
|
|
295
|
+
toggle(workflow, enable, { silent, transaction } = {}) {
|
|
290
296
|
const type = workflow.get("type");
|
|
291
297
|
const trigger = this.triggers.get(type);
|
|
292
298
|
if (!trigger) {
|
|
@@ -306,11 +312,14 @@ class PluginWorkflowServer extends import_server.Plugin {
|
|
|
306
312
|
this.enabledCache.delete(workflow.id);
|
|
307
313
|
}
|
|
308
314
|
if (!silent) {
|
|
309
|
-
this.
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
315
|
+
this.sendSyncMessage(
|
|
316
|
+
{
|
|
317
|
+
type: "statusChange",
|
|
318
|
+
workflowId: workflow.id,
|
|
319
|
+
enabled: next
|
|
320
|
+
},
|
|
321
|
+
{ transaction }
|
|
322
|
+
);
|
|
314
323
|
}
|
|
315
324
|
}
|
|
316
325
|
trigger(workflow, context, options = {}) {
|
|
@@ -320,11 +329,24 @@ class PluginWorkflowServer extends import_server.Plugin {
|
|
|
320
329
|
logger.debug(`ignored event data:`, context);
|
|
321
330
|
return;
|
|
322
331
|
}
|
|
332
|
+
if (!options.force && !options.manually && !workflow.enabled) {
|
|
333
|
+
logger.warn(`workflow ${workflow.id} is not enabled, event will be ignored`);
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
const duplicated = this.events.find(([w, c, { eventKey }]) => {
|
|
337
|
+
if (eventKey && options.eventKey) {
|
|
338
|
+
return eventKey === options.eventKey;
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
if (duplicated) {
|
|
342
|
+
logger.warn(`event of workflow ${workflow.id} is duplicated (${options.eventKey}), event will be ignored`);
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
323
345
|
if (context == null) {
|
|
324
346
|
logger.warn(`workflow ${workflow.id} event data context is null, event will be ignored`);
|
|
325
347
|
return;
|
|
326
348
|
}
|
|
327
|
-
if (this.isWorkflowSync(workflow)) {
|
|
349
|
+
if (options.manually || this.isWorkflowSync(workflow)) {
|
|
328
350
|
return this.triggerSync(workflow, context, options);
|
|
329
351
|
}
|
|
330
352
|
const { transaction, ...rest } = options;
|
|
@@ -333,6 +355,7 @@ class PluginWorkflowServer extends import_server.Plugin {
|
|
|
333
355
|
logger.info(`new event triggered, now events: ${this.events.length}`);
|
|
334
356
|
logger.debug(`event data:`, { context });
|
|
335
357
|
if (this.events.length > 1) {
|
|
358
|
+
logger.info(`new event is pending to be prepared after previous preparation is finished`);
|
|
336
359
|
return;
|
|
337
360
|
}
|
|
338
361
|
setTimeout(this.prepare);
|
|
@@ -360,31 +383,61 @@ class PluginWorkflowServer extends import_server.Plugin {
|
|
|
360
383
|
`execution (${job.execution.id}) resuming from job (${job.id}) added to pending list`
|
|
361
384
|
);
|
|
362
385
|
this.pending.push([job.execution, job]);
|
|
386
|
+
if (this.executing) {
|
|
387
|
+
await this.executing;
|
|
388
|
+
}
|
|
363
389
|
this.dispatch();
|
|
364
390
|
}
|
|
365
391
|
/**
|
|
366
392
|
* Start a deferred execution
|
|
367
393
|
* @experimental
|
|
368
394
|
*/
|
|
369
|
-
start(execution) {
|
|
395
|
+
async start(execution) {
|
|
370
396
|
if (execution.status !== import_constants.EXECUTION_STATUS.STARTED) {
|
|
371
397
|
return;
|
|
372
398
|
}
|
|
373
399
|
this.pending.push([execution]);
|
|
400
|
+
if (this.executing) {
|
|
401
|
+
await this.executing;
|
|
402
|
+
}
|
|
374
403
|
this.dispatch();
|
|
375
404
|
}
|
|
376
|
-
|
|
377
|
-
|
|
405
|
+
async validateEvent(workflow, context, options) {
|
|
406
|
+
const trigger = this.triggers.get(workflow.type);
|
|
407
|
+
const triggerValid = await trigger.validateEvent(workflow, context, options);
|
|
408
|
+
if (!triggerValid) {
|
|
409
|
+
return false;
|
|
410
|
+
}
|
|
411
|
+
const { stack } = options;
|
|
412
|
+
let valid = true;
|
|
413
|
+
if ((stack == null ? void 0 : stack.length) > 0) {
|
|
414
|
+
const existed = await workflow.countExecutions({
|
|
415
|
+
where: {
|
|
416
|
+
id: stack
|
|
417
|
+
},
|
|
418
|
+
transaction: options.transaction
|
|
419
|
+
});
|
|
420
|
+
if (existed) {
|
|
421
|
+
this.getLogger(workflow.id).warn(
|
|
422
|
+
`workflow ${workflow.id} has already been triggered in stacks executions (${stack}), and newly triggering will be skipped.`
|
|
423
|
+
);
|
|
424
|
+
valid = false;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
return valid;
|
|
378
428
|
}
|
|
379
429
|
async createExecution(workflow, context, options) {
|
|
380
|
-
|
|
381
|
-
const
|
|
382
|
-
const
|
|
430
|
+
var _a;
|
|
431
|
+
const { deferred } = options;
|
|
432
|
+
const transaction = await this.useDataSourceTransaction("main", options.transaction, true);
|
|
433
|
+
const sameTransaction = options.transaction === transaction;
|
|
434
|
+
const valid = await this.validateEvent(workflow, context, { ...options, transaction });
|
|
383
435
|
if (!valid) {
|
|
384
|
-
if (!
|
|
436
|
+
if (!sameTransaction) {
|
|
385
437
|
await transaction.commit();
|
|
386
438
|
}
|
|
387
|
-
|
|
439
|
+
(_a = options.onTriggerFail) == null ? void 0 : _a.call(options, workflow, context, options);
|
|
440
|
+
return Promise.reject(new Error("event is not valid"));
|
|
388
441
|
}
|
|
389
442
|
let execution;
|
|
390
443
|
try {
|
|
@@ -393,12 +446,13 @@ class PluginWorkflowServer extends import_server.Plugin {
|
|
|
393
446
|
context,
|
|
394
447
|
key: workflow.key,
|
|
395
448
|
eventKey: options.eventKey ?? (0, import_crypto.randomUUID)(),
|
|
449
|
+
stack: options.stack,
|
|
396
450
|
status: deferred ? import_constants.EXECUTION_STATUS.STARTED : import_constants.EXECUTION_STATUS.QUEUEING
|
|
397
451
|
},
|
|
398
452
|
{ transaction }
|
|
399
453
|
);
|
|
400
454
|
} catch (err) {
|
|
401
|
-
if (!
|
|
455
|
+
if (!sameTransaction) {
|
|
402
456
|
await transaction.rollback();
|
|
403
457
|
}
|
|
404
458
|
throw err;
|
|
@@ -419,7 +473,7 @@ class PluginWorkflowServer extends import_server.Plugin {
|
|
|
419
473
|
transaction
|
|
420
474
|
}
|
|
421
475
|
);
|
|
422
|
-
if (!
|
|
476
|
+
if (!sameTransaction) {
|
|
423
477
|
await transaction.commit();
|
|
424
478
|
}
|
|
425
479
|
execution.workflow = workflow;
|
|
@@ -432,7 +486,7 @@ class PluginWorkflowServer extends import_server.Plugin {
|
|
|
432
486
|
const event = this.events.shift();
|
|
433
487
|
this.eventsCount = this.events.length;
|
|
434
488
|
if (!event) {
|
|
435
|
-
this.getLogger("dispatcher").
|
|
489
|
+
this.getLogger("dispatcher").info(`events queue is empty, no need to prepare`);
|
|
436
490
|
return;
|
|
437
491
|
}
|
|
438
492
|
const logger = this.getLogger(event[0].id);
|
|
@@ -442,8 +496,8 @@ class PluginWorkflowServer extends import_server.Plugin {
|
|
|
442
496
|
if ((execution == null ? void 0 : execution.status) === import_constants.EXECUTION_STATUS.QUEUEING && !this.executing && !this.pending.length) {
|
|
443
497
|
this.pending.push([execution]);
|
|
444
498
|
}
|
|
445
|
-
} catch (
|
|
446
|
-
logger.error(`failed to create execution
|
|
499
|
+
} catch (error) {
|
|
500
|
+
logger.error(`failed to create execution:`, { error });
|
|
447
501
|
}
|
|
448
502
|
if (this.events.length) {
|
|
449
503
|
await this.prepare();
|
|
@@ -465,38 +519,56 @@ class PluginWorkflowServer extends import_server.Plugin {
|
|
|
465
519
|
}
|
|
466
520
|
this.executing = (async () => {
|
|
467
521
|
let next = null;
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
"workflow.enabled": true,
|
|
477
|
-
"workflow.id": {
|
|
478
|
-
[import_database.Op.not]: null
|
|
479
|
-
}
|
|
522
|
+
if (this.pending.length) {
|
|
523
|
+
next = this.pending.shift();
|
|
524
|
+
this.getLogger(next[0].workflowId).info(`pending execution (${next[0].id}) ready to process`);
|
|
525
|
+
} else {
|
|
526
|
+
try {
|
|
527
|
+
await this.db.sequelize.transaction(
|
|
528
|
+
{
|
|
529
|
+
isolationLevel: this.db.options.dialect === "sqlite" ? [][0] : import_sequelize.Transaction.ISOLATION_LEVELS.REPEATABLE_READ
|
|
480
530
|
},
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
531
|
+
async (transaction) => {
|
|
532
|
+
const execution = await this.db.getRepository("executions").findOne({
|
|
533
|
+
filter: {
|
|
534
|
+
status: import_constants.EXECUTION_STATUS.QUEUEING,
|
|
535
|
+
"workflow.enabled": true
|
|
536
|
+
},
|
|
537
|
+
sort: "id",
|
|
538
|
+
transaction
|
|
539
|
+
});
|
|
540
|
+
if (execution) {
|
|
541
|
+
this.getLogger(execution.workflowId).info(`execution (${execution.id}) fetched from db`);
|
|
542
|
+
await execution.update(
|
|
543
|
+
{
|
|
544
|
+
status: import_constants.EXECUTION_STATUS.STARTED
|
|
545
|
+
},
|
|
546
|
+
{ transaction }
|
|
547
|
+
);
|
|
548
|
+
execution.workflow = this.enabledCache.get(execution.workflowId);
|
|
549
|
+
next = [execution];
|
|
550
|
+
} else {
|
|
551
|
+
this.getLogger("dispatcher").info(`no execution in db queued to process`);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
);
|
|
555
|
+
} catch (error) {
|
|
556
|
+
this.getLogger("dispatcher").error(`fetching execution from db failed: ${error.message}`, { error });
|
|
496
557
|
}
|
|
497
558
|
}
|
|
559
|
+
if (next) {
|
|
560
|
+
await this.process(...next);
|
|
561
|
+
}
|
|
562
|
+
this.executing = null;
|
|
563
|
+
if (next) {
|
|
564
|
+
this.getLogger("dispatcher").info(`last process finished, will do another dispatch`);
|
|
565
|
+
this.dispatch();
|
|
566
|
+
}
|
|
498
567
|
})();
|
|
499
568
|
}
|
|
569
|
+
createProcessor(execution, options = {}) {
|
|
570
|
+
return new import_Processor.default(execution, { ...options, plugin: this });
|
|
571
|
+
}
|
|
500
572
|
async process(execution, job, options = {}) {
|
|
501
573
|
var _a, _b;
|
|
502
574
|
if (execution.status === import_constants.EXECUTION_STATUS.QUEUEING) {
|
|
@@ -510,13 +582,23 @@ class PluginWorkflowServer extends import_server.Plugin {
|
|
|
510
582
|
await (job ? processor.resume(job) : processor.start());
|
|
511
583
|
logger.info(`execution (${execution.id}) finished with status: ${execution.status}`, { execution });
|
|
512
584
|
if (execution.status && ((_b = (_a = execution.workflow.options) == null ? void 0 : _a.deleteExecutionOnStatus) == null ? void 0 : _b.includes(execution.status))) {
|
|
513
|
-
await execution.destroy();
|
|
585
|
+
await execution.destroy({ transaction: processor.mainTransaction });
|
|
514
586
|
}
|
|
515
587
|
} catch (err) {
|
|
516
588
|
logger.error(`execution (${execution.id}) error: ${err.message}`, err);
|
|
517
589
|
}
|
|
518
590
|
return processor;
|
|
519
591
|
}
|
|
592
|
+
async execute(workflow, values, options = {}) {
|
|
593
|
+
const trigger = this.triggers.get(workflow.type);
|
|
594
|
+
if (!trigger) {
|
|
595
|
+
throw new Error(`trigger type "${workflow.type}" of workflow ${workflow.id} is not registered`);
|
|
596
|
+
}
|
|
597
|
+
if (!trigger.execute) {
|
|
598
|
+
throw new Error(`"execute" method of trigger ${workflow.type} is not implemented`);
|
|
599
|
+
}
|
|
600
|
+
return trigger.execute(workflow, values, options);
|
|
601
|
+
}
|
|
520
602
|
/**
|
|
521
603
|
* @experimental
|
|
522
604
|
* @param {string} dataSourceName
|
package/dist/server/Processor.js
CHANGED
|
@@ -117,11 +117,11 @@ class Processor {
|
|
|
117
117
|
execution,
|
|
118
118
|
options: { plugin }
|
|
119
119
|
} = this;
|
|
120
|
-
if (!execution.workflow) {
|
|
121
|
-
execution.workflow = plugin.enabledCache.get(execution.workflowId);
|
|
122
|
-
}
|
|
123
120
|
this.mainTransaction = plugin.useDataSourceTransaction("main", this.transaction);
|
|
124
121
|
const transaction = this.mainTransaction;
|
|
122
|
+
if (!execution.workflow) {
|
|
123
|
+
execution.workflow = plugin.enabledCache.get(execution.workflowId) || await execution.getWorkflow({ transaction });
|
|
124
|
+
}
|
|
125
125
|
const nodes = await execution.workflow.getNodes({ transaction });
|
|
126
126
|
this.makeNodes(nodes);
|
|
127
127
|
const jobs = await execution.getJobs({
|
|
@@ -11,4 +11,9 @@ export declare function update(context: Context, next: any): Promise<void>;
|
|
|
11
11
|
export declare function destroy(context: Context, next: any): Promise<void>;
|
|
12
12
|
export declare function revision(context: Context, next: any): Promise<void>;
|
|
13
13
|
export declare function sync(context: Context, next: any): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* @deprecated
|
|
16
|
+
* Keep for action trigger compatibility
|
|
17
|
+
*/
|
|
14
18
|
export declare function trigger(context: Context, next: any): Promise<any>;
|
|
19
|
+
export declare function execute(context: Context, next: any): Promise<any>;
|
|
@@ -37,6 +37,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
37
37
|
var workflows_exports = {};
|
|
38
38
|
__export(workflows_exports, {
|
|
39
39
|
destroy: () => destroy,
|
|
40
|
+
execute: () => execute,
|
|
40
41
|
revision: () => revision,
|
|
41
42
|
sync: () => sync,
|
|
42
43
|
trigger: () => trigger,
|
|
@@ -90,69 +91,13 @@ async function destroy(context, next) {
|
|
|
90
91
|
next();
|
|
91
92
|
}
|
|
92
93
|
async function revision(context, next) {
|
|
93
|
-
const plugin = context.app.getPlugin(import_Plugin.default);
|
|
94
94
|
const repository = import_actions.utils.getRepositoryFromParams(context);
|
|
95
95
|
const { filterByTk, filter = {}, values = {} } = context.action.params;
|
|
96
|
-
context.body = await
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
context,
|
|
102
|
-
transaction
|
|
103
|
-
});
|
|
104
|
-
const trigger2 = plugin.triggers.get(origin.type);
|
|
105
|
-
const revisionData = filter.key ? {
|
|
106
|
-
key: filter.key,
|
|
107
|
-
title: origin.title,
|
|
108
|
-
triggerTitle: origin.triggerTitle,
|
|
109
|
-
allExecuted: origin.allExecuted
|
|
110
|
-
} : values;
|
|
111
|
-
const instance = await repository.create({
|
|
112
|
-
values: {
|
|
113
|
-
title: `${origin.title} copy`,
|
|
114
|
-
description: origin.description,
|
|
115
|
-
...revisionData,
|
|
116
|
-
sync: origin.sync,
|
|
117
|
-
type: origin.type,
|
|
118
|
-
config: typeof trigger2.duplicateConfig === "function" ? await trigger2.duplicateConfig(origin, { transaction }) : origin.config
|
|
119
|
-
},
|
|
120
|
-
transaction
|
|
121
|
-
});
|
|
122
|
-
const originalNodesMap = /* @__PURE__ */ new Map();
|
|
123
|
-
origin.nodes.forEach((node) => {
|
|
124
|
-
originalNodesMap.set(node.id, node);
|
|
125
|
-
});
|
|
126
|
-
const oldToNew = /* @__PURE__ */ new Map();
|
|
127
|
-
const newToOld = /* @__PURE__ */ new Map();
|
|
128
|
-
for await (const node of origin.nodes) {
|
|
129
|
-
const instruction = plugin.instructions.get(node.type);
|
|
130
|
-
const newNode = await instance.createNode(
|
|
131
|
-
{
|
|
132
|
-
type: node.type,
|
|
133
|
-
key: node.key,
|
|
134
|
-
config: typeof instruction.duplicateConfig === "function" ? await instruction.duplicateConfig(node, { transaction }) : node.config,
|
|
135
|
-
title: node.title,
|
|
136
|
-
branchIndex: node.branchIndex
|
|
137
|
-
},
|
|
138
|
-
{ transaction }
|
|
139
|
-
);
|
|
140
|
-
oldToNew.set(node.id, newNode);
|
|
141
|
-
newToOld.set(newNode.id, node);
|
|
142
|
-
}
|
|
143
|
-
for await (const [oldId, newNode] of oldToNew.entries()) {
|
|
144
|
-
const oldNode = originalNodesMap.get(oldId);
|
|
145
|
-
const newUpstream = oldNode.upstreamId ? oldToNew.get(oldNode.upstreamId) : null;
|
|
146
|
-
const newDownstream = oldNode.downstreamId ? oldToNew.get(oldNode.downstreamId) : null;
|
|
147
|
-
await newNode.update(
|
|
148
|
-
{
|
|
149
|
-
upstreamId: (newUpstream == null ? void 0 : newUpstream.id) ?? null,
|
|
150
|
-
downstreamId: (newDownstream == null ? void 0 : newDownstream.id) ?? null
|
|
151
|
-
},
|
|
152
|
-
{ transaction }
|
|
153
|
-
);
|
|
154
|
-
}
|
|
155
|
-
return instance;
|
|
96
|
+
context.body = await repository.revision({
|
|
97
|
+
filterByTk,
|
|
98
|
+
filter,
|
|
99
|
+
values,
|
|
100
|
+
context
|
|
156
101
|
});
|
|
157
102
|
await next();
|
|
158
103
|
}
|
|
@@ -174,9 +119,62 @@ async function sync(context, next) {
|
|
|
174
119
|
async function trigger(context, next) {
|
|
175
120
|
return next();
|
|
176
121
|
}
|
|
122
|
+
async function execute(context, next) {
|
|
123
|
+
const plugin = context.app.pm.get(import_Plugin.default);
|
|
124
|
+
const { filterByTk, values, autoRevision } = context.action.params;
|
|
125
|
+
if (!values) {
|
|
126
|
+
return context.throw(400, "values is required");
|
|
127
|
+
}
|
|
128
|
+
if (!filterByTk) {
|
|
129
|
+
return context.throw(400, "filterByTk is required");
|
|
130
|
+
}
|
|
131
|
+
const id = Number.parseInt(filterByTk, 10);
|
|
132
|
+
if (Number.isNaN(id)) {
|
|
133
|
+
return context.throw(400, "filterByTk is invalid");
|
|
134
|
+
}
|
|
135
|
+
const repository = import_actions.utils.getRepositoryFromParams(context);
|
|
136
|
+
const workflow = plugin.enabledCache.get(id) || await repository.findOne({ filterByTk });
|
|
137
|
+
if (!workflow) {
|
|
138
|
+
return context.throw(404, "workflow not found");
|
|
139
|
+
}
|
|
140
|
+
const { executed } = workflow;
|
|
141
|
+
let processor;
|
|
142
|
+
try {
|
|
143
|
+
processor = await plugin.execute(workflow, values, { manually: true });
|
|
144
|
+
if (!processor) {
|
|
145
|
+
return context.throw(400, "workflow not triggered");
|
|
146
|
+
}
|
|
147
|
+
} catch (ex) {
|
|
148
|
+
return context.throw(400, ex.message);
|
|
149
|
+
}
|
|
150
|
+
context.action.mergeParams({
|
|
151
|
+
filter: { key: workflow.key }
|
|
152
|
+
});
|
|
153
|
+
let newVersion;
|
|
154
|
+
if (!executed && autoRevision) {
|
|
155
|
+
newVersion = await repository.revision({
|
|
156
|
+
filterByTk: workflow.id,
|
|
157
|
+
filter: { key: workflow.key },
|
|
158
|
+
values: {
|
|
159
|
+
current: workflow.current,
|
|
160
|
+
enabled: workflow.enabled
|
|
161
|
+
},
|
|
162
|
+
context
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
context.body = {
|
|
166
|
+
execution: {
|
|
167
|
+
id: processor.execution.id,
|
|
168
|
+
status: processor.execution.status
|
|
169
|
+
},
|
|
170
|
+
newVersionId: newVersion == null ? void 0 : newVersion.id
|
|
171
|
+
};
|
|
172
|
+
return next();
|
|
173
|
+
}
|
|
177
174
|
// Annotate the CommonJS export names for ESM import in node:
|
|
178
175
|
0 && (module.exports = {
|
|
179
176
|
destroy,
|
|
177
|
+
execute,
|
|
180
178
|
revision,
|
|
181
179
|
sync,
|
|
182
180
|
trigger,
|
|
@@ -34,6 +34,7 @@ function workflows_default() {
|
|
|
34
34
|
dumpRules: "required",
|
|
35
35
|
name: "workflows",
|
|
36
36
|
shared: true,
|
|
37
|
+
repository: "WorkflowRepository",
|
|
37
38
|
fields: [
|
|
38
39
|
{
|
|
39
40
|
name: "key",
|
|
@@ -90,8 +91,7 @@ function workflows_default() {
|
|
|
90
91
|
},
|
|
91
92
|
{
|
|
92
93
|
type: "boolean",
|
|
93
|
-
name: "current"
|
|
94
|
-
defaultValue: false
|
|
94
|
+
name: "current"
|
|
95
95
|
},
|
|
96
96
|
{
|
|
97
97
|
type: "boolean",
|
package/dist/server/index.d.ts
CHANGED
|
@@ -13,5 +13,5 @@ export * from './functions';
|
|
|
13
13
|
export * from './logicCalculate';
|
|
14
14
|
export { Trigger } from './triggers';
|
|
15
15
|
export { default as Processor } from './Processor';
|
|
16
|
-
export { default } from './Plugin';
|
|
16
|
+
export { default, EventOptions } from './Plugin';
|
|
17
17
|
export * from './types';
|
package/dist/server/index.js
CHANGED
|
@@ -37,6 +37,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
37
37
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
38
38
|
var server_exports = {};
|
|
39
39
|
__export(server_exports, {
|
|
40
|
+
EventOptions: () => import_Plugin.EventOptions,
|
|
40
41
|
Processor: () => import_Processor.default,
|
|
41
42
|
Trigger: () => import_triggers.Trigger,
|
|
42
43
|
default: () => import_Plugin.default
|
|
@@ -53,6 +54,7 @@ var import_Plugin = __toESM(require("./Plugin"));
|
|
|
53
54
|
__reExport(server_exports, require("./types"), module.exports);
|
|
54
55
|
// Annotate the CommonJS export names for ESM import in node:
|
|
55
56
|
0 && (module.exports = {
|
|
57
|
+
EventOptions,
|
|
56
58
|
Processor,
|
|
57
59
|
Trigger,
|
|
58
60
|
...require("./utils"),
|