@nocobase/plugin-workflow 1.6.0-alpha.12 → 1.6.0-alpha.13

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.
@@ -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.6.0-alpha.12",
15
- "@nocobase/utils": "1.6.0-alpha.12",
14
+ "@nocobase/client": "1.6.0-alpha.13",
15
+ "@nocobase/utils": "1.6.0-alpha.13",
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
- "@nocobase/database": "1.6.0-alpha.12",
23
- "@nocobase/server": "1.6.0-alpha.12",
24
- "@nocobase/logger": "1.6.0-alpha.12",
25
- "@nocobase/actions": "1.6.0-alpha.12",
26
- "@nocobase/data-source-manager": "1.6.0-alpha.12",
27
- "@nocobase/evaluators": "1.6.0-alpha.12",
22
+ "sequelize": "6.35.2",
23
+ "@nocobase/database": "1.6.0-alpha.13",
24
+ "@nocobase/server": "1.6.0-alpha.13",
25
+ "@nocobase/logger": "1.6.0-alpha.13",
26
+ "@nocobase/actions": "1.6.0-alpha.13",
27
+ "@nocobase/data-source-manager": "1.6.0-alpha.13",
28
+ "@nocobase/evaluators": "1.6.0-alpha.13",
28
29
  "@formily/antd-v5": "1.1.9",
29
30
  "@formily/reactive": "2.3.0",
30
31
  "dayjs": "1.11.10",
31
- "sequelize": "6.35.2",
32
- "@nocobase/plugin-workflow-test": "1.6.0-alpha.12",
33
- "@nocobase/test": "1.6.0-alpha.12"
32
+ "@nocobase/plugin-workflow-test": "1.6.0-alpha.13",
33
+ "@nocobase/test": "1.6.0-alpha.13"
34
34
  };
@@ -157,19 +157,19 @@
157
157
  "Node type": "节点类型",
158
158
  "Unknown node": "未知节点",
159
159
  "Node with unknown type will cause error. Please delete it or check plugin which provide this type.": "未知类型的节点会导致错误,请删除或检查提供该类型的插件。",
160
- "Calculation": "运算",
161
- "Calculation engine": "运算引擎",
160
+ "Calculation": "计算",
161
+ "Calculation engine": "计算引擎",
162
162
  "Basic": "基础",
163
- "Calculation expression": "运算表达式",
163
+ "Calculation expression": "计算表达式",
164
164
  "Expression syntax error": "表达式语法错误",
165
165
  "Syntax references: ": "语法参考:",
166
- "Calculation result": "运算结果",
166
+ "Calculation result": "计算结果",
167
167
  "True": "真",
168
168
  "False": "假",
169
169
  "concat": "连接",
170
170
  "Condition": "条件判断",
171
171
  "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\".":
172
- "基于运算结果的真假来决定“继续”或“退出”流程,或者在“是”与“否”的分支上分别继续。",
172
+ "基于计算结果的真假来决定“继续”或“退出”流程,或者在“是”与“否”的分支上分别继续。",
173
173
  "Mode": "模式",
174
174
  "Continue when \"Yes\"": "“是”则继续",
