@nocobase/plugin-workflow 1.4.21 → 1.4.23
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/externalVersion.js +11 -11
- package/dist/locale/zh-CN.json +5 -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 +4 -4
- package/dist/server/Plugin.js +67 -34
- package/dist/server/triggers/ScheduleTrigger/DateFieldScheduleTrigger.d.ts +1 -1
- package/dist/server/triggers/ScheduleTrigger/DateFieldScheduleTrigger.js +17 -12
- package/package.json +3 -3
package/dist/externalVersion.js
CHANGED
|
@@ -11,24 +11,24 @@ module.exports = {
|
|
|
11
11
|
"react": "18.2.0",
|
|
12
12
|
"@formily/core": "2.3.0",
|
|
13
13
|
"@formily/react": "2.3.0",
|
|
14
|
-
"@nocobase/client": "1.4.
|
|
15
|
-
"@nocobase/utils": "1.4.
|
|
14
|
+
"@nocobase/client": "1.4.23",
|
|
15
|
+
"@nocobase/utils": "1.4.23",
|
|
16
16
|
"antd": "5.12.8",
|
|
17
17
|
"@ant-design/icons": "5.2.6",
|
|
18
18
|
"react-router-dom": "6.21.0",
|
|
19
19
|
"react-i18next": "11.18.6",
|
|
20
20
|
"@formily/shared": "2.3.2",
|
|
21
21
|
"lodash": "4.17.21",
|
|
22
|
-
"
|
|
23
|
-
"@nocobase/
|
|
24
|
-
"@nocobase/
|
|
25
|
-
"@nocobase/
|
|
22
|
+
"sequelize": "6.35.2",
|
|
23
|
+
"@nocobase/database": "1.4.23",
|
|
24
|
+
"@nocobase/server": "1.4.23",
|
|
25
|
+
"@nocobase/logger": "1.4.23",
|
|
26
|
+
"@nocobase/evaluators": "1.4.23",
|
|
26
27
|
"@formily/antd-v5": "1.1.9",
|
|
27
28
|
"@formily/reactive": "2.3.0",
|
|
28
|
-
"@nocobase/actions": "1.4.
|
|
29
|
+
"@nocobase/actions": "1.4.23",
|
|
29
30
|
"dayjs": "1.11.10",
|
|
30
|
-
"@nocobase/data-source-manager": "1.4.
|
|
31
|
-
"
|
|
32
|
-
"@nocobase/
|
|
33
|
-
"@nocobase/test": "1.4.21"
|
|
31
|
+
"@nocobase/data-source-manager": "1.4.23",
|
|
32
|
+
"@nocobase/plugin-workflow-test": "1.4.23",
|
|
33
|
+
"@nocobase/test": "1.4.23"
|
|
34
34
|
};
|
package/dist/locale/zh-CN.json
CHANGED
|
@@ -143,19 +143,19 @@
|
|
|
143
143
|
"Node type": "节点类型",
|
|
144
144
|
"Unknown node": "未知节点",
|
|
145
145
|
"Node with unknown type will cause error. Please delete it or check plugin which provide this type.": "未知类型的节点会导致错误,请删除或检查提供该类型的插件。",
|
|
146
|
-
"Calculation": "
|
|
147
|
-
"Calculation engine": "
|
|
146
|
+
"Calculation": "计算",
|
|
147
|
+
"Calculation engine": "计算引擎",
|
|
148
148
|
"Basic": "基础",
|
|
149
|
-
"Calculation expression": "
|
|
149
|
+
"Calculation expression": "计算表达式",
|
|
150
150
|
"Expression syntax error": "表达式语法错误",
|
|
151
151
|
"Syntax references: ": "语法参考:",
|
|
152
|
-
"Calculation result": "
|
|
152
|
+
"Calculation result": "计算结果",
|
|
153
153
|
"True": "真",
|
|
154
154
|
"False": "假",
|
|
155
155
|
"concat": "连接",
|
|
156
156
|
"Condition": "条件判断",
|
|
157
157
|
"Based on boolean result of the calculation to determine whether to \"continue\" or \"exit\" the process, or continue on different branches of \"yes\" and \"no\".":
|
|
158
|
-
"
|
|
158
|
+
"基于计算结果的真假来决定“继续”或“退出”流程,或者在“是”与“否”的分支上分别继续。",
|
|
159
159
|
"Mode": "模式",
|
|
160
160
|
"Continue when \"Yes\"": "“是”则继续",
|
|
161
161
|
"Branch into \"Yes\" and \"No\"": "“是”和“否”分别继续",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"cron-parser","version":"4.4.0","description":"Node.js library for parsing crontab instructions","main":"lib/parser.js","types":"index.d.ts","typesVersions":{"<4.1":{"*":["types/ts3/*"]}},"directories":{"test":"test"},"scripts":{"test:tsd":"tsd","test:unit":"TZ=UTC tap ./test/*.js","test:cover":"TZ=UTC tap --coverage-report=html ./test/*.js","lint":"eslint .","lint:fix":"eslint --fix .","test":"npm run lint && npm run test:unit && npm run test:tsd"},"repository":{"type":"git","url":"https://github.com/harrisiirak/cron-parser.git"},"keywords":["cron","crontab","parser"],"author":"Harri Siirak","contributors":["Nicholas Clawson","Daniel Prentis <daniel@salsitasoft.com>","Renault John Lecoultre","Richard Astbury <richard.astbury@gmail.com>","Meaglin Wasabi <Meaglin.wasabi@gmail.com>","Mike Kusold <hello@mikekusold.com>","Alex Kit <alex.kit@atmajs.com>","Santiago Gimeno <santiago.gimeno@gmail.com>","Daniel <darc.tec@gmail.com>","Christian Steininger <christian.steininger.cs@gmail.com>","Mykola Piskovyi <m.piskovyi@gmail.com>","Brian Vaughn <brian.david.vaughn@gmail.com>","Nicholas Clawson <nickclaw@gmail.com>","Yasuhiroki <yasuhiroki.duck@gmail.com>","Nicholas Clawson <nickclaw@gmail.com>","Brendan Warkentin <faazshift@gmail.com>","Charlie Fish <fishcharlie.code@gmail.com>","Ian Graves <ian+diskimage@iangrav.es>","Andy Thompson <me@andytson.com>","Regev Brody <regevbr@gmail.com>"],"license":"MIT","dependencies":{"luxon":"^1.28.0"},"devDependencies":{"eslint":"^8.2.0","sinon":"^10.0.0","tap":"^16.0.1","tsd":"^0.19.0"},"engines":{"node":">=0.8"},"browser":{"fs":false},"tap":{"check-coverage":false},"tsd":{"directory":"test","compilerOptions":{"lib":["es2017","dom"]}},"_lastModified":"2025-01-
|
|
1
|
+
{"name":"cron-parser","version":"4.4.0","description":"Node.js library for parsing crontab instructions","main":"lib/parser.js","types":"index.d.ts","typesVersions":{"<4.1":{"*":["types/ts3/*"]}},"directories":{"test":"test"},"scripts":{"test:tsd":"tsd","test:unit":"TZ=UTC tap ./test/*.js","test:cover":"TZ=UTC tap --coverage-report=html ./test/*.js","lint":"eslint .","lint:fix":"eslint --fix .","test":"npm run lint && npm run test:unit && npm run test:tsd"},"repository":{"type":"git","url":"https://github.com/harrisiirak/cron-parser.git"},"keywords":["cron","crontab","parser"],"author":"Harri Siirak","contributors":["Nicholas Clawson","Daniel Prentis <daniel@salsitasoft.com>","Renault John Lecoultre","Richard Astbury <richard.astbury@gmail.com>","Meaglin Wasabi <Meaglin.wasabi@gmail.com>","Mike Kusold <hello@mikekusold.com>","Alex Kit <alex.kit@atmajs.com>","Santiago Gimeno <santiago.gimeno@gmail.com>","Daniel <darc.tec@gmail.com>","Christian Steininger <christian.steininger.cs@gmail.com>","Mykola Piskovyi <m.piskovyi@gmail.com>","Brian Vaughn <brian.david.vaughn@gmail.com>","Nicholas Clawson <nickclaw@gmail.com>","Yasuhiroki <yasuhiroki.duck@gmail.com>","Nicholas Clawson <nickclaw@gmail.com>","Brendan Warkentin <faazshift@gmail.com>","Charlie Fish <fishcharlie.code@gmail.com>","Ian Graves <ian+diskimage@iangrav.es>","Andy Thompson <me@andytson.com>","Regev Brody <regevbr@gmail.com>"],"license":"MIT","dependencies":{"luxon":"^1.28.0"},"devDependencies":{"eslint":"^8.2.0","sinon":"^10.0.0","tap":"^16.0.1","tsd":"^0.19.0"},"engines":{"node":">=0.8"},"browser":{"fs":false},"tap":{"check-coverage":false},"tsd":{"directory":"test","compilerOptions":{"lib":["es2017","dom"]}},"_lastModified":"2025-01-13T09:44:19.065Z"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"lru-cache","description":"A cache object that deletes the least-recently-used items.","version":"8.0.5","author":"Isaac Z. Schlueter <i@izs.me>","keywords":["mru","lru","cache"],"sideEffects":false,"scripts":{"build":"npm run prepare","preprepare":"rm -rf dist","prepare":"tsc -p tsconfig.json && tsc -p tsconfig-esm.json","postprepare":"bash fixup.sh","pretest":"npm run prepare","presnap":"npm run prepare","test":"c8 tap","snap":"c8 tap","preversion":"npm test","postversion":"npm publish","prepublishOnly":"git push origin --follow-tags","format":"prettier --write .","typedoc":"typedoc --tsconfig tsconfig-esm.json ./src/*.ts","benchmark-results-typedoc":"bash scripts/benchmark-results-typedoc.sh","prebenchmark":"npm run prepare","benchmark":"make -C benchmark","preprofile":"npm run prepare","profile":"make -C benchmark profile"},"main":"./dist/cjs/index-cjs.js","module":"./dist/mjs/index.js","types":"./dist/mjs/index.d.ts","exports":{"./min":{"import":{"types":"./dist/mjs/index.d.ts","default":"./dist/mjs/index.min.js"},"require":{"types":"./dist/cjs/index.d.ts","default":"./dist/cjs/index.min.js"}},".":{"import":{"types":"./dist/mjs/index.d.ts","default":"./dist/mjs/index.js"},"require":{"types":"./dist/cjs/index.d.ts","default":"./dist/cjs/index-cjs.js"}}},"repository":"git://github.com/isaacs/node-lru-cache.git","devDependencies":{"@size-limit/preset-small-lib":"^7.0.8","@types/node":"^17.0.31","@types/tap":"^15.0.6","benchmark":"^2.1.4","c8":"^7.11.2","clock-mock":"^1.0.6","esbuild":"^0.17.11","eslint-config-prettier":"^8.5.0","marked":"^4.2.12","mkdirp":"^2.1.5","prettier":"^2.6.2","size-limit":"^7.0.8","tap":"^16.3.4","ts-node":"^10.7.0","tslib":"^2.4.0","typedoc":"^0.23.24","typescript":"^4.6.4"},"license":"ISC","files":["dist"],"engines":{"node":">=16.14"},"prettier":{"semi":false,"printWidth":70,"tabWidth":2,"useTabs":false,"singleQuote":true,"jsxSingleQuote":false,"bracketSameLine":true,"arrowParens":"avoid","endOfLine":"lf"},"tap":{"coverage":false,"node-arg":["--expose-gc","--no-warnings","--loader","ts-node/esm"],"ts":false},"size-limit":[{"path":"./dist/mjs/index.js"}],"_lastModified":"2025-01-
|
|
1
|
+
{"name":"lru-cache","description":"A cache object that deletes the least-recently-used items.","version":"8.0.5","author":"Isaac Z. Schlueter <i@izs.me>","keywords":["mru","lru","cache"],"sideEffects":false,"scripts":{"build":"npm run prepare","preprepare":"rm -rf dist","prepare":"tsc -p tsconfig.json && tsc -p tsconfig-esm.json","postprepare":"bash fixup.sh","pretest":"npm run prepare","presnap":"npm run prepare","test":"c8 tap","snap":"c8 tap","preversion":"npm test","postversion":"npm publish","prepublishOnly":"git push origin --follow-tags","format":"prettier --write .","typedoc":"typedoc --tsconfig tsconfig-esm.json ./src/*.ts","benchmark-results-typedoc":"bash scripts/benchmark-results-typedoc.sh","prebenchmark":"npm run prepare","benchmark":"make -C benchmark","preprofile":"npm run prepare","profile":"make -C benchmark profile"},"main":"./dist/cjs/index-cjs.js","module":"./dist/mjs/index.js","types":"./dist/mjs/index.d.ts","exports":{"./min":{"import":{"types":"./dist/mjs/index.d.ts","default":"./dist/mjs/index.min.js"},"require":{"types":"./dist/cjs/index.d.ts","default":"./dist/cjs/index.min.js"}},".":{"import":{"types":"./dist/mjs/index.d.ts","default":"./dist/mjs/index.js"},"require":{"types":"./dist/cjs/index.d.ts","default":"./dist/cjs/index-cjs.js"}}},"repository":"git://github.com/isaacs/node-lru-cache.git","devDependencies":{"@size-limit/preset-small-lib":"^7.0.8","@types/node":"^17.0.31","@types/tap":"^15.0.6","benchmark":"^2.1.4","c8":"^7.11.2","clock-mock":"^1.0.6","esbuild":"^0.17.11","eslint-config-prettier":"^8.5.0","marked":"^4.2.12","mkdirp":"^2.1.5","prettier":"^2.6.2","size-limit":"^7.0.8","tap":"^16.3.4","ts-node":"^10.7.0","tslib":"^2.4.0","typedoc":"^0.23.24","typescript":"^4.6.4"},"license":"ISC","files":["dist"],"engines":{"node":">=16.14"},"prettier":{"semi":false,"printWidth":70,"tabWidth":2,"useTabs":false,"singleQuote":true,"jsxSingleQuote":false,"bracketSameLine":true,"arrowParens":"avoid","endOfLine":"lf"},"tap":{"coverage":false,"node-arg":["--expose-gc","--no-warnings","--loader","ts-node/esm"],"ts":false},"size-limit":[{"path":"./dist/mjs/index.js"}],"_lastModified":"2025-01-13T09:44:18.714Z"}
|
package/dist/server/Plugin.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
|
-
import { Transactionable } from '
|
|
9
|
+
import { Transactionable } from 'sequelize';
|
|
10
10
|
import { Plugin } from '@nocobase/server';
|
|
11
11
|
import { Registry } from '@nocobase/utils';
|
|
12
12
|
import { Logger } from '@nocobase/logger';
|
|
@@ -40,7 +40,7 @@ export default class PluginWorkflowServer extends Plugin {
|
|
|
40
40
|
/**
|
|
41
41
|
* @experimental
|
|
42
42
|
*/
|
|
43
|
-
getLogger(workflowId
|
|
43
|
+
getLogger(workflowId?: ID): Logger;
|
|
44
44
|
/**
|
|
45
45
|
* @experimental
|
|
46
46
|
* @param {WorkflowModel} workflow
|
|
@@ -67,11 +67,11 @@ export default class PluginWorkflowServer extends Plugin {
|
|
|
67
67
|
* Start a deferred execution
|
|
68
68
|
* @experimental
|
|
69
69
|
*/
|
|
70
|
-
start(execution: ExecutionModel): void
|
|
71
|
-
createProcessor(execution: ExecutionModel, options?: {}): Processor;
|
|
70
|
+
start(execution: ExecutionModel): Promise<void>;
|
|
72
71
|
private createExecution;
|
|
73
72
|
private prepare;
|
|
74
73
|
private dispatch;
|
|
74
|
+
createProcessor(execution: ExecutionModel, options?: {}): Processor;
|
|
75
75
|
private process;
|
|
76
76
|
/**
|
|
77
77
|
* @experimental
|
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");
|
|
@@ -137,7 +138,7 @@ class PluginWorkflowServer extends import_server.Plugin {
|
|
|
137
138
|
/**
|
|
138
139
|
* @experimental
|
|
139
140
|
*/
|
|
140
|
-
getLogger(workflowId) {
|
|
141
|
+
getLogger(workflowId = "dispatcher") {
|
|
141
142
|
const now = /* @__PURE__ */ new Date();
|
|
142
143
|
const date = `${now.getFullYear()}-${`0${now.getMonth() + 1}`.slice(-2)}-${`0${now.getDate()}`.slice(-2)}`;
|
|
143
144
|
const key = `${date}-${workflowId}}`;
|
|
@@ -256,7 +257,6 @@ class PluginWorkflowServer extends import_server.Plugin {
|
|
|
256
257
|
db.on("workflows.afterUpdate", (model) => this.toggle(model));
|
|
257
258
|
db.on("workflows.beforeDestroy", (model) => this.toggle(model, false));
|
|
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({
|
|
@@ -266,8 +266,10 @@ class PluginWorkflowServer extends import_server.Plugin {
|
|
|
266
266
|
this.toggle(workflow);
|
|
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.getLogger("dispatcher").info("(starting) check for queueing executions");
|
|
271
273
|
this.dispatch();
|
|
272
274
|
});
|
|
273
275
|
this.app.on("beforeStop", async () => {
|
|
@@ -320,6 +322,15 @@ class PluginWorkflowServer extends import_server.Plugin {
|
|
|
320
322
|
logger.debug(`ignored event data:`, context);
|
|
321
323
|
return;
|
|
322
324
|
}
|
|
325
|
+
const duplicated = this.events.find(([w, c, { eventKey }]) => {
|
|
326
|
+
if (eventKey && options.eventKey) {
|
|
327
|
+
return eventKey === options.eventKey;
|
|
328
|
+
}
|
|
329
|
+
});
|
|
330
|
+
if (duplicated) {
|
|
331
|
+
logger.warn(`event of workflow ${workflow.id} is duplicated (${options.eventKey}), event will be ignored`);
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
323
334
|
if (context == null) {
|
|
324
335
|
logger.warn(`workflow ${workflow.id} event data context is null, event will be ignored`);
|
|
325
336
|
return;
|
|
@@ -333,6 +344,7 @@ class PluginWorkflowServer extends import_server.Plugin {
|
|
|
333
344
|
logger.info(`new event triggered, now events: ${this.events.length}`);
|
|
334
345
|
logger.debug(`event data:`, { context });
|
|
335
346
|
if (this.events.length > 1) {
|
|
347
|
+
logger.info(`new event is pending to be prepared after previous preparation is finished`);
|
|
336
348
|
return;
|
|
337
349
|
}
|
|
338
350
|
setTimeout(this.prepare);
|
|
@@ -360,22 +372,25 @@ class PluginWorkflowServer extends import_server.Plugin {
|
|
|
360
372
|
`execution (${job.execution.id}) resuming from job (${job.id}) added to pending list`
|
|
361
373
|
);
|
|
362
374
|
this.pending.push([job.execution, job]);
|
|
375
|
+
if (this.executing) {
|
|
376
|
+
await this.executing;
|
|
377
|
+
}
|
|
363
378
|
this.dispatch();
|
|
364
379
|
}
|
|
365
380
|
/**
|
|
366
381
|
* Start a deferred execution
|
|
367
382
|
* @experimental
|
|
368
383
|
*/
|
|
369
|
-
start(execution) {
|
|
384
|
+
async start(execution) {
|
|
370
385
|
if (execution.status !== import_constants.EXECUTION_STATUS.STARTED) {
|
|
371
386
|
return;
|
|
372
387
|
}
|
|
373
388
|
this.pending.push([execution]);
|
|
389
|
+
if (this.executing) {
|
|
390
|
+
await this.executing;
|
|
391
|
+
}
|
|
374
392
|
this.dispatch();
|
|
375
393
|
}
|
|
376
|
-
createProcessor(execution, options = {}) {
|
|
377
|
-
return new import_Processor.default(execution, { ...options, plugin: this });
|
|
378
|
-
}
|
|
379
394
|
async createExecution(workflow, context, options) {
|
|
380
395
|
const { deferred } = options;
|
|
381
396
|
const transaction = await this.useDataSourceTransaction("main", options.transaction, true);
|
|
@@ -434,7 +449,7 @@ class PluginWorkflowServer extends import_server.Plugin {
|
|
|
434
449
|
const event = this.events.shift();
|
|
435
450
|
this.eventsCount = this.events.length;
|
|
436
451
|
if (!event) {
|
|
437
|
-
this.getLogger("dispatcher").
|
|
452
|
+
this.getLogger("dispatcher").info(`events queue is empty, no need to prepare`);
|
|
438
453
|
return;
|
|
439
454
|
}
|
|
440
455
|
const logger = this.getLogger(event[0].id);
|
|
@@ -467,38 +482,56 @@ class PluginWorkflowServer extends import_server.Plugin {
|
|
|
467
482
|
}
|
|
468
483
|
this.executing = (async () => {
|
|
469
484
|
let next = null;
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
"workflow.enabled": true,
|
|
479
|
-
"workflow.id": {
|
|
480
|
-
[import_database.Op.not]: null
|
|
481
|
-
}
|
|
485
|
+
if (this.pending.length) {
|
|
486
|
+
next = this.pending.shift();
|
|
487
|
+
this.getLogger(next[0].workflowId).info(`pending execution (${next[0].id}) ready to process`);
|
|
488
|
+
} else {
|
|
489
|
+
try {
|
|
490
|
+
await this.db.sequelize.transaction(
|
|
491
|
+
{
|
|
492
|
+
isolationLevel: this.db.options.dialect === "sqlite" ? [][0] : import_sequelize.Transaction.ISOLATION_LEVELS.REPEATABLE_READ
|
|
482
493
|
},
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
494
|
+
async (transaction) => {
|
|
495
|
+
const execution = await this.db.getRepository("executions").findOne({
|
|
496
|
+
filter: {
|
|
497
|
+
status: import_constants.EXECUTION_STATUS.QUEUEING,
|
|
498
|
+
"workflow.enabled": true
|
|
499
|
+
},
|
|
500
|
+
sort: "id",
|
|
501
|
+
transaction
|
|
502
|
+
});
|
|
503
|
+
if (execution) {
|
|
504
|
+
this.getLogger(execution.workflowId).info(`execution (${execution.id}) fetched from db`);
|
|
505
|
+
await execution.update(
|
|
506
|
+
{
|
|
507
|
+
status: import_constants.EXECUTION_STATUS.STARTED
|
|
508
|
+
},
|
|
509
|
+
{ transaction }
|
|
510
|
+
);
|
|
511
|
+
execution.workflow = this.enabledCache.get(execution.workflowId);
|
|
512
|
+
next = [execution];
|
|
513
|
+
} else {
|
|
514
|
+
this.getLogger("dispatcher").info(`no execution in db queued to process`);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
);
|
|
518
|
+
} catch (error) {
|
|
519
|
+
this.getLogger("dispatcher").error(`fetching execution from db failed: ${error.message}`, { error });
|
|
498
520
|
}
|
|
499
521
|
}
|
|
522
|
+
if (next) {
|
|
523
|
+
await this.process(...next);
|
|
524
|
+
}
|
|
525
|
+
this.executing = null;
|
|
526
|
+
if (next) {
|
|
527
|
+
this.getLogger("dispatcher").info(`last process finished, will do another dispatch`);
|
|
528
|
+
this.dispatch();
|
|
529
|
+
}
|
|
500
530
|
})();
|
|
501
531
|
}
|
|
532
|
+
createProcessor(execution, options = {}) {
|
|
533
|
+
return new import_Processor.default(execution, { ...options, plugin: this });
|
|
534
|
+
}
|
|
502
535
|
async process(execution, job, options = {}) {
|
|
503
536
|
var _a, _b;
|
|
504
537
|
if (execution.status === import_constants.EXECUTION_STATUS.QUEUEING) {
|
|
@@ -30,7 +30,7 @@ export default class ScheduleTrigger {
|
|
|
30
30
|
constructor(workflow: Plugin);
|
|
31
31
|
reload(): Promise<void>;
|
|
32
32
|
inspect(workflows: WorkflowModel[]): void;
|
|
33
|
-
loadRecordsToSchedule({ config: { collection, limit, startsOn, repeat, endsOn }, allExecuted }: WorkflowModel, currentDate: Date): Promise<import("@nocobase/database").Model<any, any>[]>;
|
|
33
|
+
loadRecordsToSchedule({ id, config: { collection, limit, startsOn, repeat, endsOn }, allExecuted }: WorkflowModel, currentDate: Date): Promise<import("@nocobase/database").Model<any, any>[]>;
|
|
34
34
|
getRecordNextTime(workflow: WorkflowModel, record: any, nextSecond?: boolean): any;
|
|
35
35
|
schedule(workflow: WorkflowModel, record: any, nextTime: any, toggle?: boolean, options?: {}): Promise<void>;
|
|
36
36
|
trigger(workflow: WorkflowModel, record: any, nextTime: any, { transaction }?: Transactionable): Promise<void>;
|
|
@@ -131,6 +131,7 @@ class ScheduleTrigger {
|
|
|
131
131
|
const now = /* @__PURE__ */ new Date();
|
|
132
132
|
workflows.forEach(async (workflow) => {
|
|
133
133
|
const records = await this.loadRecordsToSchedule(workflow, now);
|
|
134
|
+
this.workflow.getLogger(workflow.id).info(`[Schedule on date field] ${records.length} records to schedule`);
|
|
134
135
|
records.forEach((record) => {
|
|
135
136
|
const nextTime = this.getRecordNextTime(workflow, record);
|
|
136
137
|
this.schedule(workflow, record, nextTime, Boolean(nextTime));
|
|
@@ -144,17 +145,20 @@ class ScheduleTrigger {
|
|
|
144
145
|
// b. repeat in range (number or cron):
|
|
145
146
|
// i. endsOn after now -> yes
|
|
146
147
|
// ii. endsOn before now -> no
|
|
147
|
-
async loadRecordsToSchedule({ config: { collection, limit, startsOn, repeat, endsOn }, allExecuted }, currentDate) {
|
|
148
|
+
async loadRecordsToSchedule({ id, config: { collection, limit, startsOn, repeat, endsOn }, allExecuted }, currentDate) {
|
|
148
149
|
const { dataSourceManager } = this.workflow.app;
|
|
149
150
|
if (limit && allExecuted >= limit) {
|
|
151
|
+
this.workflow.getLogger(id).warn(`[Schedule on date field] limit reached (all executed ${allExecuted})`);
|
|
150
152
|
return [];
|
|
151
153
|
}
|
|
152
154
|
if (!startsOn) {
|
|
155
|
+
this.workflow.getLogger(id).warn(`[Schedule on date field] "startsOn" is not configured`);
|
|
153
156
|
return [];
|
|
154
157
|
}
|
|
155
158
|
const timestamp = currentDate.getTime();
|
|
156
159
|
const startTimestamp = getOnTimestampWithOffset(startsOn, currentDate);
|
|
157
160
|
if (!startTimestamp) {
|
|
161
|
+
this.workflow.getLogger(id).warn(`[Schedule on date field] "startsOn.field" is not configured`);
|
|
158
162
|
return [];
|
|
159
163
|
}
|
|
160
164
|
const [dataSourceName, collectionName] = (0, import_data_source_manager.parseCollectionName)(collection);
|
|
@@ -193,21 +197,21 @@ class ScheduleTrigger {
|
|
|
193
197
|
}
|
|
194
198
|
}
|
|
195
199
|
if (endsOn) {
|
|
196
|
-
const now = /* @__PURE__ */ new Date();
|
|
197
|
-
const endTimestamp = getOnTimestampWithOffset(endsOn, now);
|
|
198
|
-
if (!endTimestamp) {
|
|
199
|
-
return [];
|
|
200
|
-
}
|
|
201
200
|
if (typeof endsOn === "string") {
|
|
202
|
-
if (
|
|
201
|
+
if ((0, import_utils.parseDateWithoutMs)(endsOn) <= timestamp) {
|
|
203
202
|
return [];
|
|
204
203
|
}
|
|
205
204
|
} else {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
205
|
+
const endTimestamp = getOnTimestampWithOffset(endsOn, currentDate);
|
|
206
|
+
if (endTimestamp) {
|
|
207
|
+
conditions.push({
|
|
208
|
+
[endsOn.field]: {
|
|
209
|
+
[import_database.Op.gte]: new Date(endTimestamp)
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
} else {
|
|
213
|
+
this.workflow.getLogger(id).warn(`[Schedule on date field] "endsOn.field" is not configured`);
|
|
214
|
+
}
|
|
211
215
|
}
|
|
212
216
|
}
|
|
213
217
|
} else {
|
|
@@ -217,6 +221,7 @@ class ScheduleTrigger {
|
|
|
217
221
|
}
|
|
218
222
|
});
|
|
219
223
|
}
|
|
224
|
+
this.workflow.getLogger(id).debug(`[Schedule on date field] conditions: `, { conditions });
|
|
220
225
|
return model.findAll({
|
|
221
226
|
where: {
|
|
222
227
|
[import_database.Op.and]: conditions
|
package/package.json
CHANGED
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
"displayName.zh-CN": "工作流",
|
|
5
5
|
"description": "A powerful BPM tool that provides foundational support for business automation, with the capability to extend unlimited triggers and nodes.",
|
|
6
6
|
"description.zh-CN": "一个强大的 BPM 工具,为业务自动化提供基础支持,并且可任意扩展更多的触发器和节点。",
|
|
7
|
-
"version": "1.4.
|
|
7
|
+
"version": "1.4.23",
|
|
8
8
|
"license": "AGPL-3.0",
|
|
9
9
|
"main": "./dist/server/index.js",
|
|
10
10
|
"homepage": "https://docs.nocobase.com/handbook/workflow",
|
|
11
11
|
"homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/workflow",
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@nocobase/plugin-workflow-test": "1.4.
|
|
13
|
+
"@nocobase/plugin-workflow-test": "1.4.23"
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
16
16
|
"@ant-design/icons": "5.x",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"@nocobase/test": "1.x",
|
|
45
45
|
"@nocobase/utils": "1.x"
|
|
46
46
|
},
|
|
47
|
-
"gitHead": "
|
|
47
|
+
"gitHead": "1e87e75a9c3b1efb0426b0690589f988a6d4aedc",
|
|
48
48
|
"keywords": [
|
|
49
49
|
"Workflow"
|
|
50
50
|
]
|