@nocobase/plugin-workflow 2.2.0-alpha.1 → 2.2.0-alpha.11

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 (264) hide show
  1. package/client-v2.d.ts +2 -0
  2. package/client-v2.js +1 -0
  3. package/dist/client/119.e7dbd037d52d1286.js +10 -0
  4. package/dist/client/142.fb4936d78fc80007.js +10 -0
  5. package/dist/client/159.cc9a0f2d92cab2c1.js +10 -0
  6. package/dist/client/276.69fb2aea13bc7c37.js +10 -0
  7. package/dist/client/346.66d060d37843d3d1.js +10 -0
  8. package/dist/client/382.d37fba14a6b91b0b.js +10 -0
  9. package/dist/client/394.a37310b78419ad7a.js +10 -0
  10. package/dist/client/438.6c6409d821d8c353.js +10 -0
  11. package/dist/client/509.88792f5bd054b2af.js +10 -0
  12. package/dist/client/54.d81b710f7b4c1cd5.js +10 -0
  13. package/dist/client/618.1aa6c21d0f2840cb.js +10 -0
  14. package/dist/client/635.ff6085589e23d39b.js +10 -0
  15. package/dist/client/67.56a3d15a55ab7d5c.js +10 -0
  16. package/dist/client/719.f011fde3ad54571e.js +10 -0
  17. package/dist/client/728.711fd4f1ed7d4e6a.js +10 -0
  18. package/dist/client/739.49407722fca8d236.js +10 -0
  19. package/dist/client/759.13aab01e6912ed8d.js +10 -0
  20. package/dist/client/772.1ebaef11a0ac8688.js +10 -0
  21. package/dist/client/782.47792ce10fc0d5fb.js +10 -0
  22. package/dist/client/828.6880ab21513b1968.js +10 -0
  23. package/dist/client/87.083467b89aaf3e53.js +10 -0
  24. package/dist/client/938.26493fc09ba1ccbc.js +10 -0
  25. package/dist/client/964.5ab736effd480a42.js +10 -0
  26. package/dist/client/972.dd7f074d5f12e171.js +10 -0
  27. package/dist/client/AddNodeContext.d.ts +1 -9
  28. package/dist/client/Branch.d.ts +1 -1
  29. package/dist/client/BranchContext.d.ts +2 -10
  30. package/dist/client/FlowContext.d.ts +10 -5
  31. package/dist/client/NodeClipboardContext.d.ts +12 -2
  32. package/dist/client/NodeDragContext.d.ts +14 -2
  33. package/dist/client/RemoveNodeContext.d.ts +16 -2
  34. package/dist/client/index.d.ts +1 -1
  35. package/dist/client/index.js +1 -1
  36. package/dist/client/nodeVariableUtils.d.ts +7 -6
  37. package/dist/client/nodes/calculation.d.ts +3 -75
  38. package/dist/client/nodes/condition.d.ts +7 -111
  39. package/dist/client/nodes/create.d.ts +3 -124
  40. package/dist/client/nodes/destroy.d.ts +2 -57
  41. package/dist/client/nodes/end.d.ts +2 -23
  42. package/dist/client/nodes/index.d.ts +2 -91
  43. package/dist/client/nodes/multi-conditions.d.ts +10 -48
  44. package/dist/client/nodes/output.d.ts +2 -44
  45. package/dist/client/nodes/query.d.ts +3 -255
  46. package/dist/client/nodes/update.d.ts +2 -117
  47. package/dist/client/style.d.ts +7 -26
  48. package/dist/client/triggers/collection.d.ts +3 -154
  49. package/dist/client/triggers/index.d.ts +2 -36
  50. package/dist/client/triggers/schedule/index.d.ts +8 -65
  51. package/dist/client/utils.d.ts +4 -5
  52. package/dist/client/variable.d.ts +7 -53
  53. package/dist/client-v2/119.81195bcd0d451279.js +10 -0
  54. package/dist/client-v2/142.a8c8df2a9abb43c5.js +10 -0
  55. package/dist/client-v2/159.cb221540c286cd32.js +10 -0
  56. package/dist/client-v2/276.7f746d899e221e2f.js +10 -0
  57. package/dist/client-v2/326.bdc99ad8e7590970.js +10 -0
  58. package/dist/client-v2/346.8c038b3c99d4fdc9.js +10 -0
  59. package/dist/client-v2/382.05f5482bb512b179.js +10 -0
  60. package/dist/client-v2/387.5e61d648d16dbf1b.js +10 -0
  61. package/dist/client-v2/394.515ed058e7f72797.js +10 -0
  62. package/dist/client-v2/438.b7df0416b66f8f64.js +10 -0
  63. package/dist/client-v2/513.617697f74783a611.js +10 -0
  64. package/dist/client-v2/54.d3daf06e53092726.js +10 -0
  65. package/dist/client-v2/635.14a6f21cf4f16345.js +10 -0
  66. package/dist/client-v2/677.7382807126d9621a.js +10 -0
  67. package/dist/client-v2/719.05cf070ef89a78f4.js +10 -0
  68. package/dist/client-v2/728.4e8322ff8fce87b9.js +10 -0
  69. package/dist/client-v2/739.5b60845103064f8d.js +10 -0
  70. package/dist/client-v2/759.7b162ad3adf450f1.js +10 -0
  71. package/dist/client-v2/772.8e5148d8c1518449.js +10 -0
  72. package/dist/client-v2/938.717e47af39485b29.js +10 -0
  73. package/dist/client-v2/ExecutionCanvas.d.ts +15 -0
  74. package/dist/client-v2/canvas/AddNodeContext.d.ts +35 -0
  75. package/dist/client-v2/canvas/AddNodeContext.shared.d.ts +33 -0
  76. package/dist/client-v2/canvas/AddNodeSlot.d.ts +20 -0
  77. package/dist/client-v2/canvas/Branch.d.ts +32 -0
  78. package/dist/client-v2/canvas/BranchContext.d.ts +29 -0
  79. package/dist/client-v2/canvas/BranchRenderContext.d.ts +14 -0
  80. package/dist/client-v2/canvas/CanvasContent.d.ts +20 -0
  81. package/dist/client-v2/canvas/DownstreamBranchIndex.d.ts +20 -0
  82. package/dist/client-v2/canvas/Instruction.d.ts +139 -0
  83. package/dist/{client/triggers/schedule/EndsByField.d.ts → client-v2/canvas/JobButton.d.ts} +3 -3
  84. package/dist/client-v2/canvas/Node.d.ts +38 -0
  85. package/dist/client-v2/canvas/NodeClipboardContext.d.ts +64 -0
  86. package/dist/client-v2/canvas/NodeConfigDrawer.d.ts +27 -0
  87. package/dist/client-v2/canvas/NodeDragContext.d.ts +83 -0
  88. package/dist/client-v2/canvas/RemoveNodeContext.d.ts +45 -0
  89. package/dist/client-v2/canvas/WorkflowTypedVariableInput.d.ts +16 -0
  90. package/dist/client-v2/canvas/WorkflowVariableInput.d.ts +47 -0
  91. package/dist/client-v2/canvas/WorkflowVariableJsonTextArea.d.ts +15 -0
  92. package/dist/client-v2/canvas/WorkflowVariableTag.d.ts +22 -0
  93. package/dist/client-v2/canvas/WorkflowVariableTextArea.d.ts +23 -0
  94. package/dist/client-v2/canvas/adaptVariableOptionToMetaTree.d.ts +48 -0
  95. package/dist/client-v2/canvas/addNodeController.d.ts +70 -0
  96. package/dist/client-v2/canvas/collectionFieldOptions.d.ts +57 -0
  97. package/dist/client-v2/canvas/contexts.d.ts +86 -0
  98. package/dist/client-v2/canvas/dropImpact.d.ts +28 -0
  99. package/dist/client-v2/canvas/instructionAvailability.d.ts +26 -0
  100. package/dist/client-v2/canvas/nodeRenderDispatch.d.ts +79 -0
  101. package/dist/client-v2/canvas/nodeTree.d.ts +21 -0
  102. package/dist/client-v2/canvas/nodeVariableUtils.d.ts +14 -0
  103. package/dist/client-v2/canvas/removeNodeUtils.d.ts +31 -0
  104. package/dist/client-v2/canvas/style.d.ts +35 -0
  105. package/dist/client-v2/canvas/textAreaInsertion.d.ts +14 -0
  106. package/dist/client-v2/canvas/useWorkflowInstruction.d.ts +23 -0
  107. package/dist/client-v2/canvas/useWorkflowVariableOptions.d.ts +40 -0
  108. package/dist/client-v2/canvas/workflowVariableConverters.d.ts +13 -0
  109. package/dist/client-v2/components/Calculation.d.ts +18 -0
  110. package/dist/client-v2/components/ExecutionStatusIcon.d.ts +18 -0
  111. package/dist/{client/triggers/schedule/RepeatField.d.ts → client-v2/components/ExecutionStatusTag.d.ts} +3 -4
  112. package/dist/client-v2/components/ExecutionViewHeader.d.ts +29 -0
  113. package/dist/client-v2/components/ExecutionsDropdown.d.ts +25 -0
  114. package/dist/client-v2/components/FilterDynamicComponent.d.ts +28 -0
  115. package/dist/client-v2/components/HideVariableContext.d.ts +11 -0
  116. package/dist/client-v2/components/JobResultModal.d.ts +11 -0
  117. package/dist/client-v2/components/RadioWithTooltip.d.ts +23 -0
  118. package/dist/client-v2/components/SyncModeSelect.d.ts +16 -0
  119. package/dist/{client/triggers/schedule/OnField.d.ts → client-v2/components/SyncModeTag.d.ts} +3 -3
  120. package/dist/client-v2/components/TestRunButton.d.ts +36 -0
  121. package/dist/client-v2/components/TimeoutInput.d.ts +15 -0
  122. package/dist/client-v2/components/WorkflowCanvasHeader.d.ts +17 -0
  123. package/dist/client-v2/components/WorkflowDetailsModal.d.ts +25 -0
  124. package/dist/client-v2/components/WorkflowEnabledSwitch.d.ts +16 -0
  125. package/dist/client-v2/components/WorkflowMenu.d.ts +17 -0
  126. package/dist/client-v2/components/WorkflowRevisionsDropdown.d.ts +15 -0
  127. package/dist/client-v2/components/WorkflowVariableWrapper.d.ts +25 -0
  128. package/dist/client-v2/components/collection/AppendsSelect.d.ts +15 -0
  129. package/dist/client-v2/components/collection/AssignedFieldsEditor.d.ts +24 -0
  130. package/dist/client-v2/components/collection/CollectionCascader.d.ts +15 -0
  131. package/dist/client-v2/components/collection/FieldsSelect.d.ts +16 -0
  132. package/dist/client-v2/components/collection/PaginationFields.d.ts +14 -0
  133. package/dist/client-v2/components/collection/SortFieldsInput.d.ts +19 -0
  134. package/dist/client-v2/components/collection/TriggerCollectionRecordSelect.d.ts +15 -0
  135. package/dist/client-v2/components/collection/index.d.ts +16 -0
  136. package/dist/client-v2/components/collection/utils.d.ts +42 -0
  137. package/dist/client-v2/components/formatResultForDisplay.d.ts +17 -0
  138. package/dist/client-v2/components/jobStatus.d.ts +27 -0
  139. package/dist/client-v2/components/renderEngineReference.d.ts +10 -0
  140. package/dist/client-v2/components/workflowCanvas.d.ts +41 -0
  141. package/dist/client-v2/constants.d.ts +19 -0
  142. package/dist/client-v2/hooks/useWorkflowRuntimePaths.d.ts +16 -0
  143. package/dist/client-v2/index.d.ts +48 -0
  144. package/dist/client-v2/index.js +10 -0
  145. package/dist/client-v2/locale.d.ts +41 -0
  146. package/dist/{client → client-v2}/models/NodeDetailsGridModel.d.ts +1 -1
  147. package/dist/{client → client-v2}/models/NodeDetailsModel.d.ts +1 -1
  148. package/dist/{client → client-v2}/models/NodeValueModel.d.ts +1 -1
  149. package/dist/{client → client-v2}/models/TaskCardCommonItemModel.d.ts +1 -1
  150. package/dist/client-v2/models/WorkflowTasksTopbarActionModel.d.ts +18 -0
  151. package/dist/{client → client-v2}/models/index.d.ts +2 -0
  152. package/dist/client-v2/models/triggerWorkflows.d.ts +43 -0
  153. package/dist/client-v2/nodes/calculation.d.ts +38 -0
  154. package/dist/client-v2/nodes/collectionNode.d.ts +29 -0
  155. package/dist/client-v2/nodes/components/calculation.d.ts +11 -0
  156. package/dist/client-v2/nodes/components/collection.d.ts +15 -0
  157. package/dist/client-v2/nodes/components/condition.d.ts +25 -0
  158. package/dist/client-v2/nodes/components/conditionShared.d.ts +20 -0
  159. package/dist/client-v2/nodes/components/create.d.ts +12 -0
  160. package/dist/client-v2/nodes/components/destroy.d.ts +12 -0
  161. package/dist/{client/triggers/schedule/ScheduleConfig.d.ts → client-v2/nodes/components/end.d.ts} +1 -1
  162. package/dist/client-v2/nodes/components/filter.d.ts +17 -0
  163. package/dist/client-v2/nodes/components/multi-conditions.d.ts +13 -0
  164. package/dist/client-v2/nodes/components/multiConditionsShared.d.ts +20 -0
  165. package/dist/client-v2/nodes/components/output.d.ts +10 -0
  166. package/dist/client-v2/nodes/components/query.d.ts +12 -0
  167. package/dist/client-v2/nodes/components/update.d.ts +12 -0
  168. package/dist/client-v2/nodes/condition.d.ts +46 -0
  169. package/dist/client-v2/nodes/create.d.ts +30 -0
  170. package/dist/client-v2/nodes/destroy.d.ts +24 -0
  171. package/dist/client-v2/nodes/end.d.ts +21 -0
  172. package/dist/client-v2/nodes/multi-conditions.d.ts +34 -0
  173. package/dist/client-v2/nodes/output.d.ts +29 -0
  174. package/dist/client-v2/nodes/query.d.ts +32 -0
  175. package/dist/client-v2/nodes/update.d.ts +25 -0
  176. package/dist/client-v2/pages/ExecutionHistoryDrawer.d.ts +13 -0
  177. package/dist/client-v2/pages/ExecutionViewPage.d.ts +10 -0
  178. package/dist/client-v2/pages/WorkflowCanvasPage.d.ts +10 -0
  179. package/dist/client-v2/pages/WorkflowCategoryTabs.d.ts +25 -0
  180. package/dist/client-v2/pages/WorkflowFormDrawer.d.ts +40 -0
  181. package/dist/client-v2/pages/WorkflowPane.d.ts +10 -0
  182. package/dist/client-v2/pages/WorkflowTasksPage.d.ts +10 -0
  183. package/dist/client-v2/plugin.d.ts +119 -0
  184. package/dist/client-v2/taskCenter.d.ts +105 -0
  185. package/dist/client-v2/triggers/ExecuteWorkflowButton.d.ts +35 -0
  186. package/dist/client-v2/triggers/TriggerConfig.d.ts +22 -0
  187. package/dist/client-v2/triggers/TriggerExecutionButton.d.ts +13 -0
  188. package/dist/client-v2/triggers/collection/CollectionConfig.d.ts +14 -0
  189. package/dist/client-v2/triggers/collection/TriggerCollectionConfig.d.ts +11 -0
  190. package/dist/client-v2/triggers/collection/constants.d.ts +28 -0
  191. package/dist/client-v2/triggers/collection/index.d.ts +40 -0
  192. package/dist/client-v2/triggers/index.d.ts +63 -0
  193. package/dist/client-v2/triggers/schedule/EndsByField.d.ts +17 -0
  194. package/dist/client-v2/triggers/schedule/OnField.d.ts +20 -0
  195. package/dist/client-v2/triggers/schedule/RepeatField.d.ts +23 -0
  196. package/dist/client-v2/triggers/schedule/ScheduleConfig.d.ts +17 -0
  197. package/dist/client-v2/triggers/schedule/ScheduleModes.d.ts +41 -0
  198. package/dist/{client → client-v2}/triggers/schedule/TriggerScheduleConfig.d.ts +1 -0
  199. package/dist/{client → client-v2}/triggers/schedule/constants.d.ts +8 -5
  200. package/dist/client-v2/triggers/schedule/index.d.ts +40 -0
  201. package/dist/client-v2/triggers/schedule/locale/Cron.zh-CN.d.ts +11 -0
  202. package/dist/client-v2/utils/contextSingleton.d.ts +9 -0
  203. package/dist/common/collections/workflows.d.ts +16 -0
  204. package/dist/common/collections/workflows.js +5 -0
  205. package/dist/common/defaultWorkflowFilter.d.ts +21 -0
  206. package/dist/common/defaultWorkflowFilter.js +38 -0
  207. package/dist/common/executionStatus.d.ts +44 -0
  208. package/dist/common/executionStatus.js +133 -0
  209. package/dist/externalVersion.js +16 -12
  210. package/dist/locale/de-DE.json +16 -1
  211. package/dist/locale/en-US.json +31 -2
  212. package/dist/locale/es-ES.json +16 -1
  213. package/dist/locale/fr-FR.json +16 -1
  214. package/dist/locale/hu-HU.json +16 -1
  215. package/dist/locale/id-ID.json +16 -1
  216. package/dist/locale/it-IT.json +16 -1
  217. package/dist/locale/ja-JP.json +16 -1
  218. package/dist/locale/ko-KR.json +16 -1
  219. package/dist/locale/nl-NL.json +16 -1
  220. package/dist/locale/pt-BR.json +16 -1
  221. package/dist/locale/ru-RU.json +16 -1
  222. package/dist/locale/tr-TR.json +16 -1
  223. package/dist/locale/uk-UA.json +16 -1
  224. package/dist/locale/vi-VN.json +16 -1
  225. package/dist/locale/zh-CN.json +30 -2
  226. package/dist/locale/zh-TW.json +22 -1
  227. package/dist/node_modules/cron-parser/package.json +1 -1
  228. package/dist/node_modules/joi/package.json +1 -1
  229. package/dist/node_modules/lru-cache/package.json +1 -1
  230. package/dist/node_modules/nodejs-snowflake/package.json +1 -1
  231. package/dist/server/Dispatcher.d.ts +27 -14
  232. package/dist/server/Dispatcher.js +208 -154
  233. package/dist/server/ExecutionTimeoutManager.js +4 -3
  234. package/dist/server/Plugin.d.ts +17 -8
  235. package/dist/server/Plugin.js +58 -13
  236. package/dist/server/Processor.d.ts +17 -7
  237. package/dist/server/Processor.js +112 -0
  238. package/dist/server/actions/executions.js +3 -6
  239. package/dist/server/actions/jobs.js +1 -2
  240. package/dist/server/actions/nodes.js +36 -1
  241. package/dist/server/actions/workflows.d.ts +1 -0
  242. package/dist/server/actions/workflows.js +17 -2
  243. package/dist/server/index.d.ts +1 -1
  244. package/dist/server/instructions/CreateInstruction.js +6 -2
  245. package/dist/server/instructions/DestroyInstruction.js +2 -1
  246. package/dist/server/instructions/QueryInstruction.js +2 -1
  247. package/dist/server/instructions/UpdateInstruction.js +2 -1
  248. package/dist/server/triggers/CollectionTrigger.d.ts +6 -1
  249. package/dist/server/triggers/CollectionTrigger.js +29 -1
  250. package/dist/server/triggers/ScheduleTrigger/StaticScheduleTrigger.d.ts +1 -1
  251. package/dist/server/triggers/index.d.ts +1 -1
  252. package/dist/server/types/Execution.d.ts +2 -0
  253. package/dist/server/types/Job.d.ts +5 -0
  254. package/dist/server/types/Workflow.d.ts +1 -0
  255. package/dist/server/utils.d.ts +2 -1
  256. package/dist/server/utils.js +46 -28
  257. package/dist/swagger/index.d.ts +1 -0
  258. package/dist/swagger/index.js +4 -2
  259. package/package.json +4 -2
  260. package/dist/client/618.19af7f84261c815d.js +0 -10
  261. package/dist/client/67.452743ce8ec30617.js +0 -10
  262. package/dist/client/964.ffbf5b47ed12bbdc.js +0 -10
  263. package/dist/client/triggers/schedule/ScheduleModes.d.ts +0 -170
  264. package/dist/client/triggers/schedule/locale/Cron.zh-CN.d.ts +0 -42
