@nocobase/plugin-workflow 1.9.0-beta.5 → 1.9.0-beta.7

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.
Files changed (29) hide show
  1. package/dist/client/2a8332e23037d42f.js +10 -0
  2. package/dist/client/3b0762a72796b5f8.js +10 -0
  3. package/dist/client/9e124936e3877c66.js +10 -0
  4. package/dist/client/components/ExecutionStatus.d.ts +2 -3
  5. package/dist/client/index.js +1 -1
  6. package/dist/client/schemas/executions.d.ts +22 -0
  7. package/dist/client/variable.d.ts +1 -1
  8. package/dist/common/collections/executions.d.ts +22 -0
  9. package/dist/common/collections/executions.js +7 -1
  10. package/dist/externalVersion.js +11 -11
  11. package/dist/locale/zh-CN.json +4 -2
  12. package/dist/node_modules/cron-parser/package.json +1 -1
  13. package/dist/node_modules/lru-cache/package.json +1 -1
  14. package/dist/node_modules/nodejs-snowflake/package.json +1 -1
  15. package/dist/server/Plugin.js +13 -13
  16. package/dist/server/Processor.d.ts +4 -4
  17. package/dist/server/Processor.js +58 -16
  18. package/dist/server/actions/executions.js +2 -2
  19. package/dist/server/instructions/ConditionInstruction.js +0 -1
  20. package/dist/server/instructions/index.d.ts +1 -1
  21. package/dist/server/migrations/20250820145214-mobile-tasks-uid.d.ts +21 -0
  22. package/dist/server/migrations/20250820145214-mobile-tasks-uid.js +58 -0
  23. package/dist/server/migrations/20250826154821-execution-dispatched.d.ts +21 -0
  24. package/dist/server/migrations/20250826154821-execution-dispatched.js +64 -0
  25. package/dist/server/types/Execution.d.ts +1 -0
  26. package/package.json +2 -2
  27. package/dist/client/256475f279fb46d1.js +0 -10
  28. package/dist/client/69d4f948046f2ad2.js +0 -10
  29. package/dist/client/98ae71d4cff2436b.js +0 -10
