@lostgradient/weft 0.3.0 → 0.4.0

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 (508) hide show
  1. package/README.md +79 -24
  2. package/dist/cli/conformance.js +7 -1
  3. package/dist/cli/generated/operation-client.generated.d.ts +28 -13
  4. package/dist/cli/generated/operation-client.generated.js +1 -0
  5. package/dist/cli/help-text.d.ts +1 -1
  6. package/dist/cli/help-text.js +1 -0
  7. package/dist/cli/operation-catalog-snapshot.d.ts +8 -0
  8. package/dist/cli/operation-catalog-snapshot.js +11 -0
  9. package/dist/cli/parse-schedule-arguments.js +3 -1
  10. package/dist/cli/schedule.js +2 -1
  11. package/dist/cli/types.d.ts +1 -0
  12. package/dist/cli-main.js +79 -78
  13. package/dist/client/handle-delegation.d.ts +3 -2
  14. package/dist/client/handle-delegation.js +3 -1
  15. package/dist/client/http-client-requests.d.ts +2 -1
  16. package/dist/client/http-client-requests.js +7 -0
  17. package/dist/client/http-client.d.ts +9 -6
  18. package/dist/client/http-client.js +10 -1
  19. package/dist/client/http-request.d.ts +11 -1
  20. package/dist/client/http-request.js +17 -7
  21. package/dist/client/index.d.ts +1 -1
  22. package/dist/client/interface.d.ts +46 -5
  23. package/dist/client/local.d.ts +4 -1
  24. package/dist/client/local.js +12 -4
  25. package/dist/client/start-body.d.ts +4 -3
  26. package/dist/core/byte-arrays.d.ts +5 -0
  27. package/dist/core/byte-arrays.js +5 -0
  28. package/dist/core/checkpoint/lifecycle.d.ts +3 -0
  29. package/dist/core/checkpoint/lifecycle.js +9 -4
  30. package/dist/core/checkpoint/serialization.js +12 -5
  31. package/dist/core/codec/extension-codec.d.ts +16 -0
  32. package/dist/core/codec/extension-codec.js +100 -6
  33. package/dist/core/context/activity-retry-state.d.ts +38 -0
  34. package/dist/core/context/activity-retry-state.js +89 -0
  35. package/dist/core/context/activity-schedule-to-close.d.ts +159 -0
  36. package/dist/core/context/activity-schedule-to-close.js +69 -0
  37. package/dist/core/context/child-workflow-pipe.d.ts +5 -5
  38. package/dist/core/context/child-workflow-pipe.js +15 -2
  39. package/dist/core/context/context-presence.d.ts +19 -0
  40. package/dist/core/context/context-presence.js +13 -0
  41. package/dist/core/context/durable-operations.d.ts +25 -0
  42. package/dist/core/context/durable-operations.js +64 -0
  43. package/dist/core/context/index.d.ts +9 -5
  44. package/dist/core/context/index.js +17 -12
  45. package/dist/core/context/internals.d.ts +20 -0
  46. package/dist/core/context/internals.js +3 -1
  47. package/dist/core/context/operation-request.d.ts +35 -0
  48. package/dist/core/context/parallel-cache-entry.d.ts +14 -5
  49. package/dist/core/context/run-operation.d.ts +6 -1
  50. package/dist/core/context/run-operation.js +41 -87
  51. package/dist/core/context/session-state.js +7 -8
  52. package/dist/core/context/speculative-child.js +2 -0
  53. package/dist/core/context/types.d.ts +15 -0
  54. package/dist/core/context/version-patching.d.ts +8 -0
  55. package/dist/core/context/version-patching.js +40 -0
  56. package/dist/core/context/workflow-logger.d.ts +98 -0
  57. package/dist/core/context/workflow-logger.js +68 -0
  58. package/dist/core/engine/activity-heartbeat-tracking.d.ts +64 -0
  59. package/dist/core/engine/activity-heartbeat-tracking.js +42 -0
  60. package/dist/core/engine/activity-per-attempt-timeout.d.ts +41 -0
  61. package/dist/core/engine/activity-per-attempt-timeout.js +36 -0
  62. package/dist/core/engine/activity-reconciliation.d.ts +1 -0
  63. package/dist/core/engine/activity-reconciliation.js +12 -1
  64. package/dist/core/engine/activity-resolution.d.ts +23 -0
  65. package/dist/core/engine/activity-resolution.js +37 -0
  66. package/dist/core/engine/aggregate.js +66 -30
  67. package/dist/core/engine/async-activity-completion.d.ts +23 -6
  68. package/dist/core/engine/async-activity-completion.js +53 -12
  69. package/dist/core/engine/attributes-tags.js +9 -4
  70. package/dist/core/engine/bulk-operations-purge.d.ts +26 -0
  71. package/dist/core/engine/bulk-operations-purge.js +38 -3
  72. package/dist/core/engine/bulk-operations-shared.d.ts +2 -0
  73. package/dist/core/engine/bulk-operations-shared.js +8 -2
  74. package/dist/core/engine/bulk-operations.d.ts +4 -1
  75. package/dist/core/engine/bulk-operations.js +235 -24
  76. package/dist/core/engine/callback-creators-bundles.d.ts +9 -0
  77. package/dist/core/engine/callback-creators-bundles.js +30 -2
  78. package/dist/core/engine/callback-creators-core.js +6 -4
  79. package/dist/core/engine/callback-creators-router.js +10 -0
  80. package/dist/core/engine/callback-creators-schedule.d.ts +2 -2
  81. package/dist/core/engine/callback-creators-schedule.js +12 -8
  82. package/dist/core/engine/candidate-read-batching.d.ts +6 -0
  83. package/dist/core/engine/candidate-read-batching.js +1 -0
  84. package/dist/core/engine/checkpoint-io.js +61 -25
  85. package/dist/core/engine/checkpoint-reads.js +3 -2
  86. package/dist/core/engine/checkpoint-replay.d.ts +20 -0
  87. package/dist/core/engine/checkpoint-replay.js +242 -0
  88. package/dist/core/engine/checkpoint-side-effects.d.ts +23 -0
  89. package/dist/core/engine/checkpoint-side-effects.js +35 -0
  90. package/dist/core/engine/child-workflow-cancellation.d.ts +10 -0
  91. package/dist/core/engine/child-workflow-cancellation.js +40 -0
  92. package/dist/core/engine/child-workflow.js +27 -4
  93. package/dist/core/engine/condition-waiters.d.ts +14 -0
  94. package/dist/core/engine/condition-waiters.js +5 -0
  95. package/dist/core/engine/construction.d.ts +3 -0
  96. package/dist/core/engine/construction.js +21 -8
  97. package/dist/core/engine/coordination-branch-executors.d.ts +70 -0
  98. package/dist/core/engine/coordination-branch-executors.js +107 -0
  99. package/dist/core/engine/deferred-consume-envelope.d.ts +59 -0
  100. package/dist/core/engine/deferred-consume-envelope.js +14 -0
  101. package/dist/core/engine/disposal.js +13 -0
  102. package/dist/core/engine/engine-create-types.d.ts +14 -4
  103. package/dist/core/engine/engine-internal-types.d.ts +26 -3
  104. package/dist/core/engine/errors.d.ts +47 -0
  105. package/dist/core/engine/errors.js +20 -0
  106. package/dist/core/engine/event-log-compaction.d.ts +8 -0
  107. package/dist/core/engine/event-log-compaction.js +20 -2
  108. package/dist/core/engine/fenced-write.d.ts +65 -0
  109. package/dist/core/engine/fenced-write.js +71 -0
  110. package/dist/core/engine/finalizer-state.d.ts +28 -0
  111. package/dist/core/engine/finalizer-state.js +16 -0
  112. package/dist/core/engine/handles.d.ts +8 -0
  113. package/dist/core/engine/index.d.ts +34 -16
  114. package/dist/core/engine/index.js +133 -8
  115. package/dist/core/engine/inline-parking.js +3 -2
  116. package/dist/core/engine/internals.d.ts +107 -3
  117. package/dist/core/engine/lease-codec.d.ts +35 -0
  118. package/dist/core/engine/lease-codec.js +32 -0
  119. package/dist/core/engine/lease-deposition.d.ts +66 -0
  120. package/dist/core/engine/lease-deposition.js +10 -0
  121. package/dist/core/engine/lease-errors.d.ts +99 -0
  122. package/dist/core/engine/lease-errors.js +30 -0
  123. package/dist/core/engine/lease-manager.d.ts +114 -0
  124. package/dist/core/engine/lease-manager.js +135 -0
  125. package/dist/core/engine/lifecycle/persist.js +10 -32
  126. package/dist/core/engine/lifecycle/recovered-services.d.ts +8 -6
  127. package/dist/core/engine/lifecycle/recovered-services.js +18 -3
  128. package/dist/core/engine/lifecycle/resume.js +16 -9
  129. package/dist/core/engine/lifecycle/shared.d.ts +8 -1
  130. package/dist/core/engine/lifecycle/start-batch.d.ts +1 -1
  131. package/dist/core/engine/lifecycle/start-batch.js +2 -1
  132. package/dist/core/engine/lifecycle/start-commit.d.ts +9 -0
  133. package/dist/core/engine/lifecycle/start-commit.js +50 -8
  134. package/dist/core/engine/lifecycle/start-or-signal-create.d.ts +58 -0
  135. package/dist/core/engine/lifecycle/start-or-signal-create.js +95 -0
  136. package/dist/core/engine/lifecycle/start-or-signal.d.ts +3 -2
  137. package/dist/core/engine/lifecycle/start-or-signal.js +11 -81
  138. package/dist/core/engine/lifecycle/start-terminal-conflict-purge.d.ts +39 -0
  139. package/dist/core/engine/lifecycle/start-terminal-conflict-purge.js +28 -0
  140. package/dist/core/engine/lifecycle/start.d.ts +4 -4
  141. package/dist/core/engine/lifecycle/start.js +17 -9
  142. package/dist/core/engine/lifecycle/transition.js +17 -5
  143. package/dist/core/engine/lifecycle.d.ts +1 -1
  144. package/dist/core/engine/list-candidate-resolution.js +2 -2
  145. package/dist/core/engine/listing.js +9 -5
  146. package/dist/core/engine/operations-activity.d.ts +4 -11
  147. package/dist/core/engine/operations-activity.js +22 -49
  148. package/dist/core/engine/operations-coordination.d.ts +10 -0
  149. package/dist/core/engine/operations-coordination.js +43 -8
  150. package/dist/core/engine/operations-router.d.ts +6 -0
  151. package/dist/core/engine/operations-router.js +2 -0
  152. package/dist/core/engine/operations-speculate.js +6 -2
  153. package/dist/core/engine/operations-stream.js +12 -2
  154. package/dist/core/engine/operations-time.d.ts +4 -2
  155. package/dist/core/engine/operations-time.js +14 -2
  156. package/dist/core/engine/operations-wait-condition.d.ts +23 -0
  157. package/dist/core/engine/operations-wait-condition.js +62 -0
  158. package/dist/core/engine/ownership-options.d.ts +23 -0
  159. package/dist/core/engine/ownership-options.js +26 -0
  160. package/dist/core/engine/payload-size-policy.d.ts +3 -0
  161. package/dist/core/engine/payload-size-policy.js +4 -0
  162. package/dist/core/engine/pending-updates.d.ts +17 -0
  163. package/dist/core/engine/pending-updates.js +33 -11
  164. package/dist/core/engine/queries.js +1 -1
  165. package/dist/core/engine/registration.d.ts +1 -0
  166. package/dist/core/engine/registration.js +18 -3
  167. package/dist/core/engine/schedule-jitter.d.ts +5 -0
  168. package/dist/core/engine/schedule-jitter.js +10 -0
  169. package/dist/core/engine/schedule-run.d.ts +17 -0
  170. package/dist/core/engine/schedule-run.js +38 -0
  171. package/dist/core/engine/schedule-timer.js +81 -17
  172. package/dist/core/engine/schedules.d.ts +7 -4
  173. package/dist/core/engine/schedules.js +37 -16
  174. package/dist/core/engine/search-attribute-records.d.ts +4 -0
  175. package/dist/core/engine/search-attribute-records.js +17 -0
  176. package/dist/core/engine/signals.d.ts +18 -2
  177. package/dist/core/engine/signals.js +42 -21
  178. package/dist/core/engine/state-utilities.d.ts +49 -2
  179. package/dist/core/engine/state-utilities.js +114 -3
  180. package/dist/core/engine/storage-io.d.ts +16 -2
  181. package/dist/core/engine/storage-io.js +26 -5
  182. package/dist/core/engine/stream-chunk-loading.d.ts +2 -0
  183. package/dist/core/engine/stream-chunk-loading.js +24 -1
  184. package/dist/core/engine/sub-operation.js +22 -3
  185. package/dist/core/engine/termination/cleanup.d.ts +3 -1
  186. package/dist/core/engine/termination/cleanup.js +25 -1
  187. package/dist/core/engine/termination/complete.js +44 -6
  188. package/dist/core/engine/termination/finalizer-activity.d.ts +53 -0
  189. package/dist/core/engine/termination/finalizer-activity.js +30 -0
  190. package/dist/core/engine/termination/finalizer-claim.d.ts +110 -0
  191. package/dist/core/engine/termination/finalizer-claim.js +80 -0
  192. package/dist/core/engine/termination/finalizer.d.ts +48 -0
  193. package/dist/core/engine/termination/finalizer.js +159 -0
  194. package/dist/core/engine/termination/suspend.d.ts +3 -1
  195. package/dist/core/engine/termination.d.ts +1 -0
  196. package/dist/core/engine/termination.js +4 -0
  197. package/dist/core/engine/updates.js +5 -25
  198. package/dist/core/engine/validation/schedule.d.ts +2 -1
  199. package/dist/core/engine/validation/schedule.js +51 -2
  200. package/dist/core/engine/validation.js +32 -5
  201. package/dist/core/engine/waiting-update-response.d.ts +8 -0
  202. package/dist/core/engine/waiting-update-response.js +22 -0
  203. package/dist/core/engine/workflow-concurrency.d.ts +10 -0
  204. package/dist/core/engine/workflow-concurrency.js +136 -0
  205. package/dist/core/engine/workflow-feed.d.ts +4 -5
  206. package/dist/core/engine/workflow-feed.js +4 -1
  207. package/dist/core/engine/workflow-indexes.d.ts +9 -0
  208. package/dist/core/engine/workflow-indexes.js +10 -0
  209. package/dist/core/engine/workflow-state-stream.js +33 -13
  210. package/dist/core/engine/workflow-visibility-queries.d.ts +2 -2
  211. package/dist/core/engine-helpers.js +1 -0
  212. package/dist/core/events/activity-events.d.ts +43 -12
  213. package/dist/core/events/activity-events.js +28 -0
  214. package/dist/core/events/attribute-events.d.ts +2 -3
  215. package/dist/core/events/event-map.d.ts +18 -12
  216. package/dist/core/events/index.d.ts +1 -0
  217. package/dist/core/events/index.js +1 -0
  218. package/dist/core/events/schedule-events.d.ts +71 -0
  219. package/dist/core/events/schedule-events.js +29 -0
  220. package/dist/core/events/signal-events.d.ts +4 -6
  221. package/dist/core/events/system-events.d.ts +29 -19
  222. package/dist/core/events/system-events.js +26 -0
  223. package/dist/core/events/update-events.d.ts +6 -8
  224. package/dist/core/events/workflow-events.d.ts +88 -23
  225. package/dist/core/events/workflow-events.js +26 -0
  226. package/dist/core/failure-categories.js +5 -17
  227. package/dist/core/fault-code.d.ts +9 -3
  228. package/dist/core/fault-code.js +1 -0
  229. package/dist/core/inline-execution-strategy.context-options.d.ts +69 -0
  230. package/dist/core/inline-execution-strategy.context-options.js +56 -0
  231. package/dist/core/inline-execution-strategy.d.ts +31 -36
  232. package/dist/core/inline-execution-strategy.js +16 -27
  233. package/dist/core/list-filter-validation.d.ts +1 -1
  234. package/dist/core/payload-size.d.ts +1 -1
  235. package/dist/core/persisted-data-incompatible-error.d.ts +9 -7
  236. package/dist/core/review/events.d.ts +6 -8
  237. package/dist/core/scheduler/scheduler-class.d.ts +10 -1
  238. package/dist/core/scheduler/scheduler-class.js +38 -11
  239. package/dist/core/scheduler/timer-batch.js +9 -1
  240. package/dist/core/scheduler/timer-sources.d.ts +1 -0
  241. package/dist/core/scheduler/timer-sources.js +11 -5
  242. package/dist/core/session-state.d.ts +0 -1
  243. package/dist/core/session-state.js +2 -2
  244. package/dist/core/start-workflow-validation.d.ts +34 -0
  245. package/dist/core/start-workflow-validation.js +19 -0
  246. package/dist/core/types/activity-verification.d.ts +67 -0
  247. package/dist/core/types/activity-verification.js +0 -0
  248. package/dist/core/types/activity.d.ts +80 -61
  249. package/dist/core/types/bulk.d.ts +50 -9
  250. package/dist/core/types/checkpoint.d.ts +44 -8
  251. package/dist/core/types/list-options.d.ts +146 -0
  252. package/dist/core/types/list-options.js +0 -0
  253. package/dist/core/types/options.d.ts +121 -165
  254. package/dist/core/types/schedules.d.ts +39 -3
  255. package/dist/core/types/services-resolution.d.ts +2 -2
  256. package/dist/core/types/workflow-builder-runtime.d.ts +12 -3
  257. package/dist/core/types/workflow-builder-runtime.js +11 -2
  258. package/dist/core/types/workflow-builder.d.ts +42 -11
  259. package/dist/core/types/workflow-concurrency.d.ts +39 -0
  260. package/dist/core/types/workflow-concurrency.js +0 -0
  261. package/dist/core/types/workflow-context.d.ts +157 -14
  262. package/dist/core/types/workflow-definition.d.ts +53 -10
  263. package/dist/core/types/workflow-function.d.ts +84 -9
  264. package/dist/core/types/workflow-log.d.ts +98 -0
  265. package/dist/core/types/workflow-log.js +0 -0
  266. package/dist/core/types/workflow-registries.d.ts +14 -3
  267. package/dist/core/types/workflow-registry.d.ts +3 -0
  268. package/dist/core/types.d.ts +4 -0
  269. package/dist/core/types.js +4 -0
  270. package/dist/core/versioning.d.ts +9 -39
  271. package/dist/core/versioning.js +2 -12
  272. package/dist/core/weft-error.d.ts +44 -1
  273. package/dist/core/weft-error.js +16 -0
  274. package/dist/core/worker-execution-strategy-options.d.ts +26 -0
  275. package/dist/core/worker-execution-strategy.js +40 -36
  276. package/dist/core/worker-inbound-message.d.ts +38 -0
  277. package/dist/core/worker-inbound-message.js +37 -0
  278. package/dist/core/worker-log-abuse-counter.d.ts +175 -0
  279. package/dist/core/worker-log-abuse-counter.js +107 -0
  280. package/dist/core/worker-message-helpers.d.ts +47 -0
  281. package/dist/core/worker-message-helpers.js +26 -0
  282. package/dist/core/worker-protocol-guard.js +1 -1
  283. package/dist/core/worker-protocol-log.d.ts +56 -0
  284. package/dist/core/worker-protocol-log.js +18 -0
  285. package/dist/core/worker-protocol.d.ts +23 -0
  286. package/dist/core/worker-protocol.js +12 -2
  287. package/dist/core/workflow-version-tuple.d.ts +3 -9
  288. package/dist/core/workflow-version-tuple.js +2 -3
  289. package/dist/diagnostics/format.js +1 -6
  290. package/dist/diagnostics/types.d.ts +4 -5
  291. package/dist/diagnostics/validate.d.ts +0 -1
  292. package/dist/diagnostics/version-check.d.ts +1 -1
  293. package/dist/diagnostics/version-check.js +4 -9
  294. package/dist/index.d.ts +12 -10
  295. package/dist/index.js +29 -3
  296. package/dist/json-schema.js +3 -3
  297. package/dist/mcp/cli.js +27 -27
  298. package/dist/mcp/dispatcher.js +1 -1
  299. package/dist/mcp/http.js +16 -6
  300. package/dist/mcp/protocol.d.ts +2 -0
  301. package/dist/mcp/protocol.js +1 -1
  302. package/dist/mcp/session.d.ts +16 -0
  303. package/dist/mcp/session.js +59 -6
  304. package/dist/mcp/tools.js +73 -6
  305. package/dist/observability/index.js +2 -2
  306. package/dist/server/asyncapi-channels.js +5 -2
  307. package/dist/server/attribute-filters.d.ts +8 -3
  308. package/dist/server/attribute-filters.js +6 -1
  309. package/dist/server/authentication/api-key.d.ts +2 -1
  310. package/dist/server/authentication/api-key.js +5 -2
  311. package/dist/server/authentication/constant-time-api-key.d.ts +15 -0
  312. package/dist/server/authentication/constant-time-api-key.js +24 -0
  313. package/dist/server/authentication/index.d.ts +1 -1
  314. package/dist/server/authentication/index.js +7 -4
  315. package/dist/server/authentication/rotating-api-key-store.d.ts +5 -3
  316. package/dist/server/authentication/rotating-api-key-store.js +19 -11
  317. package/dist/server/engine-event-feed-backend.d.ts +4 -5
  318. package/dist/server/fault-to-http.js +8 -1
  319. package/dist/server/fault-to-json-rpc.js +1 -0
  320. package/dist/server/fleet-event-feed.d.ts +31 -0
  321. package/dist/server/fleet-event-feed.js +157 -0
  322. package/dist/server/handler/index.js +1 -1
  323. package/dist/server/handler/response-helpers.js +2 -1
  324. package/dist/server/handler/route-dispatch.d.ts +6 -3
  325. package/dist/server/handler/route-dispatch.js +2 -2
  326. package/dist/server/handler.js +23 -23
  327. package/dist/server/index.d.ts +32 -2
  328. package/dist/server/index.js +26 -26
  329. package/dist/server/json-rpc-transport-helpers.d.ts +1 -0
  330. package/dist/server/json-rpc-transport-helpers.js +2 -1
  331. package/dist/server/json-rpc-websocket-runtime.d.ts +11 -2
  332. package/dist/server/json-rpc-websocket-runtime.js +1 -0
  333. package/dist/server/json-rpc-websocket-subscriptions.d.ts +10 -0
  334. package/dist/server/json-rpc-websocket-subscriptions.js +29 -0
  335. package/dist/server/json-rpc-websocket-types.d.ts +22 -0
  336. package/dist/server/json-rpc-websocket-types.js +0 -0
  337. package/dist/server/json-rpc-websocket-validation.js +20 -4
  338. package/dist/server/json-rpc-websocket.d.ts +2 -43
  339. package/dist/server/json-rpc-websocket.js +57 -74
  340. package/dist/server/openapi.d.ts +2 -1
  341. package/dist/server/openapi.js +1 -3
  342. package/dist/server/openrpc-document-schema.d.ts +78 -0
  343. package/dist/server/openrpc-document-schema.js +27 -1
  344. package/dist/server/openrpc-errors.d.ts +3 -0
  345. package/dist/server/openrpc-errors.js +2 -1
  346. package/dist/server/openrpc.js +32 -0
  347. package/dist/server/operation-catalog/index.d.ts +1 -1
  348. package/dist/server/operation-catalog/pipeline-helpers.js +1 -0
  349. package/dist/server/operation-catalog/pipeline-stages.js +26 -12
  350. package/dist/server/operation-catalog/pipeline.js +8 -1
  351. package/dist/server/operation-catalog/registry.js +13 -0
  352. package/dist/server/operation-catalog/types.d.ts +20 -9
  353. package/dist/server/operation-fault.d.ts +10 -0
  354. package/dist/server/operation-fault.js +2 -0
  355. package/dist/server/operation-registry.d.ts +12 -11
  356. package/dist/server/operation-registry.js +12 -3
  357. package/dist/server/operations/aggregate-workflows.d.ts +15 -15
  358. package/dist/server/operations/async-activity.d.ts +2 -2
  359. package/dist/server/operations/async-activity.js +12 -7
  360. package/dist/server/operations/bulk-cancel-workflows.d.ts +1 -1
  361. package/dist/server/operations/bulk-cancel-workflows.js +2 -2
  362. package/dist/server/operations/bulk-delete-workflows.d.ts +1 -1
  363. package/dist/server/operations/bulk-delete-workflows.js +2 -2
  364. package/dist/server/operations/bulk-filter-helpers.d.ts +8 -6
  365. package/dist/server/operations/bulk-filter-helpers.js +54 -24
  366. package/dist/server/operations/bulk-mutate-workflow-tags.d.ts +11 -9
  367. package/dist/server/operations/bulk-mutate-workflow-tags.js +2 -2
  368. package/dist/server/operations/bulk-operation-helpers.d.ts +2 -2
  369. package/dist/server/operations/bulk-retry-failed-workflows.d.ts +7 -0
  370. package/dist/server/operations/bulk-retry-failed-workflows.js +64 -0
  371. package/dist/server/operations/bulk-signal-workflows.d.ts +11 -9
  372. package/dist/server/operations/bulk-signal-workflows.js +2 -2
  373. package/dist/server/operations/cancel-schedule.d.ts +1 -1
  374. package/dist/server/operations/create-schedule.d.ts +3 -1
  375. package/dist/server/operations/create-schedule.js +29 -11
  376. package/dist/server/operations/fleet-events-subscription.d.ts +54 -0
  377. package/dist/server/operations/fleet-events-subscription.js +99 -0
  378. package/dist/server/operations/fork-workflow.d.ts +1 -1
  379. package/dist/server/operations/fork-workflow.js +3 -2
  380. package/dist/server/operations/get-checkpoint-at.d.ts +1 -1
  381. package/dist/server/operations/get-registry.d.ts +1 -1
  382. package/dist/server/operations/get-retention-overview.d.ts +1 -1
  383. package/dist/server/operations/get-review.d.ts +1 -1
  384. package/dist/server/operations/get-schedule.d.ts +1 -1
  385. package/dist/server/operations/get-stream-chunks.d.ts +1 -1
  386. package/dist/server/operations/get-system-metrics.d.ts +2 -2
  387. package/dist/server/operations/get-task-diagnostics.d.ts +45 -6
  388. package/dist/server/operations/get-task-diagnostics.js +101 -7
  389. package/dist/server/operations/get-update-result.d.ts +1 -1
  390. package/dist/server/operations/get-workflow-attributes.d.ts +1 -1
  391. package/dist/server/operations/get-workflow-events.d.ts +1 -1
  392. package/dist/server/operations/get-workflow-result.d.ts +1 -1
  393. package/dist/server/operations/get-workflow-timeline.d.ts +1 -1
  394. package/dist/server/operations/get-workflow.d.ts +1 -1
  395. package/dist/server/operations/list-checkpoints.d.ts +1 -1
  396. package/dist/server/operations/list-reviews.d.ts +1 -1
  397. package/dist/server/operations/list-schedules.d.ts +1 -1
  398. package/dist/server/operations/list-task-queues.d.ts +2 -2
  399. package/dist/server/operations/list-workers.d.ts +2 -2
  400. package/dist/server/operations/list-workflows.d.ts +1 -1
  401. package/dist/server/operations/operation-helpers.d.ts +16 -1
  402. package/dist/server/operations/operation-helpers.js +15 -3
  403. package/dist/server/operations/pause-schedule.d.ts +1 -1
  404. package/dist/server/operations/purge-workflows.d.ts +5 -5
  405. package/dist/server/operations/purge-workflows.js +2 -2
  406. package/dist/server/operations/query-workflow.d.ts +1 -1
  407. package/dist/server/operations/query-workflow.js +3 -2
  408. package/dist/server/operations/recover-all.d.ts +1 -1
  409. package/dist/server/operations/replay-workflow.d.ts +1 -1
  410. package/dist/server/operations/resume-schedule.d.ts +1 -1
  411. package/dist/server/operations/set-workflow-attributes.d.ts +1 -1
  412. package/dist/server/operations/set-workflow-attributes.js +6 -3
  413. package/dist/server/operations/signal-workflow.js +8 -3
  414. package/dist/server/operations/single-workflow-tag-mutation.js +13 -3
  415. package/dist/server/operations/start-or-signal-workflow.d.ts +6 -1
  416. package/dist/server/operations/start-or-signal-workflow.js +14 -24
  417. package/dist/server/operations/start-workflow-options.d.ts +6 -0
  418. package/dist/server/operations/start-workflow-rest-input.d.ts +14 -0
  419. package/dist/server/operations/start-workflow-rest-input.js +31 -0
  420. package/dist/server/operations/start-workflow.d.ts +1 -1
  421. package/dist/server/operations/start-workflow.js +8 -23
  422. package/dist/server/operations/storage.d.ts +6 -6
  423. package/dist/server/operations/storage.js +24 -14
  424. package/dist/server/operations/stream-workflow-sse.d.ts +1 -1
  425. package/dist/server/operations/submit-review-decision.d.ts +1 -1
  426. package/dist/server/operations/submit-review-decision.js +6 -3
  427. package/dist/server/operations/update-schedule.d.ts +1 -1
  428. package/dist/server/operations/update-schedule.js +7 -4
  429. package/dist/server/operations/update-workflow.d.ts +1 -1
  430. package/dist/server/operations/update-workflow.js +7 -3
  431. package/dist/server/operations/worker-drain.d.ts +8 -8
  432. package/dist/server/operations/worker-drain.js +11 -8
  433. package/dist/server/operations/workflow-events-subscription.d.ts +7 -8
  434. package/dist/server/operations/workflow-events-subscription.js +43 -8
  435. package/dist/server/rest-binding.d.ts +3 -1
  436. package/dist/server/rest-bindings.js +12 -0
  437. package/dist/server/rest-body.d.ts +10 -0
  438. package/dist/server/rest-body.js +80 -0
  439. package/dist/server/runtime/authentication-bridge.d.ts +1 -0
  440. package/dist/server/runtime/authentication-bridge.js +33 -6
  441. package/dist/server/runtime/client-visible-events.d.ts +3 -0
  442. package/dist/server/runtime/client-visible-events.js +65 -0
  443. package/dist/server/runtime/context.d.ts +7 -0
  444. package/dist/server/runtime/event-broadcasting.d.ts +6 -0
  445. package/dist/server/runtime/event-broadcasting.js +72 -38
  446. package/dist/server/runtime/retry.d.ts +1 -0
  447. package/dist/server/runtime/retry.js +14 -0
  448. package/dist/server/runtime/shutdown.d.ts +7 -6
  449. package/dist/server/runtime/shutdown.js +6 -1
  450. package/dist/server/runtime/task-polling.js +61 -20
  451. package/dist/server/runtime/task-reconciliation.js +9 -1
  452. package/dist/server/runtime/task-result-resolution.d.ts +15 -0
  453. package/dist/server/runtime/task-result-resolution.js +81 -0
  454. package/dist/server/runtime/websocket-stream.d.ts +20 -1
  455. package/dist/server/runtime/websocket-stream.js +173 -7
  456. package/dist/server/runtime/websocket-upgrade.js +22 -3
  457. package/dist/server/runtime/websocket-worker.d.ts +1 -1
  458. package/dist/server/runtime/websocket-worker.js +38 -30
  459. package/dist/server/serve-internals.d.ts +3 -1
  460. package/dist/server/serve-internals.js +18 -2
  461. package/dist/server/task-state.d.ts +30 -0
  462. package/dist/server/task-state.js +28 -0
  463. package/dist/server/workflow-event-feed.d.ts +36 -115
  464. package/dist/server/workflow-event-feed.js +92 -27
  465. package/dist/service-worker/index.js +30 -30
  466. package/dist/storage/auto.js +1 -1
  467. package/dist/storage/bun-sql.js +24 -0
  468. package/dist/storage/compressed-storage.js +1 -1
  469. package/dist/storage/default-scope.d.ts +7 -4
  470. package/dist/storage/http.js +2 -2
  471. package/dist/storage/index.d.ts +76 -4
  472. package/dist/storage/indexeddb.js +1 -1
  473. package/dist/storage/interface.d.ts +163 -0
  474. package/dist/storage/interface.js +1 -1
  475. package/dist/storage/key-prefixes.d.ts +1 -1
  476. package/dist/storage/key-prefixes.js +10 -0
  477. package/dist/storage/lmdb.d.ts +4 -3
  478. package/dist/storage/lmdb.js +1 -1
  479. package/dist/storage/memory.js +1 -1
  480. package/dist/storage/neon-batch.d.ts +30 -0
  481. package/dist/storage/neon-batch.js +30 -0
  482. package/dist/storage/neon-value-mapping.d.ts +30 -3
  483. package/dist/storage/neon-value-mapping.js +12 -0
  484. package/dist/storage/neon.d.ts +16 -0
  485. package/dist/storage/neon.js +9 -4
  486. package/dist/storage/node-sqlite.js +23 -0
  487. package/dist/storage/postgres-key-value-queries.d.ts +69 -44
  488. package/dist/storage/postgres-key-value-queries.js +62 -24
  489. package/dist/storage/resolve.js +1 -1
  490. package/dist/storage/scoped-storage.js +1 -1
  491. package/dist/storage/testing.d.ts +168 -0
  492. package/dist/storage/testing.js +2 -0
  493. package/dist/storage/turso.d.ts +8 -0
  494. package/dist/storage/turso.js +2 -2
  495. package/dist/storage/typed-storage.js +1 -1
  496. package/dist/storage/web-extension.js +1 -1
  497. package/dist/testing/index.js +28 -28
  498. package/dist/version.d.ts +1 -1
  499. package/dist/version.js +1 -1
  500. package/dist/worker/protocol.js +1 -1
  501. package/dist/workers/worker-replay-state.d.ts +32 -0
  502. package/dist/workers/worker-replay-state.js +35 -0
  503. package/dist/workers/worker-state-namespace.d.ts +21 -0
  504. package/dist/workers/worker-state-namespace.js +13 -0
  505. package/dist/workers/workflow-runner.d.ts +19 -15
  506. package/dist/workers/workflow-runner.js +72 -60
  507. package/dist/workers/workflow-worker-entry.js +5 -2
  508. package/package.json +5 -1