@@ -53,6 +53,7 @@ var import_RunningExecutionRegistry = __toESM(require("./RunningExecutionRegistr
53
53
  var import_actions = __toESM(require("./actions"));
54
54
  var import_nodes = require("./actions/nodes");
55
55
  var import_workflows = require("./actions/workflows");
56
+ var import_constants = require("./constants");
56
57
  var import_functions = __toESM(require("./functions"));
57
58
  var import_CollectionTrigger = __toESM(require("./triggers/CollectionTrigger"));
58
59
  var import_ScheduleTrigger = __toESM(require("./triggers/ScheduleTrigger"));
@@ -170,16 +171,16 @@ class PluginWorkflowServer extends import_server.Plugin {
170
171
  }
171
172
  }
172
173
  this.checker = setInterval(() => {
173
- this.dispatcher.dispatch();
174
+ this.dispatcher.recover({ gracePeriod: 6e4 });
174
175
  }, 3e5);
175
176
  await this.timeoutManager.load();
176
- this.app.on("workflow:dispatch", () => {
177
- this.app.logger.info("workflow:dispatch");
178
- this.dispatcher.dispatch();
177
+ this.app.on("workflow:recover", () => {
178
+ this.app.logger.info("workflow:recover");
179
+ this.dispatcher.recover();
179
180
  });
180
181
  this.dispatcher.setReady(true);
181
182
  this.getLogger("dispatcher").info("(starting) check for queueing executions");
182
- this.dispatcher.dispatch();
183
+ this.dispatcher.recover();
183
184
  };
184
185
  onBeforeStop = async () => {
185
186
  if (this.checker) {
@@ -191,7 +192,6 @@ class PluginWorkflowServer extends import_server.Plugin {
191
192
  for (const workflow of this.enabledCache.values()) {
192
193
  this.toggle(workflow, false, { silent: true });
193
194
  }
194
- this.app.eventQueue.unsubscribe(this.channelPendingExecution);
195
195
  this.loggerCache.clear();
196
196
  };
197
197
  async handleSyncMessage(message) {
@@ -401,7 +401,7 @@ class PluginWorkflowServer extends import_server.Plugin {
401
401
  this.app.on("beforeStop", this.onBeforeStop);
402
402
  this.app.eventQueue.subscribe(this.channelPendingExecution, {
403
403
  idle: () => this.serving() && this.dispatcher.idle,
404
- process: this.dispatcher.onQueueExecution
404
+ process: this.dispatcher.onQueueTask
405
405
  });
406
406
  }
407
407
  toggle(workflow, enable, { silent, transaction } = {}) {
@@ -448,25 +448,70 @@ class PluginWorkflowServer extends import_server.Plugin {
448
448
  trigger(workflow, context, options = {}) {
449
449
  return this.dispatcher.trigger(workflow, context, options);
450
450
  }
451
- async run(pending) {
452
- return this.dispatcher.run(pending);
451
+ async rerun(execution, rerun) {
452
+ return this.dispatcher.enqueue({ executionId: this.getModelId(execution), rerun: rerun ?? {} });
453
453
  }
454
- dispatch() {
455
- return this.dispatcher.dispatch();
454
+ recover() {
455
+ return this.dispatcher.recover();
456
456
  }
457
+ /**
458
+ * Persist the current job state and publish a poke that evaluates that state.
459
+ *
460
+ * PENDING resume calls are valid for instructions such as delay and sequential approval.
461
+ * Callers that aggregate multiple user actions must only call this method when their
462
+ * atomic update changes the job from PENDING to a terminal status.
463
+ * Persistence and queue publication failures are logged and rethrown to awaiting callers.
464
+ */
457
465
  async resume(job) {
458
- return this.dispatcher.resume(job);
466
+ var _a;
467
+ const executionId = job.executionId ?? ((_a = job.execution) == null ? void 0 : _a.id);
468
+ if (executionId == null) {
469
+ this.getLogger("dispatcher").warn(`execution id of job (${job.id}) not found, resume ignored`);
470
+ return;
471
+ }
472
+ try {
473
+ if (job.changed()) {
474
+ await job.save();
475
+ }
476
+ } catch (error) {
477
+ this.getLogger("dispatcher").error(
478
+ `persisting job (${job.id}) before resuming execution (${executionId}) failed`,
479
+ { error, executionId, jobId: job.id }
480
+ );
481
+ throw error;
482
+ }
483
+ try {
484
+ await this.dispatcher.enqueue({ executionId, jobId: job.id });
485
+ this.getLogger("dispatcher").info(`execution (${executionId}) resuming from job (${job.id}) published to queue`);
486
+ } catch (error) {
487
+ this.getLogger("dispatcher").error(
488
+ `publishing resume task for execution (${executionId}) from job (${job.id}) failed`,
489
+ { error, executionId, jobId: job.id }
490
+ );
491
+ throw error;
492
+ }
459
493
  }
460
494
  /**
461
495
  * Start a deferred execution
462
496
  * @experimental
463
497
  */
464
498
  async start(execution) {
465
- return this.dispatcher.start(execution);
499
+ if (typeof execution !== "string" && typeof execution !== "number") {
500
+ if (execution.status !== import_constants.EXECUTION_STATUS.QUEUEING && execution.status !== import_constants.EXECUTION_STATUS.STARTED && execution.status != null) {
501
+ return;
502
+ }
503
+ if (execution.status === import_constants.EXECUTION_STATUS.STARTED && execution.startedAt) {
504
+ return;
505
+ }
506
+ }
507
+ return this.dispatcher.enqueue({ executionId: this.getModelId(execution) });
466
508
  }
467
509
  createProcessor(execution, options = {}) {
468
510
  return new import_Processor.default(execution, { ...options, plugin: this });
469
511
  }
512
+ getModelId(input) {
513
+ return typeof input === "string" || typeof input === "number" ? input : input.id;
514
+ }
470
515
  async execute(workflow, values, options = {}) {
471
516
  const trigger = this.triggers.get(workflow.type);
472
517
  if (!trigger) {
@@ -29,6 +29,12 @@ export type BackgroundAbortHandle = {
29
29
  dispose: () => void;
30
30
  throwIfAborted: () => void;
31
31
  };
32
+ export type ScopeTransaction = {
33
+ transaction: Transaction;
34
+ dataSource: string;
35
+ isolationLevel?: string;
36
+ closing?: 'commit' | 'rollback';
37
+ };
32
38
  export default class Processor {
33
39
  execution: ExecutionModel;
34
40
  options: ProcessorOptions;
@@ -58,6 +64,7 @@ export default class Processor {
58
64
  private jobsMapByNodeKey;
59
65
  private jobResultsMapByNodeKey;
60
66
  private jobsToSave;
67
+ private scopeTransactions;
61
68
  private rerunContext;
62
69
  /**
63
70
  * @experimental
@@ -94,13 +101,7 @@ export default class Processor {
94
101
  prepare(): Promise<void>;
95
102
  start(): Promise<any>;
96
103
  resume(job: JobModel): Promise<void>;
97
- resolveRerun(options?: ProcessorRerunOptions): {
98
- node: FlowNodeModel;
99
- input: JobModel | {
100
- result: any;
101
- };
102
- targetJob: JobModel;
103
- };
104
+ private resolveRerun;
104
105
  rerun(options?: ProcessorRerunOptions): Promise<any>;
105
106
  private getRerunNode;
106
107
  private getRerunInput;
@@ -111,6 +112,15 @@ export default class Processor {
111
112
  end(node: FlowNodeModel, job: JobModel): Promise<any>;
112
113
  private recall;
113
114
  exit(s?: number | true): Promise<any>;
115
+ setScopeTransaction(key: string, info: ScopeTransaction): void;
116
+ getScopeTransactionByKey(key: string): ScopeTransaction;
117
+ clearScopeTransaction(key: string): void;
118
+ markScopeTransactionClosing(key: string, action: 'commit' | 'rollback'): void;
119
+ getScopeTransaction(node: FlowNodeModel, dataSourceName?: string): Transaction | null;
120
+ isInstructionSync(node: FlowNodeModel): boolean;
121
+ private hasOpenScopeTransactions;
122
+ private markOpenScopePendingJobsAsError;
123
+ private cleanupScopeTransactions;
114
124
  /**
115
125
  * @experimental
116
126
  */
@@ -46,6 +46,7 @@ var import_utils = require("@nocobase/utils");
46
46
  var import_set = __toESM(require("lodash/set"));
47
47
  var import_constants = require("./constants");
48
48
  var import_timeout_errors = require("./timeout-errors");
49
+ const OPEN_SCOPE_PENDING_ERROR = "Pending jobs are not allowed inside an open transaction scope";
49
50
  class Processor {
50
51
  constructor(execution, options) {
51
52
  this.execution = execution;
@@ -79,6 +80,7 @@ class Processor {
79
80
  jobsMapByNodeKey = {};
80
81
  jobResultsMapByNodeKey = {};
81
82
  jobsToSave = /* @__PURE__ */ new Map();
83
+ scopeTransactions = /* @__PURE__ */ new Map();
82
84
  rerunContext = null;
83
85
  /**
84
86
  * @experimental
@@ -447,6 +449,15 @@ class Processor {
447
449
  if (s === true) {
448
450
  return;
449
451
  }
452
+ if ((s == null || s === import_constants.JOB_STATUS.PENDING) && this.hasOpenScopeTransactions()) {
453
+ this.markOpenScopePendingJobsAsError(OPEN_SCOPE_PENDING_ERROR);
454
+ s = import_constants.JOB_STATUS.ERROR;
455
+ }
456
+ const hadScopeTransactions = this.scopeTransactions.size > 0;
457
+ await this.cleanupScopeTransactions({ allowCommit: s === import_constants.JOB_STATUS.RESOLVED });
458
+ if (hadScopeTransactions && s == null && this.execution.status === import_constants.EXECUTION_STATUS.STARTED) {
459
+ s = import_constants.JOB_STATUS.ERROR;
460
+ }
450
461
  if (this.jobsToSave.size) {
451
462
  const newJobs = [];
452
463
  for (const job of this.jobsToSave.values()) {
@@ -520,6 +531,107 @@ class Processor {
520
531
  });
521
532
  return null;
522
533
  }
534
+ setScopeTransaction(key, info) {
535
+ this.scopeTransactions.set(key, info);
536
+ }
537
+ getScopeTransactionByKey(key) {
538
+ return this.scopeTransactions.get(key) ?? null;
539
+ }
540
+ clearScopeTransaction(key) {
541
+ this.scopeTransactions.delete(key);
542
+ }
543
+ markScopeTransactionClosing(key, action) {
544
+ const scopeTransaction = this.scopeTransactions.get(key);
545
+ if (scopeTransaction) {
546
+ scopeTransaction.closing = action;
547
+ }
548
+ }
549
+ getScopeTransaction(node, dataSourceName) {
550
+ for (let current = node; current; current = current.upstream) {
551
+ const scopeTransaction = this.scopeTransactions.get(current.key);
552
+ if (!scopeTransaction) {
553
+ continue;
554
+ }
555
+ if (dataSourceName && scopeTransaction.dataSource !== dataSourceName) {
556
+ continue;
557
+ }
558
+ const branchStartNode = this.findBranchStartNode(node, current);
559
+ if ((branchStartNode == null ? void 0 : branchStartNode.branchIndex) !== 1) {
560
+ continue;
561
+ }
562
+ return scopeTransaction.transaction;
563
+ }
564
+ return null;
565
+ }
566
+ isInstructionSync(node) {
567
+ return this.options.plugin.isWorkflowSync(this.execution.workflow) || Boolean(this.getScopeTransaction(node));
568
+ }
569
+ hasOpenScopeTransactions() {
570
+ for (const { transaction } of this.scopeTransactions.values()) {
571
+ if (!transaction.finished) {
572
+ return true;
573
+ }
574
+ }
575
+ return false;
576
+ }
577
+ markOpenScopePendingJobsAsError(message) {
578
+ const pendingJobs = /* @__PURE__ */ new Set();
579
+ for (const job of this.jobsToSave.values()) {
580
+ if (job.status === import_constants.JOB_STATUS.PENDING) {
581
+ pendingJobs.add(job);
582
+ }
583
+ }
584
+ for (const job of Object.values(this.jobsMapByNodeKey)) {
585
+ if (job.status === import_constants.JOB_STATUS.PENDING) {
586
+ pendingJobs.add(job);
587
+ }
588
+ }
589
+ for (const key of this.scopeTransactions.keys()) {
590
+ const job = this.jobsMapByNodeKey[key];
591
+ if ((job == null ? void 0 : job.status) === import_constants.JOB_STATUS.PENDING) {
592
+ pendingJobs.add(job);
593
+ }
594
+ }
595
+ for (const job of pendingJobs) {
596
+ job.set({
597
+ status: import_constants.JOB_STATUS.ERROR,
598
+ result: {
599
+ message
600
+ }
601
+ });
602
+ this.saveJob(job);
603
+ }
604
+ }
605
+ async cleanupScopeTransactions({ allowCommit = false } = {}) {
606
+ if (!this.scopeTransactions.size) {
607
+ return;
608
+ }
609
+ for (const [key, { transaction, dataSource, closing }] of Array.from(this.scopeTransactions.entries()).reverse()) {
610
+ const tx = transaction;
611
+ if (tx.finished) {
612
+ this.scopeTransactions.delete(key);
613
+ continue;
614
+ }
615
+ const action = closing === "commit" && allowCommit ? "commit" : "rollback";
616
+ const actionText = action === "commit" ? "committing" : "rolling back";
617
+ this.logger.warn(
618
+ `scope transaction (${key}) on data source "${dataSource}" was not closed before exit, ${actionText}`,
619
+ {
620
+ workflowId: this.execution.workflowId
621
+ }
622
+ );
623
+ try {
624
+ await tx[action]();
625
+ } catch (error) {
626
+ this.logger.error(`scope transaction (${key}) fallback ${action} failed`, {
627
+ error,
628
+ workflowId: this.execution.workflowId
629
+ });
630
+ } finally {
631
+ this.scopeTransactions.delete(key);
632
+ }
633
+ }
634
+ }
523
635
  /**
524
636
  * @experimental
525
637
  */
@@ -98,12 +98,9 @@ async function rerun(context, next) {
98
98
  if (execution.status !== import_constants.EXECUTION_STATUS.STARTED) {
99
99
  return context.throw(400, "Only started executions can be rerun");
100
100
  }
101
- await workflowPlugin.run({
102
- execution,
103
- rerun: {
104
- nodeId,
105
- overwrite: overwrite === true
106
- }
101
+ await workflowPlugin.rerun(execution, {
102
+ nodeId,
103
+ overwrite: overwrite === true
107
104
  });
108
105
  context.body = execution;
109
106
  context.status = 202;
@@ -82,8 +82,7 @@ async function resume(context, next) {
82
82
  context.body = job;
83
83
  context.status = 202;
84
84
  await next();
85
- job.execution = execution;
86
- workflowPlugin.resume(job);
85
+ await workflowPlugin.resume(job);
87
86
  }
88
87
  // Annotate the CommonJS export names for ESM import in node:
89
88
  0 && (module.exports = {
@@ -78,6 +78,23 @@ function validateNode(context, workflow, values) {
78
78
  }
79
79
  }
80
80
  }
81
+ async function touchWorkflow(context, workflowId, transaction) {
82
+ var _a, _b;
83
+ const values = {
84
+ updatedAt: /* @__PURE__ */ new Date()
85
+ };
86
+ const currentUserId = (_b = (_a = context.state) == null ? void 0 : _a.currentUser) == null ? void 0 : _b.id;
87
+ if (currentUserId != null) {
88
+ values.updatedById = currentUserId;
89
+ }
90
+ await context.db.getCollection("workflows").model.update(values, {
91
+ where: {
92
+ id: workflowId
93
+ },
94
+ transaction,
95
+ hooks: false
96
+ });
97
+ }
81
98
  async function create(context, next) {
82
99
  const { db } = context;
83
100
  const repository = import_actions.utils.getRepositoryFromParams(context);
@@ -122,6 +139,7 @@ async function create(context, next) {
122
139
  await instance.setDownstream(previousHead, { transaction });
123
140
  instance.set("downstream", previousHead);
124
141
  }
142
+ await touchWorkflow(context, workflow.id, transaction);
125
143
  return instance;
126
144
  }
127
145
  const upstream = await instance.getUpstream({ transaction });
@@ -162,6 +180,7 @@ async function create(context, next) {
162
180
  }
163
181
  }
164
182
  instance.set("upstream", upstream);
183
+ await touchWorkflow(context, workflow.id, transaction);
165
184
  return instance;
166
185
  });
167
186
  await next();
@@ -233,6 +252,7 @@ async function duplicate(context, next) {
233
252
  await instance.setDownstream(previousHead, { transaction });
234
253
  instance.set("downstream", previousHead);
235
254
  }
255
+ await touchWorkflow(context, origin.workflowId, transaction);
236
256
  return instance;
237
257
  }
238
258
  const upstream = await instance.getUpstream({ transaction });
@@ -273,6 +293,7 @@ async function duplicate(context, next) {
273
293
  }
274
294
  }
275
295
  instance.set("upstream", upstream);
296
+ await touchWorkflow(context, origin.workflowId, transaction);
276
297
  return instance;
277
298
  });
278
299
  await next();
@@ -401,6 +422,7 @@ async function destroy(context, next) {
401
422
  filterByTk: [instance.id, ...branchNodesToDelete.map((item) => item.id)],
402
423
  transaction
403
424
  });
425
+ await touchWorkflow(context, instance.workflowId, transaction);
404
426
  });
405
427
  context.body = instance;
406
428
  await next();
@@ -431,6 +453,7 @@ async function destroyBranch(context, next) {
431
453
  }
432
454
  let deletedBranchHead = null;
433
455
  await db.sequelize.transaction(async (transaction) => {
456
+ let shouldTouchWorkflow = false;
434
457
  const nodes = await repository.find({
435
458
  filter: {
436
459
  workflowId: instance.workflowId
@@ -461,6 +484,7 @@ async function destroyBranch(context, next) {
461
484
  filterByTk: idsToDelete,
462
485
  transaction
463
486
  });
487
+ shouldTouchWorkflow = true;
464
488
  }
465
489
  }
466
490
  if (shift) {
@@ -475,6 +499,12 @@ async function destroyBranch(context, next) {
475
499
  )
476
500
  )
477
501
  );
502
+ if (headsToShift.length) {
503
+ shouldTouchWorkflow = true;
504
+ }
505
+ }
506
+ if (shouldTouchWorkflow) {
507
+ await touchWorkflow(context, instance.workflowId, transaction);
478
508
  }
479
509
  });
480
510
  context.body = deletedBranchHead;
@@ -579,6 +609,7 @@ async function move(context, next) {
579
609
  },
580
610
  { transaction }
581
611
  );
612
+ await touchWorkflow(context, instance.workflowId, transaction);
582
613
  return instance;
583
614
  }
584
615
  if (branchIndex == null) {
@@ -612,6 +643,7 @@ async function move(context, next) {
612
643
  },
613
644
  { transaction }
614
645
  );
646
+ await touchWorkflow(context, instance.workflowId, transaction);
615
647
  return instance;
616
648
  }
617
649
  const branchHead = await repository.findOne({
@@ -640,6 +672,7 @@ async function move(context, next) {
640
672
  },
641
673
  { transaction }
642
674
  );
675
+ await touchWorkflow(context, instance.workflowId, transaction);
643
676
  return instance;
644
677
  });
645
678
  await next();
@@ -660,7 +693,7 @@ async function update(context, next) {
660
693
  }
661
694
  const merged = Object.assign({}, instance.get(), values);
662
695
  validateNode(context, null, merged);
663
- return repository.update({
696
+ const result = await repository.update({
664
697
  filterByTk,
665
698
  values,
666
699
  whitelist,
@@ -670,6 +703,8 @@ async function update(context, next) {
670
703
  context,
671
704
  transaction
672
705
  });
706
+ await touchWorkflow(context, instance.workflowId, transaction);
707
+ return result;
673
708
  });
674
709
  await next();
675
710
  }
@@ -12,6 +12,7 @@ export declare class WorkflowValidationError extends Error {
12
12
  errors: Record<string, string>;
13
13
  constructor(errors: Record<string, string>);
14
14
  }
15
+ export declare function list(context: Context, next: any): Promise<void>;
15
16
  export declare function create(context: Context, next: any): Promise<void>;
16
17
  export declare function update(context: Context, next: any): Promise<void>;
17
18
  export declare function destroy(context: Context, next: any): Promise<void>;
@@ -40,6 +40,7 @@ __export(workflows_exports, {
40
40
  create: () => create,
41
41
  destroy: () => destroy,
42
42
  execute: () => execute,
43
+ list: () => list,
43
44
  revision: () => revision,
44
45
  sync: () => sync,
45
46
  update: () => update
@@ -72,9 +73,14 @@ function validateWorkflow(context, plugin, { type, config }) {
72
73
  }
73
74
  }
74
75
  }
76
+ async function list(context, next) {
77
+ return import_actions.default.list(context, next);
78
+ }
75
79
  async function create(context, next) {
76
80
  const plugin = context.app.pm.get(import_Plugin.default);
77
- const { values } = context.action.params;
81
+ const values = { ...context.action.params.values || {} };
82
+ delete values.invalid;
83
+ context.action.mergeParams({ values }, { values: "overwrite" });
78
84
  validateWorkflow(context, plugin, values);
79
85
  return import_actions.default.create(context, next);
80
86
  }
@@ -139,10 +145,12 @@ async function destroy(context, next) {
139
145
  async function revision(context, next) {
140
146
  const repository = import_actions.utils.getRepositoryFromParams(context);
141
147
  const { filterByTk, filter = {}, values = {} } = context.action.params;
148
+ const revisionValues = { ...values };
149
+ delete revisionValues.invalid;
142
150
  context.body = await repository.revision({
143
151
  filterByTk,
144
152
  filter,
145
- values,
153
+ values: revisionValues,
146
154
  context
147
155
  });
148
156
  await next();
@@ -184,6 +192,12 @@ async function execute(context, next) {
184
192
  let processor;
185
193
  try {
186
194
  processor = await plugin.execute(workflow, values, { manually: true });
195
+ if (processor === null) {
196
+ context.body = {
197
+ execution: null
198
+ };
199
+ return next();
200
+ }
187
201
  if (!processor) {
188
202
  return context.throw(400, "workflow not triggered");
189
203
  }
@@ -220,6 +234,7 @@ async function execute(context, next) {
220
234
  create,
221
235
  destroy,
222
236
  execute,
237
+ list,
223
238
  revision,
224
239
  sync,
225
240
  update
@@ -15,6 +15,6 @@ export * from './timeout-errors';
15
15
  export { Trigger } from './triggers';
16
16
  export type { EventOptions } from './Dispatcher';
17
17
  export { default as Processor } from './Processor';
18
- export type { BackgroundAbortHandle, ProcessorOptions } from './Processor';
18
+ export type { BackgroundAbortHandle, ProcessorOptions, ScopeTransaction } from './Processor';
19
19
  export { default } from './Plugin';
20
20
  export * from './types';
@@ -63,9 +63,13 @@ class CreateInstruction extends import__.Instruction {
63
63
  async run(node, input, processor) {
64
64
  const { collection, params: { appends = [], ...params } = {} } = node.config;
65
65
  const [dataSourceName, collectionName] = (0, import_data_source_manager.parseCollectionName)(collection);
66
- const { repository, filterTargetKey } = this.workflow.app.dataSourceManager.dataSources.get(dataSourceName).collectionManager.getCollection(collectionName);
66
+ const dataSource = this.workflow.app.dataSourceManager.dataSources.get(dataSourceName);
67
+ if (!dataSource) {
68
+ throw new Error(`Data source ${dataSourceName} not found`);
69
+ }
70
+ const { repository, filterTargetKey } = dataSource.collectionManager.getCollection(collectionName);
67
71
  const options = processor.getParsedValue(params, node.id);
68
- const transaction = this.workflow.useDataSourceTransaction(dataSourceName, processor.transaction);
72
+ const transaction = processor.getScopeTransaction(node, dataSourceName) ?? this.workflow.useDataSourceTransaction(dataSourceName, processor.transaction);
69
73
  const created = await repository.create({
70
74
  ...options,
71
75
  context: {
@@ -64,12 +64,13 @@ class DestroyInstruction extends import__.Instruction {
64
64
  const [dataSourceName, collectionName] = (0, import_data_source_manager.parseCollectionName)(collection);
65
65
  const { repository } = this.workflow.app.dataSourceManager.dataSources.get(dataSourceName).collectionManager.getCollection(collectionName);
66
66
  const options = processor.getParsedValue(params, node.id);
67
+ const transaction = processor.getScopeTransaction(node, dataSourceName) ?? this.workflow.useDataSourceTransaction(dataSourceName, processor.transaction);
67
68
  const result = await repository.destroy({
68
69
  ...options,
69
70
  context: {
70
71
  stack: Array.from(new Set((processor.execution.stack ?? []).concat(processor.execution.id)))
71
72
  },
72
- transaction: this.workflow.useDataSourceTransaction(dataSourceName, processor.transaction)
73
+ transaction
73
74
  });
74
75
  return {
75
76
  result,
@@ -78,6 +78,7 @@ class QueryInstruction extends import__.Instruction {
78
78
  return set;
79
79
  }, /* @__PURE__ */ new Set())
80
80
  ) : options.appends;
81
+ const transaction = processor.getScopeTransaction(node, dataSourceName) ?? this.workflow.useDataSourceTransaction(dataSourceName, processor.transaction);
81
82
  const result = await (multiple ? repository.find : repository.findOne).call(repository, {
82
83
  ...options,
83
84
  ...import_actions.utils.pageArgsToLimitArgs(page ?? import_actions.DEFAULT_PAGE, pageSize ?? import_actions.DEFAULT_PER_PAGE),
@@ -86,7 +87,7 @@ class QueryInstruction extends import__.Instruction {
86
87
  return `${((_a = item.direction) == null ? void 0 : _a.toLowerCase()) === "desc" ? "-" : ""}${item.field}`;
87
88
  }),
88
89
  appends,
89
- transaction: this.workflow.useDataSourceTransaction(dataSourceName, processor.transaction)
90
+ transaction
90
91
  });
91
92
  if (failOnEmpty && (multiple ? !result.length : !result)) {
92
93
  return {
@@ -66,12 +66,13 @@ class UpdateInstruction extends import__.Instruction {
66
66
  const [dataSourceName, collectionName] = (0, import_data_source_manager.parseCollectionName)(collection);
67
67
  const { repository } = this.workflow.app.dataSourceManager.dataSources.get(dataSourceName).collectionManager.getCollection(collectionName);
68
68
  const options = processor.getParsedValue(params, node.id);
69
+ const transaction = processor.getScopeTransaction(node, dataSourceName) ?? this.workflow.useDataSourceTransaction(dataSourceName, processor.transaction);
69
70
  const result = await repository.update({
70
71
  ...options,
71
72
  context: {
72
73
  stack: Array.from(new Set((processor.execution.stack ?? []).concat(processor.execution.id)))
73
74
  },
74
- transaction: this.workflow.useDataSourceTransaction(dataSourceName, processor.transaction)
75
+ transaction
75
76
  });
76
77
  return {
77
78
  result: result.length ?? result,
@@ -15,6 +15,7 @@ import PluginWorkflowServer from '../Plugin';
15
15
  export interface CollectionChangeTriggerConfig {
16
16
  collection: string;
17
17
  mode: number;
18
+ rollbackOnFailure?: boolean;
18
19
  condition: any;
19
20
  }
20
21
  export default class CollectionTrigger extends Trigger {
@@ -24,8 +25,12 @@ export default class CollectionTrigger extends Trigger {
24
25
  events: Map<any, any>;
25
26
  constructor(workflow: PluginWorkflowServer);
26
27
  private static handler;
28
+ createRollbackOnFailureError(locale?: string): Error & {
29
+ status?: number;
30
+ code?: string;
31
+ };
27
32
  prepare(workflow: WorkflowModel, data: Model | Record<string, any> | string | number, options: any): Promise<{
28
- data: any;
33
+ data: string | number | Record<string, any> | Model<any, any>;
29
34
  }>;
30
35
  on(workflow: WorkflowModel): void;
31
36
  off(workflow: WorkflowModel): void;