175
175
  "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-10T04:06:28.074Z"}
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-14T06:07:36.440Z"}
@@ -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-10T04:06:27.695Z"}
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-14T06:07:36.050Z"}
@@ -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 '@nocobase/database';
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';
@@ -44,7 +44,7 @@ export default class PluginWorkflowServer extends Plugin {
44
44
  /**
45
45
  * @experimental
46
46
  */
47
- getLogger(workflowId: ID): Logger;
47
+ getLogger(workflowId?: ID): Logger;
48
48
  /**
49
49
  * @experimental
50
50
  * @param {WorkflowModel} workflow
@@ -72,12 +72,12 @@ export default class PluginWorkflowServer extends Plugin {
72
72
  * Start a deferred execution
73
73
  * @experimental
74
74
  */
75
- start(execution: ExecutionModel): void;
76
- createProcessor(execution: ExecutionModel, options?: {}): Processor;
75
+ start(execution: ExecutionModel): Promise<void>;
77
76
  private validateEvent;
78
77
  private createExecution;
79
78
  private prepare;
80
79
  private dispatch;
80
+ createProcessor(execution: ExecutionModel, options?: {}): Processor;
81
81
  private process;
82
82
  execute(workflow: WorkflowModel, values: any, options?: EventOptions): Promise<void | Processor>;
83
83
  /**
@@ -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");
@@ -126,7 +127,7 @@ class PluginWorkflowServer extends import_server.Plugin {
126
127
  /**
127
128
  * @experimental
128
129
  */
129
- getLogger(workflowId) {
130
+ getLogger(workflowId = "dispatcher") {
130
131
  const now = /* @__PURE__ */ new Date();
131
132
  const date = `${now.getFullYear()}-${`0${now.getMonth() + 1}`.slice(-2)}-${`0${now.getDate()}`.slice(-2)}`;
132
133
  const key = `${date}-${workflowId}}`;
@@ -256,7 +257,6 @@ class PluginWorkflowServer extends import_server.Plugin {
256
257
  (model, { transaction }) => this.toggle(model, false, { transaction })
257
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({
@@ -266,12 +266,14 @@ class PluginWorkflowServer extends import_server.Plugin {
266
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);
271
272
  this.app.on("workflow:dispatch", () => {
272
273
  this.app.logger.info("workflow:dispatch");
273
274
  this.dispatch();
274
275
  });
276
+ this.getLogger("dispatcher").info("(starting) check for queueing executions");
275
277
  this.dispatch();
276
278
  });
277
279
  this.app.on("beforeStop", async () => {
@@ -331,6 +333,15 @@ class PluginWorkflowServer extends import_server.Plugin {
331
333
  logger.warn(`workflow ${workflow.id} is not enabled, event will be ignored`);
332
334
  return;
333
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
+ }
334
345
  if (context == null) {
335
346
  logger.warn(`workflow ${workflow.id} event data context is null, event will be ignored`);
336
347
  return;
@@ -344,6 +355,7 @@ class PluginWorkflowServer extends import_server.Plugin {
344
355
  logger.info(`new event triggered, now events: ${this.events.length}`);
345
356
  logger.debug(`event data:`, { context });
346
357
  if (this.events.length > 1) {
358
+ logger.info(`new event is pending to be prepared after previous preparation is finished`);
347
359
  return;
348
360
  }
349
361
  setTimeout(this.prepare);
@@ -371,22 +383,25 @@ class PluginWorkflowServer extends import_server.Plugin {
371
383
  `execution (${job.execution.id}) resuming from job (${job.id}) added to pending list`
372
384
  );
373
385
  this.pending.push([job.execution, job]);
386
+ if (this.executing) {
387
+ await this.executing;
388
+ }
374
389
  this.dispatch();
375
390
  }
376
391
  /**
377
392
  * Start a deferred execution
378
393
  * @experimental
379
394
  */
380
- start(execution) {
395
+ async start(execution) {
381
396
  if (execution.status !== import_constants.EXECUTION_STATUS.STARTED) {
382
397
  return;
383
398
  }
384
399
  this.pending.push([execution]);
400
+ if (this.executing) {
401
+ await this.executing;
402
+ }
385
403
  this.dispatch();
386
404
  }
387
- createProcessor(execution, options = {}) {
388
- return new import_Processor.default(execution, { ...options, plugin: this });
389
- }
390
405
  async validateEvent(workflow, context, options) {
391
406
  const trigger = this.triggers.get(workflow.type);
392
407
  const triggerValid = await trigger.validateEvent(workflow, context, options);
@@ -471,7 +486,7 @@ class PluginWorkflowServer extends import_server.Plugin {
471
486
  const event = this.events.shift();
472
487
  this.eventsCount = this.events.length;
473
488
  if (!event) {
474
- this.getLogger("dispatcher").warn(`events queue is empty, no need to prepare`);
489
+ this.getLogger("dispatcher").info(`events queue is empty, no need to prepare`);
475
490
  return;
476
491
  }
477
492
  const logger = this.getLogger(event[0].id);
@@ -504,41 +519,56 @@ class PluginWorkflowServer extends import_server.Plugin {
504
519
  }
505
520
  this.executing = (async () => {
506
521
  let next = null;
507
- try {
508
- if (this.pending.length) {
509
- next = this.pending.shift();
510
- this.getLogger(next[0].workflowId).info(`pending execution (${next[0].id}) ready to process`);
511
- } else {
512
- const execution = await this.db.getRepository("executions").findOne({
513
- filter: {
514
- status: import_constants.EXECUTION_STATUS.QUEUEING,
515
- "workflow.enabled": true,
516
- "workflow.id": {
517
- [import_database.Op.not]: null
518
- }
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
519
530
  },
520
- appends: ["workflow"],
521
- sort: "id"
522
- });
523
- if (execution) {
524
- this.getLogger(execution.workflowId).info(`execution (${execution.id}) fetched from db`);
525
- next = [execution];
526
- }
527
- }
528
- if (next) {
529
- await this.process(...next);
530
- }
531
- } catch (err) {
532
- console.error(err);
533
- } finally {
534
- this.executing = null;
535
- this.getLogger("dispatcher").info(`execution dispatched finished`);
536
- if (next) {
537
- this.dispatch();
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 });
538
557
  }
539
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
+ }
540
567
  })();
541
568
  }
569
+ createProcessor(execution, options = {}) {
570
+ return new import_Processor.default(execution, { ...options, plugin: this });
571
+ }
542
572
  async process(execution, job, options = {}) {
543
573
  var _a, _b;
544
574
  if (execution.status === import_constants.EXECUTION_STATUS.QUEUEING) {
@@ -30,7 +30,7 @@ export default class DateFieldScheduleTrigger {
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>;
@@ -132,6 +132,7 @@ class DateFieldScheduleTrigger {
132
132
  const now = /* @__PURE__ */ new Date();
133
133
  workflows.forEach(async (workflow) => {
134
134
  const records = await this.loadRecordsToSchedule(workflow, now);
135
+ this.workflow.getLogger(workflow.id).info(`[Schedule on date field] ${records.length} records to schedule`);
135
136
  records.forEach((record) => {
136
137
  const nextTime = this.getRecordNextTime(workflow, record);
137
138
  this.schedule(workflow, record, nextTime, Boolean(nextTime));
@@ -145,17 +146,20 @@ class DateFieldScheduleTrigger {
145
146
  // b. repeat in range (number or cron):
146
147
  // i. endsOn after now -> yes
147
148
  // ii. endsOn before now -> no
148
- async loadRecordsToSchedule({ config: { collection, limit, startsOn, repeat, endsOn }, allExecuted }, currentDate) {
149
+ async loadRecordsToSchedule({ id, config: { collection, limit, startsOn, repeat, endsOn }, allExecuted }, currentDate) {
149
150
  const { dataSourceManager } = this.workflow.app;
150
151
  if (limit && allExecuted >= limit) {
152
+ this.workflow.getLogger(id).warn(`[Schedule on date field] limit reached (all executed ${allExecuted})`);
151
153
  return [];
152
154
  }
153
155
  if (!startsOn) {
156
+ this.workflow.getLogger(id).warn(`[Schedule on date field] "startsOn" is not configured`);
154
157
  return [];
155
158
  }
156
159
  const timestamp = currentDate.getTime();
157
160
  const startTimestamp = getOnTimestampWithOffset(startsOn, currentDate);
158
161
  if (!startTimestamp) {
162
+ this.workflow.getLogger(id).warn(`[Schedule on date field] "startsOn.field" is not configured`);
159
163
  return [];
160
164
  }
161
165
  const [dataSourceName, collectionName] = (0, import_data_source_manager.parseCollectionName)(collection);
@@ -194,21 +198,21 @@ class DateFieldScheduleTrigger {
194
198
  }
195
199
  }
196
200
  if (endsOn) {
197
- const now = /* @__PURE__ */ new Date();
198
- const endTimestamp = getOnTimestampWithOffset(endsOn, now);
199
- if (!endTimestamp) {
200
- return [];
201
- }
202
201
  if (typeof endsOn === "string") {
203
- if (endTimestamp <= timestamp) {
202
+ if ((0, import_utils.parseDateWithoutMs)(endsOn) <= timestamp) {
204
203
  return [];
205
204
  }
206
205
  } else {
207
- conditions.push({
208
- [endsOn.field]: {
209
- [import_database.Op.gte]: new Date(endTimestamp)
210
- }
211
- });
206
+ const endTimestamp = getOnTimestampWithOffset(endsOn, currentDate);
207
+ if (endTimestamp) {
208
+ conditions.push({
209
+ [endsOn.field]: {
210
+ [import_database.Op.gte]: new Date(endTimestamp)
211
+ }
212
+ });
213
+ } else {
214
+ this.workflow.getLogger(id).warn(`[Schedule on date field] "endsOn.field" is not configured`);
215
+ }
212
216
  }
213
217
  }
214
218
  } else {
@@ -218,6 +222,7 @@ class DateFieldScheduleTrigger {
218
222
  }
219
223
  });
220
224
  }
225
+ this.workflow.getLogger(id).debug(`[Schedule on date field] conditions: `, { conditions });
221
226
  return model.findAll({
222
227
  where: {
223
228
  [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.6.0-alpha.12",
7
+ "version": "1.6.0-alpha.13",
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.6.0-alpha.12"
13
+ "@nocobase/plugin-workflow-test": "1.6.0-alpha.13"
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": "b13c1c22daf71b4ec311114a6019c0f061864d9b",
47
+ "gitHead": "b051b9016899d0c9fd5b54543d3898edace9950b",
48
48
  "keywords": [
49
49
  "Workflow"
50
50
  ]