@@ -1,4 +1,4 @@
1
- import { KEYS, storageConditionalBatch } from "../../storage/interface.js";
1
+ import { KEYS } from "../../storage/interface.js";
2
2
  import {
3
3
  advanceCheckpoint,
4
4
  deserializeCheckpoint,
@@ -6,6 +6,7 @@ import {
6
6
  validateCheckpointRoundTrip
7
7
  } from "../checkpoint.js";
8
8
  import { encode } from "../codec.js";
9
+ import { hasPendingAttributeChanges } from "../context/context-presence.js";
9
10
  import { EMPTY_EVENT_HEAD, EventLog } from "../event-log.js";
10
11
  import {
11
12
  AttributesChangedEvent,
@@ -17,10 +18,22 @@ import {
17
18
  getCommittedCheckpointBytes,
18
19
  rememberCommittedCheckpointBytes
19
20
  } from "./checkpoint-commit-snapshots.js";
21
+ import {
22
+ attachTransientCheckpointReplayPayload,
23
+ createCheckpointEventPayload,
24
+ mergeCheckpointReplayPayloads,
25
+ pruneCheckpointReplayState,
26
+ readCheckpointReplayPayload
27
+ } from "./checkpoint-replay.js";
28
+ import {
29
+ clearPendingAtomicWorkflowCommitSideEffects,
30
+ takePendingAtomicWorkflowCommitSideEffects
31
+ } from "./checkpoint-side-effects.js";
20
32
  import {
21
33
  appendCompactionOperations,
22
34
  serializeDeletedEntries
23
35
  } from "./event-log-compaction.js";
36
+ import { commitFencedEngineWrite } from "./fenced-write.js";
24
37
  import { getTimelineInputSummary, getTimelineOperationLabel } from "./state-utilities.js";
25
38
  import { buildPendingTimelineOperation } from "./termination.js";
26
39
  import { notifyWorkflowFeedCommit } from "./workflow-feed.js";
@@ -57,21 +70,21 @@ async function persistInlineCheckpoint(internals, workflowId, operation, callbac
57
70
  const current = internals.checkpoints.get(workflowId), context = internals.inlineStrategy?.getContext(workflowId);
58
71
  if (!current || !context)
59
72
  return;
60
- const previousAttributes = { ...current.searchAttributes }, pendingAttributeChanges = context.checkpointPendingAttributeChanges, hasPendingAttributeChanges = context.hasPendingAttributeChanges, advanced = advanceCheckpoint(current, context.checkpointLocals, {
73
+ const previousAttributes = { ...current.searchAttributes }, pendingAttributeChanges = context.checkpointPendingAttributeChanges, hasPendingAttributeChangesValue = hasPendingAttributeChanges(context), advanced = advanceCheckpoint(current, context.checkpointLocals, {
61
74
  accumulatedResults: context.checkpointAccumulatedResults,
62
75
  now: internals.options.getNow(),
63
76
  ...pendingAttributeChanges !== void 0 ? { searchAttributes: pendingAttributeChanges } : {}
64
- }), commit = createCheckpointCommit(internals, workflowId, advanced, serializeCheckpoint(advanced));
65
- appendAttributeOperations(workflowId, commit, previousAttributes, pendingAttributeChanges, hasPendingAttributeChanges, callbacks);
77
+ }), pruned = pruneCheckpointReplayState(advanced, resolvePendingOperationStep(operation, context.stepIndex)), commit = createCheckpointCommit(internals, workflowId, pruned.checkpoint, serializeCheckpoint(attachTransientCheckpointReplayPayload(pruned.checkpoint, pruned.replayPayload)), pruned.replayPayload);
78
+ appendAttributeOperations(workflowId, commit, previousAttributes, pendingAttributeChanges, hasPendingAttributeChangesValue, callbacks);
66
79
  await commitCheckpoint(internals, workflowId, operation, commit, callbacks);
67
- if (hasPendingAttributeChanges)
80
+ if (hasPendingAttributeChangesValue)
68
81
  callbacks.dispatchEvent(new AttributesChangedEvent(workflowId, { ...pendingAttributeChanges }));
69
82
  }
70
83
  async function persistWorkerCheckpoint(internals, workflowId, operation, workerCheckpointBytes, callbacks) {
71
- const serialized = new Uint8Array(workerCheckpointBytes), checkpoint = deserializeCheckpoint(serialized);
72
- await commitCheckpoint(internals, workflowId, operation, createCheckpointCommit(internals, workflowId, checkpoint, serialized), callbacks);
84
+ const serialized = new Uint8Array(workerCheckpointBytes), checkpoint = deserializeCheckpoint(serialized), workerReplayPayload = readCheckpointReplayPayload(checkpoint), pruned = pruneCheckpointReplayState(checkpoint, resolvePendingOperationStep(operation, checkpoint.step)), replayPayload = mergeCheckpointReplayPayloads(workerReplayPayload, pruned.replayPayload), prunedSerialized = serializeCheckpoint(attachTransientCheckpointReplayPayload(pruned.checkpoint, replayPayload));
85
+ await commitCheckpoint(internals, workflowId, operation, createCheckpointCommit(internals, workflowId, pruned.checkpoint, prunedSerialized, replayPayload), callbacks);
73
86
  }
74
- function createCheckpointCommit(internals, workflowId, checkpoint, serialized) {
87
+ function createCheckpointCommit(internals, workflowId, checkpoint, serialized, replayPayload) {
75
88
  const operations = [
76
89
  { type: "put", key: KEYS.checkpoint(workflowId), value: serialized }
77
90
  ];
@@ -85,14 +98,15 @@ function createCheckpointCommit(internals, workflowId, checkpoint, serialized) {
85
98
  return {
86
99
  checkpoint,
87
100
  serialized,
101
+ ...replayPayload === void 0 ? {} : { replayPayload },
88
102
  ...expectedSerialized !== void 0 ? { expectedSerialized } : {},
89
103
  step: checkpoint.step,
90
104
  timestamp: checkpoint.createdAt,
91
105
  operations
92
106
  };
93
107
  }
94
- function appendAttributeOperations(workflowId, commit, previousAttributes, pendingAttributeChanges, hasPendingAttributeChanges, callbacks) {
95
- if (!hasPendingAttributeChanges)
108
+ function appendAttributeOperations(workflowId, commit, previousAttributes, pendingAttributeChanges, hasPendingAttributeChangesValue, callbacks) {
109
+ if (!hasPendingAttributeChangesValue)
96
110
  return;
97
111
  callbacks.validateAttributeValueSizes(pendingAttributeChanges ?? {});
98
112
  commit.operations.push({
@@ -104,11 +118,15 @@ function appendAttributeOperations(workflowId, commit, previousAttributes, pendi
104
118
  }
105
119
  async function commitCheckpoint(internals, workflowId, operation, commit, callbacks) {
106
120
  dispatchCheckpointSizeWarning(internals, workflowId, commit, callbacks);
107
- const nextPendingTimelineEntry = callbacks.appendTimelineBatchOperations(workflowId, operation, commit.step, commit.timestamp, commit.operations), { newHead, timestamp } = appendCheckpointEventLog(internals, workflowId, commit), retentionWindow = internals.options.historyPolicy.retentionWindow, compaction = retentionWindow === null ? null : await appendCompactionOperations(internals.storage, workflowId, newHead.sequence, retentionWindow, commit.operations);
108
- if (commit.expectedSerialized === void 0 || !internals.storage.capabilities().conditionalBatch)
109
- await internals.storage.batch(commit.operations);
110
- else
111
- await writeCheckpointCommitBatch(internals, workflowId, commit, commit.expectedSerialized);
121
+ const nextPendingTimelineEntry = callbacks.appendTimelineBatchOperations(workflowId, operation, commit.step, commit.timestamp, commit.operations), { newHead, timestamp } = appendCheckpointEventLog(internals, workflowId, commit), retentionWindow = internals.options.historyPolicy.retentionWindow, compaction = retentionWindow === null ? null : await appendCompactionOperations(internals.storage, workflowId, newHead.sequence, retentionWindow, commit.operations), pendingSideEffects = takePendingAtomicWorkflowCommitSideEffects(internals, workflowId);
122
+ if (pendingSideEffects !== void 0)
123
+ commit.operations.push(...pendingSideEffects.operations);
124
+ const storageSupportsConditionalBatch = internals.storage.capabilities().conditionalBatch, sideEffectConditions = checkpointSideEffectConditions(pendingSideEffects, storageSupportsConditionalBatch), conditions = buildCheckpointCommitConditions(workflowId, commit, storageSupportsConditionalBatch, sideEffectConditions);
125
+ await commitFencedEngineWrite(internals, commit.operations, conditions, () => {
126
+ return Error(`Checkpoint commit for workflow "${workflowId}" lost its CAS race against a newer checkpoint.`);
127
+ });
128
+ if (pendingSideEffects !== void 0)
129
+ clearPendingAtomicWorkflowCommitSideEffects(internals, workflowId);
112
130
  if (commit.expectedSerialized !== void 0)
113
131
  rememberCommittedCheckpointBytes(internals, workflowId, commit.serialized);
114
132
  internals.pendingTimelineEntries.set(workflowId, nextPendingTimelineEntry);
@@ -128,15 +146,20 @@ async function commitCheckpoint(internals, workflowId, operation, commit, callba
128
146
  if (historyEventLimitBreached(internals, newHead.sequence))
129
147
  await callbacks.enforceHistoryCircuitBreaker(workflowId);
130
148
  }
131
- async function writeCheckpointCommitBatch(internals, workflowId, commit, expectedSerialized) {
132
- const conditions = [
133
- {
149
+ function checkpointSideEffectConditions(pendingSideEffects, storageSupportsConditionalBatch) {
150
+ if (!storageSupportsConditionalBatch)
151
+ return [];
152
+ return pendingSideEffects?.conditions ?? [];
153
+ }
154
+ function buildCheckpointCommitConditions(workflowId, commit, includeCheckpointCondition, sideEffectConditions) {
155
+ const conditions = [];
156
+ if (includeCheckpointCondition && commit.expectedSerialized !== void 0)
157
+ conditions.push({
134
158
  key: KEYS.checkpoint(workflowId),
135
- expectedValue: expectedSerialized
136
- }
137
- ];
138
- if (!await storageConditionalBatch(internals.storage, conditions, commit.operations))
139
- throw Error(`Checkpoint commit for workflow "${workflowId}" lost its CAS race against a newer checkpoint.`);
159
+ expectedValue: commit.expectedSerialized
160
+ });
161
+ conditions.push(...sideEffectConditions);
162
+ return conditions;
140
163
  }
141
164
  function historyEventLimitBreached(internals, sequence) {
142
165
  const maxEvents = internals.options.historyPolicy.maxEvents;
@@ -154,7 +177,16 @@ function dispatchCheckpointSizeWarning(internals, workflowId, commit, callbacks)
154
177
  callbacks.dispatchEvent(new CheckpointSizeWarningEvent(workflowId, commit.serialized.byteLength, commit.step));
155
178
  }
156
179
  function appendCheckpointEventLog(internals, workflowId, commit) {
157
- return new EventLog(internals.storage, workflowId).appendToBatch({ type: "workflow:checkpoint", payload: { step: commit.step } }, commit.operations, internals.eventLogHeads.get(workflowId) ?? EMPTY_EVENT_HEAD, internals.workflowVersionTuples.get(workflowId));
180
+ return new EventLog(internals.storage, workflowId).appendToBatch({
181
+ type: "workflow:checkpoint",
182
+ payload: createCheckpointEventPayload(commit.step, commit.replayPayload)
183
+ }, commit.operations, internals.eventLogHeads.get(workflowId) ?? EMPTY_EVENT_HEAD, internals.workflowVersionTuples.get(workflowId));
184
+ }
185
+ function resolvePendingOperationStep(operation, fallbackStepIndex) {
186
+ const operationStep = "step" in operation ? operation.step : void 0;
187
+ if (typeof operationStep === "number" && Number.isSafeInteger(operationStep) && operationStep >= 0)
188
+ return operationStep;
189
+ return Math.max(0, fallbackStepIndex - 1);
158
190
  }
159
191
  export async function pruneCheckpointHistory(internals, workflowId, currentStep) {
160
192
  const limit = internals.options.checkpointHistory;
@@ -175,7 +207,11 @@ export function validateDevelopmentCheckpoint(internals, workflowId, callbacks)
175
207
  const step = context.stepIndex, current = internals.checkpoints.get(workflowId);
176
208
  if (!current)
177
209
  return;
178
- const result = validateCheckpointRoundTrip(current);
210
+ const result = validateCheckpointRoundTrip({
211
+ ...current,
212
+ locals: context.checkpointLocals,
213
+ accumulatedResults: context.checkpointAccumulatedResults
214
+ });
179
215
  if (!result.valid) {
180
216
  const fieldPaths = result.divergences.map((divergence) => divergence.path), message = `Checkpoint at step ${step} has ${result.divergences.length} non-serializable field(s)`;
181
217
  callbacks.dispatchEvent(new DevelopmentWarningEvent(workflowId, message, fieldPaths));
@@ -3,6 +3,7 @@ import { deserializeCheckpoint } from "../checkpoint.js";
3
3
  import { decode } from "../codec.js";
4
4
  import { sanitizeDebugValueForDisplay } from "../debug-output.js";
5
5
  import { EventLog } from "../event-log.js";
6
+ import { hydrateCheckpointReplayState } from "./checkpoint-replay.js";
6
7
  import { readEventLogWatermark } from "./event-log-compaction.js";
7
8
  import {
8
9
  sanitizeCheckpointState,
@@ -41,7 +42,7 @@ export async function getCheckpointAt(internals, workflowId, step) {
41
42
  const bytes = await internals.storage.get(KEYS.checkpointHistory(workflowId, step));
42
43
  if (!bytes)
43
44
  return null;
44
- const checkpoint = deserializeCheckpoint(bytes);
45
+ const checkpoint = await hydrateCheckpointReplayState(internals.storage, workflowId, deserializeCheckpoint(bytes));
45
46
  return sanitizeCheckpointState({
46
47
  step: checkpoint.step,
47
48
  locals: checkpoint.locals,
@@ -75,7 +76,7 @@ export async function replayTo(internals, workflowId, step) {
75
76
  const bytes = await internals.storage.get(KEYS.checkpointHistory(workflowId, step));
76
77
  if (!bytes)
77
78
  return null;
78
- const checkpoint = deserializeCheckpoint(bytes), entries = await new EventLog(internals.storage, workflowId).replay(Math.max(step - 1, -1)), watermark = await readEventLogWatermark(internals.storage, workflowId);
79
+ const entries = await new EventLog(internals.storage, workflowId).replay(Math.max(step - 1, -1)), checkpoint = await hydrateCheckpointReplayState(internals.storage, workflowId, deserializeCheckpoint(bytes)), watermark = await readEventLogWatermark(internals.storage, workflowId);
79
80
  return {
80
81
  checkpoint: sanitizeCheckpointState({
81
82
  step: checkpoint.step,
@@ -0,0 +1,20 @@
1
+ import { type Storage } from '../../storage/interface.ts';
2
+ import type { Checkpoint, WorkerReplayOperationFailure, WorkerReplayOperationSignature } from '../types.ts';
3
+ export declare const CHECKPOINT_REPLAY_PAYLOAD_KEY = "__weftCheckpointReplay";
4
+ export type CheckpointReplayPayload = {
5
+ accumulatedResults?: Array<[number, unknown]>;
6
+ workerReplaySignatures?: Array<[number, WorkerReplayOperationSignature]>;
7
+ workerReplayFailures?: Array<[number, WorkerReplayOperationFailure]>;
8
+ };
9
+ export type PrunedCheckpointReplayState = {
10
+ checkpoint: Checkpoint;
11
+ replayPayload: CheckpointReplayPayload | undefined;
12
+ };
13
+ export declare function pruneCheckpointReplayState(checkpoint: Checkpoint, pendingOperationStep: number): PrunedCheckpointReplayState;
14
+ export declare function hydrateCheckpointReplayState(storage: Storage, workflowId: string, checkpoint: Checkpoint): Promise<Checkpoint>;
15
+ export declare function hydrateCheckpointReplayStateFromPayload(checkpoint: Checkpoint, replayPayload: CheckpointReplayPayload | undefined): Checkpoint;
16
+ export declare function attachTransientCheckpointReplayPayload(checkpoint: Checkpoint, replayPayload: CheckpointReplayPayload | undefined): Checkpoint;
17
+ export declare function createCheckpointEventPayload(checkpointStep: number, replayPayload: CheckpointReplayPayload | undefined): Record<string, unknown>;
18
+ export declare function mergeCheckpointReplayPayloads(left: CheckpointReplayPayload | undefined, right: CheckpointReplayPayload | undefined): CheckpointReplayPayload | undefined;
19
+ export declare function readCheckpointReplayPayload(payload: unknown): CheckpointReplayPayload | undefined;
20
+ export declare function stripInternalCheckpointReplayPayload(payload: Record<string, unknown>): Record<string, unknown>;
@@ -0,0 +1,242 @@
1
+ import { KEYS } from "../../storage/interface.js";
2
+ import { decode } from "../codec.js";
3
+ import { isWorkflowLogEntry } from "../event-log-shared.js";
4
+ import { WORKER_REPLAY_SIGNATURE_FORMAT } from "../types/checkpoint.js";
5
+ export const CHECKPOINT_REPLAY_PAYLOAD_KEY = "__weftCheckpointReplay";
6
+ const NO_REPLAY_WATERMARK = -1;
7
+ export function pruneCheckpointReplayState(checkpoint, pendingOperationStep) {
8
+ const checkpointWithoutReplayPayload = stripTransientCheckpointReplayPayload(checkpoint), previousWatermark = checkpointWithoutReplayPayload.accumulatedResultReplayWatermark ?? NO_REPLAY_WATERMARK, consumedResults = entriesBeforeStep(checkpointWithoutReplayPayload.accumulatedResults, pendingOperationStep), consumedSignatures = entriesBeforeStep(checkpointWithoutReplayPayload.workerReplaySignatures ?? [], pendingOperationStep), consumedFailures = entriesBeforeStep(checkpointWithoutReplayPayload.workerReplayFailures ?? [], pendingOperationStep), replayPayload = buildReplayPayload({
9
+ accumulatedResults: entriesAfterWatermark(consumedResults, previousWatermark),
10
+ workerReplaySignatures: entriesAfterWatermark(consumedSignatures, previousWatermark),
11
+ workerReplayFailures: entriesAfterWatermark(consumedFailures, previousWatermark)
12
+ }), nextWatermark = resolveNextReplayWatermark(previousWatermark, replayPayload), retainedWorkerReplaySignatures = entriesAtOrAfterStep(checkpointWithoutReplayPayload.workerReplaySignatures ?? [], pendingOperationStep), retainedWorkerReplayFailures = entriesAtOrAfterStep(checkpointWithoutReplayPayload.workerReplayFailures ?? [], pendingOperationStep), prunedCheckpoint = {
13
+ ...checkpointWithoutReplayPayload,
14
+ accumulatedResults: entriesAtOrAfterStep(checkpointWithoutReplayPayload.accumulatedResults, pendingOperationStep),
15
+ ...nextWatermark === NO_REPLAY_WATERMARK ? {} : { accumulatedResultReplayWatermark: nextWatermark },
16
+ ...optionalEntries("workerReplaySignatures", retainedWorkerReplaySignatures),
17
+ ...optionalEntries("workerReplayFailures", retainedWorkerReplayFailures)
18
+ };
19
+ if (nextWatermark === NO_REPLAY_WATERMARK)
20
+ delete prunedCheckpoint.accumulatedResultReplayWatermark;
21
+ if (retainedWorkerReplaySignatures.length === 0)
22
+ delete prunedCheckpoint.workerReplaySignatures;
23
+ if (retainedWorkerReplayFailures.length === 0)
24
+ delete prunedCheckpoint.workerReplayFailures;
25
+ return {
26
+ checkpoint: prunedCheckpoint,
27
+ replayPayload
28
+ };
29
+ }
30
+ export async function hydrateCheckpointReplayState(storage, workflowId, checkpoint) {
31
+ const replayPayloads = [], checkpointReplayPayload = readCheckpointReplayPayload(checkpoint);
32
+ if (checkpointReplayPayload !== void 0)
33
+ replayPayloads.push(checkpointReplayPayload);
34
+ const compactedReplayPayload = await readCompactedCheckpointReplayPayload(storage, workflowId);
35
+ if (compactedReplayPayload !== void 0)
36
+ replayPayloads.push(compactedReplayPayload);
37
+ for await (const [, entryBytes] of storage.scan(KEYS.eventPrefix(workflowId))) {
38
+ const decoded = decode(entryBytes);
39
+ if (!isWorkflowLogEntry(decoded))
40
+ continue;
41
+ const entry = decoded, checkpointStep = getCheckpointEventStep(entry.payload);
42
+ if (checkpointStep === void 0)
43
+ continue;
44
+ if (checkpointStep > checkpoint.step)
45
+ break;
46
+ const replayPayload = readCheckpointReplayPayload(entry.payload);
47
+ if (replayPayload === void 0)
48
+ continue;
49
+ replayPayloads.push(replayPayload);
50
+ }
51
+ return hydrateCheckpointReplayStateFromPayloads(stripTransientCheckpointReplayPayload(checkpoint), replayPayloads);
52
+ }
53
+ export function hydrateCheckpointReplayStateFromPayload(checkpoint, replayPayload) {
54
+ return hydrateCheckpointReplayStateFromPayloads(stripTransientCheckpointReplayPayload(checkpoint), replayPayload === void 0 ? [] : [replayPayload]);
55
+ }
56
+ function hydrateCheckpointReplayStateFromPayloads(checkpoint, replayPayloads) {
57
+ const accumulatedResults = new Map, workerReplaySignatures = new Map, workerReplayFailures = new Map;
58
+ for (const replayPayload of replayPayloads)
59
+ mergeReplayPayload({
60
+ accumulatedResults,
61
+ workerReplaySignatures,
62
+ workerReplayFailures
63
+ }, replayPayload);
64
+ mergeEntries(accumulatedResults, checkpoint.accumulatedResults);
65
+ mergeEntries(workerReplaySignatures, checkpoint.workerReplaySignatures ?? []);
66
+ mergeEntries(workerReplayFailures, checkpoint.workerReplayFailures ?? []);
67
+ return {
68
+ ...checkpoint,
69
+ accumulatedResults: sortedEntries(accumulatedResults),
70
+ ...optionalEntries("workerReplaySignatures", sortedEntries(workerReplaySignatures)),
71
+ ...optionalEntries("workerReplayFailures", sortedEntries(workerReplayFailures))
72
+ };
73
+ }
74
+ export function attachTransientCheckpointReplayPayload(checkpoint, replayPayload) {
75
+ if (replayPayload === void 0)
76
+ return checkpoint;
77
+ return {
78
+ ...checkpoint,
79
+ [CHECKPOINT_REPLAY_PAYLOAD_KEY]: replayPayload
80
+ };
81
+ }
82
+ export function createCheckpointEventPayload(checkpointStep, replayPayload) {
83
+ return replayPayload === void 0 ? { step: checkpointStep } : { step: checkpointStep, [CHECKPOINT_REPLAY_PAYLOAD_KEY]: replayPayload };
84
+ }
85
+ export function mergeCheckpointReplayPayloads(left, right) {
86
+ if (left === void 0)
87
+ return right;
88
+ if (right === void 0)
89
+ return left;
90
+ return buildReplayPayload({
91
+ accumulatedResults: [...left.accumulatedResults ?? [], ...right.accumulatedResults ?? []],
92
+ workerReplaySignatures: [
93
+ ...left.workerReplaySignatures ?? [],
94
+ ...right.workerReplaySignatures ?? []
95
+ ],
96
+ workerReplayFailures: [
97
+ ...left.workerReplayFailures ?? [],
98
+ ...right.workerReplayFailures ?? []
99
+ ]
100
+ });
101
+ }
102
+ export function readCheckpointReplayPayload(payload) {
103
+ if (!isRecord(payload))
104
+ return;
105
+ const replayPayload = payload[CHECKPOINT_REPLAY_PAYLOAD_KEY];
106
+ if (!isRecord(replayPayload))
107
+ return;
108
+ return readCheckpointReplayPayloadRecord(replayPayload);
109
+ }
110
+ export function stripInternalCheckpointReplayPayload(payload) {
111
+ const { [CHECKPOINT_REPLAY_PAYLOAD_KEY]: _internalReplayPayload, ...publicPayload } = payload;
112
+ return publicPayload;
113
+ }
114
+ function buildReplayPayload(payload) {
115
+ const replayPayload = {}, accumulatedResults = payload.accumulatedResults, workerReplaySignatures = payload.workerReplaySignatures, workerReplayFailures = payload.workerReplayFailures;
116
+ if (accumulatedResults !== void 0 && accumulatedResults.length > 0)
117
+ replayPayload.accumulatedResults = accumulatedResults;
118
+ if (workerReplaySignatures !== void 0 && workerReplaySignatures.length > 0)
119
+ replayPayload.workerReplaySignatures = workerReplaySignatures;
120
+ if (workerReplayFailures !== void 0 && workerReplayFailures.length > 0)
121
+ replayPayload.workerReplayFailures = workerReplayFailures;
122
+ return Object.keys(replayPayload).length === 0 ? void 0 : replayPayload;
123
+ }
124
+ function resolveNextReplayWatermark(previousWatermark, replayPayload) {
125
+ if (replayPayload === void 0)
126
+ return previousWatermark;
127
+ let nextWatermark = previousWatermark;
128
+ for (const entries of [
129
+ replayPayload.accumulatedResults ?? [],
130
+ replayPayload.workerReplaySignatures ?? [],
131
+ replayPayload.workerReplayFailures ?? []
132
+ ])
133
+ for (const [step] of entries)
134
+ nextWatermark = Math.max(nextWatermark, step);
135
+ return nextWatermark;
136
+ }
137
+ function entriesBeforeStep(entries, step) {
138
+ return entries.filter(([entryStep]) => entryStep < step);
139
+ }
140
+ function entriesAtOrAfterStep(entries, step) {
141
+ return entries.filter(([entryStep]) => entryStep >= step);
142
+ }
143
+ function entriesAfterWatermark(entries, watermark) {
144
+ return entries.filter(([entryStep]) => entryStep > watermark);
145
+ }
146
+ function optionalEntries(key, entries) {
147
+ return entries.length === 0 ? {} : { [key]: entries };
148
+ }
149
+ function stripTransientCheckpointReplayPayload(checkpoint) {
150
+ const checkpointWithReplayPayload = checkpoint, { [CHECKPOINT_REPLAY_PAYLOAD_KEY]: _replayPayload, ...checkpointWithoutReplayPayload } = checkpointWithReplayPayload;
151
+ return checkpointWithoutReplayPayload;
152
+ }
153
+ function sortedEntries(entries) {
154
+ return [...entries.entries()].toSorted(([leftStep], [rightStep]) => leftStep - rightStep);
155
+ }
156
+ function mergeEntries(target, entries) {
157
+ for (const [step, value] of entries)
158
+ target.set(step, value);
159
+ }
160
+ function mergeReplayPayload(target, replayPayload) {
161
+ mergeEntries(target.accumulatedResults, replayPayload.accumulatedResults ?? []);
162
+ mergeEntries(target.workerReplaySignatures, replayPayload.workerReplaySignatures ?? []);
163
+ mergeEntries(target.workerReplayFailures, replayPayload.workerReplayFailures ?? []);
164
+ }
165
+ function getCheckpointEventStep(payload) {
166
+ if (!isRecord(payload))
167
+ return;
168
+ const step = payload.step;
169
+ return typeof step === "number" && Number.isSafeInteger(step) && step >= 0 ? step : void 0;
170
+ }
171
+ function readCheckpointReplayPayloadRecord(replayPayload) {
172
+ const accumulatedResults = readUnknownEntries(replayPayload.accumulatedResults), workerReplaySignatures = readWorkerReplaySignatureEntries(replayPayload.workerReplaySignatures), workerReplayFailures = readWorkerReplayFailureEntries(replayPayload.workerReplayFailures);
173
+ return buildReplayPayload({
174
+ ...accumulatedResults === void 0 ? {} : { accumulatedResults },
175
+ ...workerReplaySignatures === void 0 ? {} : { workerReplaySignatures },
176
+ ...workerReplayFailures === void 0 ? {} : { workerReplayFailures }
177
+ });
178
+ }
179
+ async function readCompactedCheckpointReplayPayload(storage, workflowId) {
180
+ const watermarkBytes = await storage.get(KEYS.eventWatermark(workflowId));
181
+ if (watermarkBytes === null)
182
+ return;
183
+ const watermark = decode(watermarkBytes);
184
+ if (!isRecord(watermark))
185
+ return;
186
+ const replayPayload = watermark.checkpointReplay;
187
+ return isRecord(replayPayload) ? readCheckpointReplayPayloadRecord(replayPayload) : void 0;
188
+ }
189
+ function readUnknownEntries(value) {
190
+ if (!Array.isArray(value))
191
+ return;
192
+ const entries = [];
193
+ for (const entry of value) {
194
+ if (!Array.isArray(entry) || entry.length !== 2 || !isReplayStep(entry[0]))
195
+ continue;
196
+ entries.push([entry[0], entry[1]]);
197
+ }
198
+ return entries;
199
+ }
200
+ function readWorkerReplaySignatureEntries(value) {
201
+ if (!Array.isArray(value))
202
+ return;
203
+ const entries = [];
204
+ for (const entry of value) {
205
+ if (!Array.isArray(entry) || entry.length !== 2 || !isReplayStep(entry[0]))
206
+ continue;
207
+ if (!isWorkerReplaySignature(entry[1]))
208
+ continue;
209
+ entries.push([entry[0], entry[1]]);
210
+ }
211
+ return entries;
212
+ }
213
+ function readWorkerReplayFailureEntries(value) {
214
+ if (!Array.isArray(value))
215
+ return;
216
+ const entries = [];
217
+ for (const entry of value) {
218
+ if (!Array.isArray(entry) || entry.length !== 2 || !isReplayStep(entry[0]))
219
+ continue;
220
+ if (!isWorkerReplayFailure(entry[1]))
221
+ continue;
222
+ entries.push([entry[0], entry[1]]);
223
+ }
224
+ return entries;
225
+ }
226
+ function isRecord(value) {
227
+ return typeof value === "object" && value !== null;
228
+ }
229
+ function isReplayStep(value) {
230
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
231
+ }
232
+ function isWorkerReplaySignature(value) {
233
+ if (!isRecord(value))
234
+ return !1;
235
+ return value.format === WORKER_REPLAY_SIGNATURE_FORMAT && typeof value.operationType === "string" && typeof value.stableFieldsDigest === "string" && isReplayStep(value.stableFieldsByteLength);
236
+ }
237
+ function isWorkerReplayFailure(value) {
238
+ if (!isRecord(value))
239
+ return !1;
240
+ const failureCategory = value.failureCategory;
241
+ return value.status === "failed" && typeof value.error === "string" && (value.errorName === void 0 || typeof value.errorName === "string") && (failureCategory === void 0 || failureCategory === "application" || failureCategory === "cancellation" || failureCategory === "resource" || failureCategory === "system" || failureCategory === "timeout");
242
+ }
@@ -0,0 +1,23 @@
1
+ import type { BatchOperation, ConditionalBatchCondition } from '../../storage/interface.ts';
2
+ import type { EngineInternals } from './internals.ts';
3
+ export type AtomicWorkflowCommitSideEffects = {
4
+ conditions: ConditionalBatchCondition[];
5
+ operations: BatchOperation[];
6
+ };
7
+ export declare function stageAtomicWorkflowCommitSideEffects(internals: EngineInternals, workflowId: string, sideEffects: AtomicWorkflowCommitSideEffects): void;
8
+ export declare function takePendingAtomicWorkflowCommitSideEffects(internals: EngineInternals, workflowId: string): AtomicWorkflowCommitSideEffects | undefined;
9
+ export declare function clearPendingAtomicWorkflowCommitSideEffects(internals: EngineInternals, workflowId: string): void;
10
+ /**
11
+ * Non-destructively report whether a workflow's pending atomic side-effect buffer
12
+ * already stages a `put` to `key`. Unlike {@link takePendingAtomicWorkflowCommitSideEffects},
13
+ * this does NOT consume the buffer, so it is safe to call at a gate that runs before the
14
+ * commit that will flush those same side-effects.
15
+ *
16
+ * The terminal-transition path (#446) needs this: `ctx.setFinalizerState()` stages the
17
+ * `wf-finalizer-state:` put as a pending side-effect that the terminal batch flushes, but
18
+ * a pre-batch `storage.get()` cannot see a staged-but-unflushed write. Peeking the buffer
19
+ * lets the terminal batch stage its teardown marker atomically alongside that put — without
20
+ * it, a `setFinalizerState` with no intervening checkpoint would commit the resource state
21
+ * yet skip the teardown marker, silently leaking the external resource.
22
+ */
23
+ export declare function pendingAtomicWorkflowCommitSideEffectsStagePut(internals: EngineInternals, workflowId: string, key: string): boolean;
@@ -0,0 +1,35 @@
1
+ export function stageAtomicWorkflowCommitSideEffects(internals, workflowId, sideEffects) {
2
+ if (sideEffects.conditions.length === 0 && sideEffects.operations.length === 0)
3
+ return;
4
+ const pending = internals.pendingAtomicWorkflowCommitSideEffects.get(workflowId);
5
+ if (pending === void 0) {
6
+ internals.pendingAtomicWorkflowCommitSideEffects.set(workflowId, {
7
+ conditions: [...sideEffects.conditions],
8
+ operations: [...sideEffects.operations]
9
+ });
10
+ return;
11
+ }
12
+ pending.conditions.push(...sideEffects.conditions);
13
+ pending.operations.push(...sideEffects.operations);
14
+ }
15
+ export function takePendingAtomicWorkflowCommitSideEffects(internals, workflowId) {
16
+ const pending = internals.pendingAtomicWorkflowCommitSideEffects.get(workflowId);
17
+ if (pending === void 0)
18
+ return;
19
+ internals.pendingAtomicWorkflowCommitSideEffects.delete(workflowId);
20
+ if (pending.conditions.length === 0 && pending.operations.length === 0)
21
+ return;
22
+ return {
23
+ conditions: [...pending.conditions],
24
+ operations: [...pending.operations]
25
+ };
26
+ }
27
+ export function clearPendingAtomicWorkflowCommitSideEffects(internals, workflowId) {
28
+ internals.pendingAtomicWorkflowCommitSideEffects.delete(workflowId);
29
+ }
30
+ export function pendingAtomicWorkflowCommitSideEffectsStagePut(internals, workflowId, key) {
31
+ const pending = internals.pendingAtomicWorkflowCommitSideEffects.get(workflowId);
32
+ if (pending === void 0)
33
+ return !1;
34
+ return pending.operations.some((operation) => operation.type === "put" && operation.key === key);
35
+ }
@@ -0,0 +1,10 @@
1
+ import { type BatchOperation } from '../../storage/interface.ts';
2
+ import type { WorkflowHandle } from './handles.ts';
3
+ import type { EngineInternals } from './internals.ts';
4
+ type ChildCancellationCallbacks = {
5
+ getHandle: (workflowId: string) => WorkflowHandle;
6
+ };
7
+ export declare function buildChildCancellationOperations(internals: EngineInternals, workflowId: string, childWorkflowId: string): BatchOperation[];
8
+ export declare function registerChildCancellationHandler(internals: EngineInternals, workflowId: string, childWorkflowId: string, callbacks: ChildCancellationCallbacks): void;
9
+ export declare function rehydrateChildCancellationHandlers(internals: EngineInternals, workflowId: string, callbacks: ChildCancellationCallbacks): Promise<void>;
10
+ export {};
@@ -0,0 +1,40 @@
1
+ import { KEYS, decodeStorageKeyComponent } from "../../storage/interface.js";
2
+ import { registerCancelHandler } from "./cancel-handlers.js";
3
+ import { EMPTY_STORAGE_VALUE } from "./lifecycle/shared.js";
4
+ export function buildChildCancellationOperations(internals, workflowId, childWorkflowId) {
5
+ const operations = [
6
+ {
7
+ type: "put",
8
+ key: KEYS.childCancellation(workflowId, childWorkflowId),
9
+ value: EMPTY_STORAGE_VALUE
10
+ }
11
+ ], needsCleanupMarker = !internals.workflowsNeedingTerminalCleanup.has(workflowId);
12
+ internals.workflowsNeedingTerminalCleanup.add(workflowId);
13
+ if (needsCleanupMarker)
14
+ operations.push({
15
+ type: "put",
16
+ key: KEYS.terminalCleanupNeeded(workflowId),
17
+ value: EMPTY_STORAGE_VALUE
18
+ });
19
+ return operations;
20
+ }
21
+ export function registerChildCancellationHandler(internals, workflowId, childWorkflowId, callbacks) {
22
+ registerCancelHandler(internals, workflowId, () => callbacks.getHandle(childWorkflowId).cancel());
23
+ }
24
+ export async function rehydrateChildCancellationHandlers(internals, workflowId, callbacks) {
25
+ for await (const [key] of internals.storage.scan(KEYS.childCancellationPrefix(workflowId))) {
26
+ const childWorkflowId = decodeChildCancellationKey(workflowId, key);
27
+ if (childWorkflowId === null)
28
+ continue;
29
+ registerChildCancellationHandler(internals, workflowId, childWorkflowId, callbacks);
30
+ }
31
+ }
32
+ function decodeChildCancellationKey(workflowId, key) {
33
+ const prefix = KEYS.childCancellationPrefix(workflowId);
34
+ if (!key.startsWith(prefix))
35
+ return null;
36
+ const encodedChildWorkflowId = key.slice(prefix.length);
37
+ if (encodedChildWorkflowId.length === 0 || encodedChildWorkflowId.includes(":"))
38
+ return null;
39
+ return decodeStorageKeyComponent(encodedChildWorkflowId);
40
+ }
@@ -1,3 +1,9 @@
1
+ import { assertOnTerminalConflictUnsupported } from "../start-workflow-validation.js";
2
+ import { stageAtomicWorkflowCommitSideEffects } from "./checkpoint-side-effects.js";
3
+ import {
4
+ buildChildCancellationOperations,
5
+ registerChildCancellationHandler
6
+ } from "./child-workflow-cancellation.js";
1
7
  import { WorkflowAlreadyExistsError } from "./errors.js";
2
8
  import { encodedValuesEqual } from "./state-utilities.js";
3
9
  export async function processChildWorkflowOperation(internals, workflowId, operation, callbacks) {
@@ -37,6 +43,7 @@ async function resolveCollisionChildHandle(childWorkflowId, operation, execution
37
43
  return callbacks.getHandle(childWorkflowId);
38
44
  }
39
45
  async function dispatchChildWorkflowStart(internals, childWorkflowId, operation, context, callbacks) {
46
+ assertOnTerminalConflictUnsupported(operation.options, "ctx.startChild");
40
47
  applyPendingChildExecutionContext(internals, context);
41
48
  try {
42
49
  return await callbacks.start(operation.workflowType, operation.input, {
@@ -45,19 +52,29 @@ async function dispatchChildWorkflowStart(internals, childWorkflowId, operation,
45
52
  } catch (error) {
46
53
  if (!(error instanceof WorkflowAlreadyExistsError))
47
54
  throw error;
48
- return resolveCollisionChildHandle(childWorkflowId, operation, context.pendingExecutionStateOwnerId, error, callbacks);
55
+ return resolveCollisionChildHandle(childWorkflowId, operation, context.pendingExecutionStateOwnerId ?? void 0, error, callbacks);
49
56
  } finally {
50
57
  clearPendingChildExecutionContext(internals, context);
51
58
  }
52
59
  }
53
60
  export async function executeChildWorkflow(internals, workflowId, operation, currentDepth, callbacks) {
54
- const rawId = operation.options?.id, childWorkflowId = typeof rawId === "string" ? rawId : crypto.randomUUID(), parentHeaders = internals.workflowHeaders.get(workflowId) ?? new Map, executionStateOwnerId = (await callbacks.loadWorkflowState(workflowId))?.executionStateOwnerId ?? workflowId, executeChild = async () => {
61
+ const rawId = operation.options?.id, childWorkflowId = typeof rawId === "string" ? rawId : crypto.randomUUID(), parentHeaders = internals.workflowHeaders.get(workflowId) ?? new Map, parentState = await callbacks.loadWorkflowState(workflowId), parentClosePolicy = resolveChildWorkflowParentClosePolicy(operation), executionStateOwnerId = parentClosePolicy === "abandon" ? null : parentState?.executionStateOwnerId ?? workflowId, executeChild = async () => {
55
62
  const context = {
56
63
  pendingNestingDepth: currentDepth + 1,
57
64
  pendingParentHeaders: internals.workflowHeaders.get(workflowId),
58
65
  pendingExecutionStateOwnerId: executionStateOwnerId
59
- };
60
- return (await dispatchChildWorkflowStart(internals, childWorkflowId, operation, context, callbacks)).result();
66
+ }, childHandle = await dispatchChildWorkflowStart(internals, childWorkflowId, operation, context, callbacks);
67
+ if (parentClosePolicy === "abandon")
68
+ return createChildWorkflowHandleReference(childHandle.id);
69
+ if (parentClosePolicy === "request-cancel") {
70
+ stageAtomicWorkflowCommitSideEffects(internals, workflowId, {
71
+ conditions: [],
72
+ operations: buildChildCancellationOperations(internals, workflowId, childHandle.id)
73
+ });
74
+ registerChildCancellationHandler(internals, workflowId, childHandle.id, callbacks);
75
+ return createChildWorkflowHandleReference(childHandle.id);
76
+ }
77
+ return childHandle.result();
61
78
  }, composedInterceptor = callbacks.getComposedWorkflowInterceptor();
62
79
  if (!composedInterceptor)
63
80
  return executeChild();
@@ -70,3 +87,9 @@ export async function executeChildWorkflow(internals, workflowId, operation, cur
70
87
  parentHeaders
71
88
  }, executeChild);
72
89
  }
90
+ function resolveChildWorkflowParentClosePolicy(operation) {
91
+ return operation.options?.parentClosePolicy ?? "await";
92
+ }
93
+ function createChildWorkflowHandleReference(workflowId) {
94
+ return { id: workflowId };
95
+ }
@@ -0,0 +1,14 @@
1
+ import type { EngineInternals } from './internals.ts';
2
+ /**
3
+ * Re-drive every in-process `ctx.waitUntil` waiter registered for a workflow.
4
+ * Called after an inline `onUpdate` handler runs (`tryInlineUpdateHandler`),
5
+ * since the handler may have mutated the workflow-local state a predicate reads.
6
+ * Each call wakes the parked `processWaitConditionOperation`, which re-evaluates
7
+ * its predicate against the (possibly mutated) state.
8
+ *
9
+ * Weft signals are pull-only (`ctx.waitForSignal`) and run no state-mutating
10
+ * handler, so signal delivery is intentionally NOT a re-drive trigger — `onUpdate`
11
+ * is the push path. Lives in its own module so `updates.ts` can call it without
12
+ * an import cycle through `operations-coordination.ts`.
13
+ */
14
+ export declare function notifyConditionWaiters(internals: EngineInternals, workflowId: string): void;
@@ -0,0 +1,5 @@
1
+ export function notifyConditionWaiters(internals, workflowId) {
2
+ const resolve = internals.conditionWaiters.get(workflowId);
3
+ if (resolve)
4
+ resolve();
5
+ }