@@ -45,6 +45,7 @@ export declare const executionSchema: {
45
45
  foreignKey?: undefined;
46
46
  unique?: undefined;
47
47
  onDelete?: undefined;
48
+ defaultValue?: undefined;
48
49
  } | {
49
50
  type: string;
50
51
  name: string;
@@ -69,6 +70,7 @@ export declare const executionSchema: {
69
70
  autoIncrement?: undefined;
70
71
  unique?: undefined;
71
72
  onDelete?: undefined;
73
+ defaultValue?: undefined;
72
74
  } | {
73
75
  type: string;
74
76
  name: string;
@@ -80,6 +82,7 @@ export declare const executionSchema: {
80
82
  foreignKey?: undefined;
81
83
  unique?: undefined;
82
84
  onDelete?: undefined;
85
+ defaultValue?: undefined;
83
86
  } | {
84
87
  type: string;
85
88
  name: string;
@@ -91,6 +94,7 @@ export declare const executionSchema: {
91
94
  target?: undefined;
92
95
  foreignKey?: undefined;
93
96
  onDelete?: undefined;
97
+ defaultValue?: undefined;
94
98
  } | {
95
99
  type: string;
96
100
  name: string;
@@ -102,6 +106,7 @@ export declare const executionSchema: {
102
106
  target?: undefined;
103
107
  foreignKey?: undefined;
104
108
  unique?: undefined;
109
+ defaultValue?: undefined;
105
110
  } | {
106
111
  type: string;
107
112
  name: string;
@@ -121,6 +126,19 @@ export declare const executionSchema: {
121
126
  foreignKey?: undefined;
122
127
  unique?: undefined;
123
128
  onDelete?: undefined;
129
+ defaultValue?: undefined;
130
+ } | {
131
+ type: string;
132
+ name: string;
133
+ defaultValue: boolean;
134
+ interface?: undefined;
135
+ uiSchema?: undefined;
136
+ primaryKey?: undefined;
137
+ autoIncrement?: undefined;
138
+ target?: undefined;
139
+ foreignKey?: undefined;
140
+ unique?: undefined;
141
+ onDelete?: undefined;
124
142
  } | {
125
143
  interface: string;
126
144
  type: string;
@@ -142,7 +160,11 @@ export declare const executionSchema: {
142
160
  foreignKey?: undefined;
143
161
  unique?: undefined;
144
162
  onDelete?: undefined;
163
+ defaultValue?: undefined;
145
164
  })[];
165
+ indexes: {
166
+ fields: string[];
167
+ }[];
146
168
  };
147
169
  resourceName: string;
148
170
  request: {
@@ -71,7 +71,7 @@ export declare const BaseTypeSets: {
71
71
  string: Set<string>;
72
72
  date: Set<string>;
73
73
  };
74
- export declare function useWorkflowVariableOptions(options?: UseVariableOptions): any[];
74
+ export declare function useWorkflowVariableOptions(options?: UseVariableOptions, preset?: VariableOption[]): VariableOption[];
75
75
  export declare function getCollectionFieldOptions(options: any): VariableOption[];
76
76
  export declare function useGetDataSourceCollectionManager(dataSourceName?: any): CollectionManager;
77
77
  export declare function WorkflowVariableInput({ variableOptions, ...props }: {
@@ -34,6 +34,7 @@ declare const _default: {
34
34
  foreignKey?: undefined;
35
35
  unique?: undefined;
36
36
  onDelete?: undefined;
37
+ defaultValue?: undefined;
37
38
  } | {
38
39
  type: string;
39
40
  name: string;
@@ -58,6 +59,7 @@ declare const _default: {
58
59
  autoIncrement?: undefined;
59
60
  unique?: undefined;
60
61
  onDelete?: undefined;
62
+ defaultValue?: undefined;
61
63
  } | {
62
64
  type: string;
63
65
  name: string;
@@ -69,6 +71,7 @@ declare const _default: {
69
71
  foreignKey?: undefined;
70
72
  unique?: undefined;
71
73
  onDelete?: undefined;
74
+ defaultValue?: undefined;
72
75
  } | {
73
76
  type: string;
74
77
  name: string;
@@ -80,6 +83,7 @@ declare const _default: {
80
83
  target?: undefined;
81
84
  foreignKey?: undefined;
82
85
  onDelete?: undefined;
86
+ defaultValue?: undefined;
83
87
  } | {
84
88
  type: string;
85
89
  name: string;
@@ -91,6 +95,7 @@ declare const _default: {
91
95
  target?: undefined;
92
96
  foreignKey?: undefined;
93
97
  unique?: undefined;
98
+ defaultValue?: undefined;
94
99
  } | {
95
100
  type: string;
96
101
  name: string;
@@ -110,6 +115,19 @@ declare const _default: {
110
115
  foreignKey?: undefined;
111
116
  unique?: undefined;
112
117
  onDelete?: undefined;
118
+ defaultValue?: undefined;
119
+ } | {
120
+ type: string;
121
+ name: string;
122
+ defaultValue: boolean;
123
+ interface?: undefined;
124
+ uiSchema?: undefined;
125
+ primaryKey?: undefined;
126
+ autoIncrement?: undefined;
127
+ target?: undefined;
128
+ foreignKey?: undefined;
129
+ unique?: undefined;
130
+ onDelete?: undefined;
113
131
  } | {
114
132
  interface: string;
115
133
  type: string;
@@ -131,6 +149,10 @@ declare const _default: {
131
149
  foreignKey?: undefined;
132
150
  unique?: undefined;
133
151
  onDelete?: undefined;
152
+ defaultValue?: undefined;
134
153
  })[];
154
+ indexes: {
155
+ fields: string[];
156
+ }[];
135
157
  };
136
158
  export default _default;
@@ -101,6 +101,11 @@ var executions_default = {
101
101
  enum: "{{ExecutionStatusOptions}}"
102
102
  }
103
103
  },
104
+ {
105
+ type: "boolean",
106
+ name: "dispatched",
107
+ defaultValue: false
108
+ },
104
109
  {
105
110
  type: "json",
106
111
  name: "stack"
@@ -121,5 +126,6 @@ var executions_default = {
121
126
  "x-read-pretty": true
122
127
  }
123
128
  }
124
- ]
129
+ ],
130
+ indexes: [{ fields: ["dispatched", "id"] }]
125
131
  };
@@ -11,8 +11,8 @@ 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.9.0-beta.5",
15
- "@nocobase/utils": "1.9.0-beta.5",
14
+ "@nocobase/client": "1.9.0-beta.7",
15
+ "@nocobase/utils": "1.9.0-beta.7",
16
16
  "antd": "5.24.2",
17
17
  "@ant-design/icons": "5.6.1",
18
18
  "react-router-dom": "6.28.1",
@@ -20,17 +20,17 @@ module.exports = {
20
20
  "lodash": "4.17.21",
21
21
  "@dnd-kit/core": "6.1.0",
22
22
  "@formily/shared": "2.3.2",
23
- "@nocobase/plugin-mobile": "1.9.0-beta.5",
23
+ "@nocobase/plugin-mobile": "1.9.0-beta.7",
24
24
  "sequelize": "6.35.2",
25
- "@nocobase/database": "1.9.0-beta.5",
26
- "@nocobase/server": "1.9.0-beta.5",
27
- "@nocobase/data-source-manager": "1.9.0-beta.5",
28
- "@nocobase/logger": "1.9.0-beta.5",
29
- "@nocobase/evaluators": "1.9.0-beta.5",
25
+ "@nocobase/database": "1.9.0-beta.7",
26
+ "@nocobase/server": "1.9.0-beta.7",
27
+ "@nocobase/data-source-manager": "1.9.0-beta.7",
28
+ "@nocobase/logger": "1.9.0-beta.7",
29
+ "@nocobase/evaluators": "1.9.0-beta.7",
30
30
  "@formily/antd-v5": "1.2.3",
31
31
  "@formily/reactive": "2.3.0",
32
- "@nocobase/actions": "1.9.0-beta.5",
32
+ "@nocobase/actions": "1.9.0-beta.7",
33
33
  "dayjs": "1.11.13",
34
- "@nocobase/plugin-workflow-test": "1.9.0-beta.5",
35
- "@nocobase/test": "1.9.0-beta.5"
34
+ "@nocobase/plugin-workflow-test": "1.9.0-beta.7",
35
+ "@nocobase/test": "1.9.0-beta.7"
36
36
  };
@@ -241,12 +241,14 @@
241
241
  "Move all downstream nodes to": "将所有下游节点移至",
242
242
  "After end of branches": "分支结束后",
243
243
  "Inside of branch": "分支内",
244
-
244
+ "Workflow tasks": "流程待办",
245
245
  "Workflow todos": "流程待办",
246
246
  "New version enabled": "已启用新版本",
247
247
  "Workflow is not exists": "工作流不存在",
248
248
 
249
249
  "Select users": "选择用户",
250
250
  "Query users": "查询用户",
251
- "Add": "添加"
251
+ "Add": "添加",
252
+ "The workflow tasks page has already been created.": "工作流待办页面已创建。",
253
+ "No workflow tasks available. Please contact the administrator.": "没有可用的工作流待办,请联系管理员。"
252
254
  }
@@ -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-07-24T15:19:35.741Z"}
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-09-11T06:34:49.591Z"}
@@ -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-07-24T15:19:35.376Z"}
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-09-11T06:34:49.258Z"}
@@ -1 +1 @@
1
- {"name":"nodejs-snowflake","collaborators":["Utkarsh Srivastava <utkarsh@sagacious.dev>"],"description":"Generate time sortable 64 bits unique ids for distributed systems (inspired from twitter snowflake)","version":"2.0.1","license":"Apache 2.0","repository":{"type":"git","url":"https://github.com/utkarsh-pro/nodejs-snowflake.git"},"files":["nodejs_snowflake_bg.wasm","nodejs_snowflake.js","nodejs_snowflake.d.ts"],"main":"nodejs_snowflake.js","types":"nodejs_snowflake.d.ts","_lastModified":"2025-07-24T15:19:35.186Z"}
1
+ {"name":"nodejs-snowflake","collaborators":["Utkarsh Srivastava <utkarsh@sagacious.dev>"],"description":"Generate time sortable 64 bits unique ids for distributed systems (inspired from twitter snowflake)","version":"2.0.1","license":"Apache 2.0","repository":{"type":"git","url":"https://github.com/utkarsh-pro/nodejs-snowflake.git"},"files":["nodejs_snowflake_bg.wasm","nodejs_snowflake.js","nodejs_snowflake.d.ts"],"main":"nodejs_snowflake.js","types":"nodejs_snowflake.d.ts","_lastModified":"2025-09-11T06:34:48.715Z"}
@@ -81,7 +81,7 @@ class PluginWorkflowServer extends import_server.Plugin {
81
81
  const execution = await ExecutionRepo.findOne({
82
82
  filterByTk: event.executionId
83
83
  });
84
- if (!execution || execution.status !== import_constants.EXECUTION_STATUS.QUEUEING) {
84
+ if (!execution || execution.dispatched) {
85
85
  this.getLogger("dispatcher").info(
86
86
  `execution (${event.executionId}) from queue not found or not in queueing status, skip`
87
87
  );
@@ -474,7 +474,7 @@ class PluginWorkflowServer extends import_server.Plugin {
474
474
  * @experimental
475
475
  */
476
476
  async start(execution) {
477
- if (execution.status !== import_constants.EXECUTION_STATUS.STARTED) {
477
+ if (execution.status) {
478
478
  return;
479
479
  }
480
480
  this.getLogger(execution.workflowId).info(`starting deferred execution (${execution.id})`);
@@ -526,7 +526,7 @@ class PluginWorkflowServer extends import_server.Plugin {
526
526
  key: workflow.key,
527
527
  eventKey: options.eventKey ?? (0, import_crypto.randomUUID)(),
528
528
  stack: options.stack,
529
- status: deferred ? import_constants.EXECUTION_STATUS.STARTED : import_constants.EXECUTION_STATUS.QUEUEING
529
+ dispatched: deferred ?? false
530
530
  },
531
531
  { transaction }
532
532
  );
@@ -571,13 +571,15 @@ class PluginWorkflowServer extends import_server.Plugin {
571
571
  logger.info(`preparing execution for event`);
572
572
  try {
573
573
  const execution = await this.createExecution(...event);
574
- if ((execution == null ? void 0 : execution.status) === import_constants.EXECUTION_STATUS.QUEUEING) {
574
+ if (!(execution == null ? void 0 : execution.dispatched)) {
575
575
  if (!this.executing && !this.pending.length) {
576
576
  logger.info(`local pending list is empty, adding execution (${execution.id}) to pending list`);
577
577
  this.pending.push([execution]);
578
578
  } else {
579
579
  logger.info(`local pending list is not empty, sending execution (${execution.id}) to queue`);
580
- this.app.backgroundJobManager.publish(`${this.name}.pendingExecution`, { executionId: execution.id });
580
+ if (this.ready) {
581
+ this.app.backgroundJobManager.publish(`${this.name}.pendingExecution`, { executionId: execution.id });
582
+ }
581
583
  }
582
584
  }
583
585
  } catch (error) {
@@ -625,9 +627,7 @@ class PluginWorkflowServer extends import_server.Plugin {
625
627
  async (transaction) => {
626
628
  const execution = await this.db.getRepository("executions").findOne({
627
629
  filter: {
628
- status: {
629
- [import_database.Op.is]: import_constants.EXECUTION_STATUS.QUEUEING
630
- },
630
+ dispatched: false,
631
631
  "workflow.enabled": true
632
632
  },
633
633
  sort: "id",
@@ -637,6 +637,7 @@ class PluginWorkflowServer extends import_server.Plugin {
637
637
  this.getLogger(execution.workflowId).info(`execution (${execution.id}) fetched from db`);
638
638
  await execution.update(
639
639
  {
640
+ dispatched: true,
640
641
  status: import_constants.EXECUTION_STATUS.STARTED
641
642
  },
642
643
  { transaction }
@@ -668,9 +669,9 @@ class PluginWorkflowServer extends import_server.Plugin {
668
669
  async process(execution, job, options = {}) {
669
670
  var _a, _b;
670
671
  const logger = this.getLogger(execution.workflowId);
671
- if (execution.status === import_constants.EXECUTION_STATUS.QUEUEING) {
672
+ if (!execution.dispatched) {
672
673
  const transaction = await this.useDataSourceTransaction("main", options.transaction);
673
- await execution.update({ status: import_constants.EXECUTION_STATUS.STARTED }, { transaction });
674
+ await execution.update({ dispatched: true, status: import_constants.EXECUTION_STATUS.STARTED }, { transaction });
674
675
  logger.info(`execution (${execution.id}) from pending list updated to started`);
675
676
  }
676
677
  const processor = this.createProcessor(execution, options);
@@ -746,9 +747,8 @@ class PluginWorkflowServer extends import_server.Plugin {
746
747
  });
747
748
  }
748
749
  if (userId) {
749
- this.app.emit("ws:sendToTag", {
750
- tagKey: "userId",
751
- tagValue: `${userId}`,
750
+ this.app.emit("ws:sendToUser", {
751
+ userId,
752
752
  message: { type: "workflow:tasks:updated", payload: record.get() }
753
753
  });
754
754
  }
@@ -43,7 +43,7 @@ export default class Processor {
43
43
  /**
44
44
  * @experimental
45
45
  */
46
- nodesMap: Map<number, FlowNodeModel>;
46
+ nodesMap: Map<string | number, FlowNodeModel>;
47
47
  private jobsMapByNodeKey;
48
48
  private jobResultsMapByNodeKey;
49
49
  private jobsToSave;
@@ -61,7 +61,7 @@ export default class Processor {
61
61
  run(node: any, input?: any): any;
62
62
  end(node: any, job: JobModel): Promise<any>;
63
63
  private recall;
64
- exit(s?: number): Promise<any>;
64
+ exit(s?: number | true): Promise<any>;
65
65
  /**
66
66
  * @experimental
67
67
  */
@@ -95,7 +95,7 @@ export default class Processor {
95
95
  /**
96
96
  * @experimental
97
97
  */
98
- getScope(sourceNodeId: number, includeSelfScope?: boolean): {
98
+ getScope(sourceNodeId?: number | string, includeSelfScope?: boolean): {
99
99
  $context: any;
100
100
  $jobsMapByNodeKey: {
101
101
  [key: string]: any;
@@ -107,7 +107,7 @@ export default class Processor {
107
107
  /**
108
108
  * @experimental
109
109
  */
110
- getParsedValue(value: any, sourceNodeId: number, { additionalScope, includeSelfScope }?: {
110
+ getParsedValue(value: any, sourceNodeId?: number | string, { additionalScope, includeSelfScope }?: {
111
111
  additionalScope?: {};
112
112
  includeSelfScope?: boolean;
113
113
  }): any;
@@ -39,6 +39,7 @@ __export(Processor_exports, {
39
39
  default: () => Processor
40
40
  });
41
41
  module.exports = __toCommonJS(Processor_exports);
42
+ var import_sequelize = require("sequelize");
42
43
  var import_database = require("@nocobase/database");
43
44
  var import_evaluators = require("@nocobase/evaluators");
44
45
  var import_utils = require("@nocobase/utils");
@@ -117,10 +118,23 @@ class Processor {
117
118
  if (!execution.workflow) {
118
119
  execution.workflow = plugin.enabledCache.get(execution.workflowId) || await execution.getWorkflow({ transaction });
119
120
  }
120
- const nodes = await execution.workflow.getNodes({ transaction });
121
+ const nodes = execution.workflow.nodes || await execution.workflow.getNodes({ transaction });
121
122
  execution.workflow.nodes = nodes;
122
123
  this.makeNodes(nodes);
124
+ const JobDBModel = plugin.db.getModel("jobs");
125
+ const jobIds = await JobDBModel.findAll({
126
+ attributes: ["executionId", "nodeId", [(0, import_sequelize.fn)("MAX", (0, import_sequelize.col)("id")), "id"]],
127
+ group: ["executionId", "nodeId"],
128
+ where: {
129
+ executionId: execution.id
130
+ },
131
+ raw: true,
132
+ transaction
133
+ });
123
134
  const jobs = await execution.getJobs({
135
+ where: {
136
+ id: jobIds.map((item) => item.id)
137
+ },
124
138
  order: [["id", "ASC"]],
125
139
  transaction
126
140
  });
@@ -129,7 +143,7 @@ class Processor {
129
143
  }
130
144
  async start() {
131
145
  const { execution } = this;
132
- if (execution.status !== import_constants.EXECUTION_STATUS.STARTED) {
146
+ if (execution.status) {
133
147
  this.logger.warn(`execution was ended with status ${execution.status} before, could not be started again`);
134
148
  return;
135
149
  }
@@ -143,7 +157,7 @@ class Processor {
143
157
  }
144
158
  async resume(job) {
145
159
  const { execution } = this;
146
- if (execution.status !== import_constants.EXECUTION_STATUS.STARTED) {
160
+ if (execution.status) {
147
161
  this.logger.warn(`execution was ended with status ${execution.status} before, could not be resumed`);
148
162
  return;
149
163
  }
@@ -154,12 +168,14 @@ class Processor {
154
168
  async exec(instruction, node, prevJob) {
155
169
  let job;
156
170
  try {
157
- this.logger.info(`execution (${this.execution.id}) run instruction [${node.type}] for node (${node.id})`);
158
171
  this.logger.debug(`config of node`, { data: node.config });
159
172
  job = await instruction(node, prevJob, this);
160
- if (!job) {
173
+ if (job === null) {
161
174
  return this.exit();
162
175
  }
176
+ if (!job) {
177
+ return this.exit(true);
178
+ }
163
179
  } catch (err) {
164
180
  this.logger.error(
165
181
  `execution (${this.execution.id}) run instruction [${node.type}] for node (${node.id}) failed: `,
@@ -201,6 +217,7 @@ class Processor {
201
217
  if (typeof instruction.run !== "function") {
202
218
  return Promise.reject(new Error("`run` should be implemented for customized execution of the node"));
203
219
  }
220
+ this.logger.info(`execution (${this.execution.id}) run instruction [${node.type}] for node (${node.id})`);
204
221
  return this.exec(instruction.run.bind(instruction), node, input);
205
222
  }
206
223
  // parent node should take over the control
@@ -225,16 +242,35 @@ class Processor {
225
242
  new Error(`"resume" method should be implemented for [${node.type}] instruction of node (#${node.id})`)
226
243
  );
227
244
  }
245
+ this.logger.info(`execution (${this.execution.id}) resume instruction [${node.type}] for node (${node.id})`);
228
246
  return this.exec(instruction.resume.bind(instruction), node, job);
229
247
  }
230
248
  async exit(s) {
249
+ if (s === true) {
250
+ return;
251
+ }
231
252
  if (this.jobsToSave.size) {
232
253
  const newJobs = [];
233
254
  for (const job of this.jobsToSave.values()) {
234
255
  if (job.isNewRecord) {
235
256
  newJobs.push(job);
236
257
  } else {
237
- await job.save({ transaction: this.mainTransaction });
258
+ const JobCollection = this.options.plugin.db.getCollection("jobs");
259
+ const changes = [];
260
+ if (job.changed("status")) {
261
+ changes.push([`status`, job.status]);
262
+ job.changed("status", false);
263
+ }
264
+ if (job.changed("result")) {
265
+ changes.push([`result`, JSON.stringify(job.result ?? null)]);
266
+ job.changed("result", false);
267
+ }
268
+ if (changes.length) {
269
+ await this.options.plugin.db.sequelize.query(
270
+ `UPDATE ${JobCollection.quotedTableName()} SET ${changes.map(([key]) => `${key} = ?`)} WHERE id='${job.id}'`,
271
+ { replacements: changes.map(([, value]) => value), transaction: this.mainTransaction }
272
+ );
273
+ }
238
274
  }
239
275
  }
240
276
  if (newJobs.length) {
@@ -273,18 +309,24 @@ class Processor {
273
309
  job = payload;
274
310
  job.set("updatedAt", /* @__PURE__ */ new Date());
275
311
  } else {
276
- job = model.build({
277
- ...payload,
278
- id: this.options.plugin.snowflake.getUniqueID().toString(),
279
- createdAt: /* @__PURE__ */ new Date(),
280
- updatedAt: /* @__PURE__ */ new Date(),
281
- executionId: this.execution.id
282
- });
312
+ job = model.build(
313
+ {
314
+ ...payload,
315
+ id: this.options.plugin.snowflake.getUniqueID().toString(),
316
+ createdAt: /* @__PURE__ */ new Date(),
317
+ updatedAt: /* @__PURE__ */ new Date(),
318
+ executionId: this.execution.id
319
+ },
320
+ {
321
+ isNewRecord: true
322
+ }
323
+ );
283
324
  }
284
325
  this.jobsToSave.set(job.id, job);
285
326
  this.lastSavedJob = job;
286
327
  this.jobsMapByNodeKey[job.nodeKey] = job;
287
328
  this.jobResultsMapByNodeKey[job.nodeKey] = job.result;
329
+ this.logger.debug(`job added to save list: ${JSON.stringify(job)}`);
288
330
  return job;
289
331
  }
290
332
  /**
@@ -349,7 +391,7 @@ class Processor {
349
391
  for (let n = this.findBranchEndNode(node); n && n !== node.upstream; n = n.upstream) {
350
392
  branchJobs.push(...allJobs.filter((item) => item.nodeId === n.id));
351
393
  }
352
- branchJobs.sort((a, b) => a.updatedAt.getTime() - b.updatedAt.getTime());
394
+ branchJobs.sort((a, b) => a.id - b.id);
353
395
  return branchJobs[branchJobs.length - 1] || null;
354
396
  }
355
397
  /**
@@ -362,8 +404,8 @@ class Processor {
362
404
  execution: this.execution,
363
405
  node
364
406
  };
365
- for (const [name, fn] of this.options.plugin.functions.getEntities()) {
366
- (0, import_set.default)(systemFns, name, fn.bind(scope));
407
+ for (const [name, fn2] of this.options.plugin.functions.getEntities()) {
408
+ (0, import_set.default)(systemFns, name, fn2.bind(scope));
367
409
  }
368
410
  const $scopes = {};
369
411
  for (let n = includeSelfScope ? node : this.findBranchParentNode(node); n; n = this.findBranchParentNode(n)) {
@@ -70,14 +70,14 @@ async function cancel(context, next) {
70
70
  await context.db.sequelize.transaction(async (transaction) => {
71
71
  await execution.update(
72
72
  {
73
- status: import_constants.EXECUTION_STATUS.CANCELED
73
+ status: import_constants.EXECUTION_STATUS.ABORTED
74
74
  },
75
75
  { transaction }
76
76
  );
77
77
  const pendingJobs = execution.jobs.filter((job) => job.status === import_constants.JOB_STATUS.PENDING);
78
78
  await JobRepo.update({
79
79
  values: {
80
- status: import_constants.JOB_STATUS.CANCELED
80
+ status: import_constants.JOB_STATUS.ABORTED
81
81
  },
82
82
  filter: {
83
83
  id: pendingJobs.map((job) => job.id)
@@ -75,7 +75,6 @@ class ConditionInstruction extends import__.Instruction {
75
75
  }
76
76
  const savedJob = processor.saveJob(job);
77
77
  await processor.run(branchNode, savedJob);
78
- return null;
79
78
  }
80
79
  async resume(node, branchJob, processor) {
81
80
  const job = processor.findBranchParentJob(branchJob, node);
@@ -15,7 +15,7 @@ export interface IJob {
15
15
  result?: unknown;
16
16
  [key: string]: unknown;
17
17
  }
18
- export type InstructionResult = IJob | Promise<IJob> | null;
18
+ export type InstructionResult = IJob | Promise<IJob> | Promise<void> | null | void;
19
19
  export type Runner = (node: FlowNodeModel, input: any, processor: Processor) => InstructionResult;
20
20
  export type InstructionInterface = {
21
21
  run: Runner;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+ /**
10
+ * This file is part of the NocoBase (R) project.
11
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
12
+ * Authors: NocoBase Team.
13
+ *
14
+ * This program is offered under a commercial license.
15
+ * For more information, see <https://www.nocobase.com/agreement>
16
+ */
17
+ import { Migration } from '@nocobase/server';
18
+ export default class extends Migration {
19
+ appVersion: string;
20
+ up(): Promise<void>;
21
+ }