@lostgradient/weft 0.3.0 → 0.5.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 (510) 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 +61 -5
  23. package/dist/client/local-handles.d.ts +22 -0
  24. package/dist/client/local-handles.js +23 -0
  25. package/dist/client/local.d.ts +6 -3
  26. package/dist/client/local.js +12 -26
  27. package/dist/client/start-body.d.ts +4 -3
  28. package/dist/core/byte-arrays.d.ts +5 -0
  29. package/dist/core/byte-arrays.js +5 -0
  30. package/dist/core/checkpoint/lifecycle.d.ts +3 -0
  31. package/dist/core/checkpoint/lifecycle.js +9 -4
  32. package/dist/core/checkpoint/serialization.js +12 -5
  33. package/dist/core/codec/extension-codec.d.ts +16 -0
  34. package/dist/core/codec/extension-codec.js +100 -6
  35. package/dist/core/context/activity-retry-state.d.ts +38 -0
  36. package/dist/core/context/activity-retry-state.js +89 -0
  37. package/dist/core/context/activity-schedule-to-close.d.ts +159 -0
  38. package/dist/core/context/activity-schedule-to-close.js +69 -0
  39. package/dist/core/context/child-workflow-pipe.d.ts +5 -5
  40. package/dist/core/context/child-workflow-pipe.js +15 -2
  41. package/dist/core/context/context-presence.d.ts +19 -0
  42. package/dist/core/context/context-presence.js +13 -0
  43. package/dist/core/context/durable-operations.d.ts +25 -0
  44. package/dist/core/context/durable-operations.js +64 -0
  45. package/dist/core/context/index.d.ts +9 -5
  46. package/dist/core/context/index.js +17 -12
  47. package/dist/core/context/internals.d.ts +20 -0
  48. package/dist/core/context/internals.js +3 -1
  49. package/dist/core/context/operation-request.d.ts +35 -0
  50. package/dist/core/context/parallel-cache-entry.d.ts +14 -5
  51. package/dist/core/context/run-operation.d.ts +6 -1
  52. package/dist/core/context/run-operation.js +41 -87
  53. package/dist/core/context/session-state.js +7 -8
  54. package/dist/core/context/speculative-child.js +2 -0
  55. package/dist/core/context/types.d.ts +15 -0
  56. package/dist/core/context/version-patching.d.ts +8 -0
  57. package/dist/core/context/version-patching.js +40 -0
  58. package/dist/core/context/workflow-logger.d.ts +98 -0
  59. package/dist/core/context/workflow-logger.js +68 -0
  60. package/dist/core/engine/activity-heartbeat-tracking.d.ts +64 -0
  61. package/dist/core/engine/activity-heartbeat-tracking.js +42 -0
  62. package/dist/core/engine/activity-per-attempt-timeout.d.ts +46 -0
  63. package/dist/core/engine/activity-per-attempt-timeout.js +36 -0
  64. package/dist/core/engine/activity-reconciliation.d.ts +1 -0
  65. package/dist/core/engine/activity-reconciliation.js +12 -1
  66. package/dist/core/engine/activity-resolution.d.ts +23 -0
  67. package/dist/core/engine/activity-resolution.js +37 -0
  68. package/dist/core/engine/aggregate.js +66 -30
  69. package/dist/core/engine/async-activity-completion.d.ts +23 -6
  70. package/dist/core/engine/async-activity-completion.js +53 -12
  71. package/dist/core/engine/attributes-tags.js +9 -4
  72. package/dist/core/engine/bulk-operations-purge.d.ts +26 -0
  73. package/dist/core/engine/bulk-operations-purge.js +38 -3
  74. package/dist/core/engine/bulk-operations-shared.d.ts +2 -0
  75. package/dist/core/engine/bulk-operations-shared.js +8 -2
  76. package/dist/core/engine/bulk-operations.d.ts +4 -1
  77. package/dist/core/engine/bulk-operations.js +235 -24
  78. package/dist/core/engine/callback-creators-bundles.d.ts +9 -0
  79. package/dist/core/engine/callback-creators-bundles.js +30 -2
  80. package/dist/core/engine/callback-creators-core.js +6 -4
  81. package/dist/core/engine/callback-creators-router.js +10 -0
  82. package/dist/core/engine/callback-creators-schedule.d.ts +2 -2
  83. package/dist/core/engine/callback-creators-schedule.js +12 -8
  84. package/dist/core/engine/candidate-read-batching.d.ts +6 -0
  85. package/dist/core/engine/candidate-read-batching.js +1 -0
  86. package/dist/core/engine/checkpoint-io.js +61 -25
  87. package/dist/core/engine/checkpoint-reads.js +3 -2
  88. package/dist/core/engine/checkpoint-replay.d.ts +20 -0
  89. package/dist/core/engine/checkpoint-replay.js +242 -0
  90. package/dist/core/engine/checkpoint-side-effects.d.ts +23 -0
  91. package/dist/core/engine/checkpoint-side-effects.js +35 -0
  92. package/dist/core/engine/child-workflow-cancellation.d.ts +10 -0
  93. package/dist/core/engine/child-workflow-cancellation.js +40 -0
  94. package/dist/core/engine/child-workflow.js +27 -4
  95. package/dist/core/engine/condition-waiters.d.ts +14 -0
  96. package/dist/core/engine/condition-waiters.js +5 -0
  97. package/dist/core/engine/construction.d.ts +3 -0
  98. package/dist/core/engine/construction.js +21 -8
  99. package/dist/core/engine/coordination-branch-executors.d.ts +70 -0
  100. package/dist/core/engine/coordination-branch-executors.js +107 -0
  101. package/dist/core/engine/deferred-consume-envelope.d.ts +59 -0
  102. package/dist/core/engine/deferred-consume-envelope.js +14 -0
  103. package/dist/core/engine/disposal.js +13 -0
  104. package/dist/core/engine/engine-create-types.d.ts +14 -4
  105. package/dist/core/engine/engine-internal-types.d.ts +26 -3
  106. package/dist/core/engine/errors.d.ts +47 -0
  107. package/dist/core/engine/errors.js +20 -0
  108. package/dist/core/engine/event-log-compaction.d.ts +8 -0
  109. package/dist/core/engine/event-log-compaction.js +20 -2
  110. package/dist/core/engine/fenced-write.d.ts +65 -0
  111. package/dist/core/engine/fenced-write.js +71 -0
  112. package/dist/core/engine/finalizer-state.d.ts +28 -0
  113. package/dist/core/engine/finalizer-state.js +16 -0
  114. package/dist/core/engine/handles.d.ts +8 -0
  115. package/dist/core/engine/index.d.ts +34 -16
  116. package/dist/core/engine/index.js +136 -9
  117. package/dist/core/engine/inline-parking.js +3 -2
  118. package/dist/core/engine/internals.d.ts +107 -3
  119. package/dist/core/engine/lease-codec.d.ts +35 -0
  120. package/dist/core/engine/lease-codec.js +32 -0
  121. package/dist/core/engine/lease-deposition.d.ts +66 -0
  122. package/dist/core/engine/lease-deposition.js +10 -0
  123. package/dist/core/engine/lease-errors.d.ts +99 -0
  124. package/dist/core/engine/lease-errors.js +30 -0
  125. package/dist/core/engine/lease-manager.d.ts +114 -0
  126. package/dist/core/engine/lease-manager.js +135 -0
  127. package/dist/core/engine/lifecycle/persist.js +10 -32
  128. package/dist/core/engine/lifecycle/recovered-services.d.ts +8 -6
  129. package/dist/core/engine/lifecycle/recovered-services.js +18 -3
  130. package/dist/core/engine/lifecycle/resume.js +16 -9
  131. package/dist/core/engine/lifecycle/shared.d.ts +8 -1
  132. package/dist/core/engine/lifecycle/start-batch.d.ts +1 -1
  133. package/dist/core/engine/lifecycle/start-batch.js +2 -1
  134. package/dist/core/engine/lifecycle/start-commit.d.ts +9 -0
  135. package/dist/core/engine/lifecycle/start-commit.js +50 -8
  136. package/dist/core/engine/lifecycle/start-or-signal-create.d.ts +58 -0
  137. package/dist/core/engine/lifecycle/start-or-signal-create.js +95 -0
  138. package/dist/core/engine/lifecycle/start-or-signal.d.ts +3 -2
  139. package/dist/core/engine/lifecycle/start-or-signal.js +11 -81
  140. package/dist/core/engine/lifecycle/start-terminal-conflict-purge.d.ts +39 -0
  141. package/dist/core/engine/lifecycle/start-terminal-conflict-purge.js +28 -0
  142. package/dist/core/engine/lifecycle/start.d.ts +4 -4
  143. package/dist/core/engine/lifecycle/start.js +17 -9
  144. package/dist/core/engine/lifecycle/transition.js +17 -5
  145. package/dist/core/engine/lifecycle.d.ts +1 -1
  146. package/dist/core/engine/list-candidate-resolution.js +2 -2
  147. package/dist/core/engine/listing.js +9 -5
  148. package/dist/core/engine/operations-activity.d.ts +6 -13
  149. package/dist/core/engine/operations-activity.js +26 -53
  150. package/dist/core/engine/operations-coordination.d.ts +10 -0
  151. package/dist/core/engine/operations-coordination.js +44 -9
  152. package/dist/core/engine/operations-router.d.ts +6 -0
  153. package/dist/core/engine/operations-router.js +2 -0
  154. package/dist/core/engine/operations-speculate.js +6 -2
  155. package/dist/core/engine/operations-stream.js +12 -2
  156. package/dist/core/engine/operations-time.d.ts +4 -2
  157. package/dist/core/engine/operations-time.js +14 -2
  158. package/dist/core/engine/operations-wait-condition.d.ts +23 -0
  159. package/dist/core/engine/operations-wait-condition.js +62 -0
  160. package/dist/core/engine/ownership-options.d.ts +23 -0
  161. package/dist/core/engine/ownership-options.js +26 -0
  162. package/dist/core/engine/payload-size-policy.d.ts +3 -0
  163. package/dist/core/engine/payload-size-policy.js +4 -0
  164. package/dist/core/engine/pending-updates.d.ts +17 -0
  165. package/dist/core/engine/pending-updates.js +33 -11
  166. package/dist/core/engine/queries.js +1 -1
  167. package/dist/core/engine/registration.d.ts +1 -0
  168. package/dist/core/engine/registration.js +18 -3
  169. package/dist/core/engine/schedule-jitter.d.ts +5 -0
  170. package/dist/core/engine/schedule-jitter.js +10 -0
  171. package/dist/core/engine/schedule-run.d.ts +17 -0
  172. package/dist/core/engine/schedule-run.js +38 -0
  173. package/dist/core/engine/schedule-timer.js +81 -17
  174. package/dist/core/engine/schedules.d.ts +7 -4
  175. package/dist/core/engine/schedules.js +37 -16
  176. package/dist/core/engine/search-attribute-records.d.ts +4 -0
  177. package/dist/core/engine/search-attribute-records.js +17 -0
  178. package/dist/core/engine/signals.d.ts +18 -2
  179. package/dist/core/engine/signals.js +42 -21
  180. package/dist/core/engine/state-utilities.d.ts +49 -2
  181. package/dist/core/engine/state-utilities.js +114 -3
  182. package/dist/core/engine/storage-io.d.ts +16 -2
  183. package/dist/core/engine/storage-io.js +26 -5
  184. package/dist/core/engine/stream-chunk-loading.d.ts +2 -0
  185. package/dist/core/engine/stream-chunk-loading.js +24 -1
  186. package/dist/core/engine/sub-operation.js +25 -6
  187. package/dist/core/engine/termination/cleanup.d.ts +3 -1
  188. package/dist/core/engine/termination/cleanup.js +25 -1
  189. package/dist/core/engine/termination/complete.js +44 -6
  190. package/dist/core/engine/termination/finalizer-activity.d.ts +53 -0
  191. package/dist/core/engine/termination/finalizer-activity.js +30 -0
  192. package/dist/core/engine/termination/finalizer-claim.d.ts +110 -0
  193. package/dist/core/engine/termination/finalizer-claim.js +80 -0
  194. package/dist/core/engine/termination/finalizer.d.ts +48 -0
  195. package/dist/core/engine/termination/finalizer.js +159 -0
  196. package/dist/core/engine/termination/suspend.d.ts +3 -1
  197. package/dist/core/engine/termination.d.ts +1 -0
  198. package/dist/core/engine/termination.js +4 -0
  199. package/dist/core/engine/updates.js +5 -25
  200. package/dist/core/engine/validation/schedule.d.ts +2 -1
  201. package/dist/core/engine/validation/schedule.js +51 -2
  202. package/dist/core/engine/validation.js +32 -5
  203. package/dist/core/engine/waiting-update-response.d.ts +8 -0
  204. package/dist/core/engine/waiting-update-response.js +22 -0
  205. package/dist/core/engine/workflow-concurrency.d.ts +10 -0
  206. package/dist/core/engine/workflow-concurrency.js +136 -0
  207. package/dist/core/engine/workflow-feed.d.ts +4 -5
  208. package/dist/core/engine/workflow-feed.js +4 -1
  209. package/dist/core/engine/workflow-indexes.d.ts +9 -0
  210. package/dist/core/engine/workflow-indexes.js +10 -0
  211. package/dist/core/engine/workflow-state-stream.js +33 -13
  212. package/dist/core/engine/workflow-visibility-queries.d.ts +2 -2
  213. package/dist/core/engine-helpers.js +1 -0
  214. package/dist/core/events/activity-events.d.ts +43 -12
  215. package/dist/core/events/activity-events.js +28 -0
  216. package/dist/core/events/attribute-events.d.ts +2 -3
  217. package/dist/core/events/event-map.d.ts +18 -12
  218. package/dist/core/events/index.d.ts +1 -0
  219. package/dist/core/events/index.js +1 -0
  220. package/dist/core/events/schedule-events.d.ts +71 -0
  221. package/dist/core/events/schedule-events.js +29 -0
  222. package/dist/core/events/signal-events.d.ts +4 -6
  223. package/dist/core/events/system-events.d.ts +29 -19
  224. package/dist/core/events/system-events.js +26 -0
  225. package/dist/core/events/update-events.d.ts +6 -8
  226. package/dist/core/events/workflow-events.d.ts +88 -23
  227. package/dist/core/events/workflow-events.js +26 -0
  228. package/dist/core/failure-categories.js +5 -17
  229. package/dist/core/fault-code.d.ts +9 -3
  230. package/dist/core/fault-code.js +1 -0
  231. package/dist/core/inline-execution-strategy.context-options.d.ts +69 -0
  232. package/dist/core/inline-execution-strategy.context-options.js +56 -0
  233. package/dist/core/inline-execution-strategy.d.ts +31 -36
  234. package/dist/core/inline-execution-strategy.js +16 -27
  235. package/dist/core/list-filter-validation.d.ts +1 -1
  236. package/dist/core/payload-size.d.ts +1 -1
  237. package/dist/core/persisted-data-incompatible-error.d.ts +9 -7
  238. package/dist/core/review/events.d.ts +6 -8
  239. package/dist/core/scheduler/scheduler-class.d.ts +10 -1
  240. package/dist/core/scheduler/scheduler-class.js +38 -11
  241. package/dist/core/scheduler/timer-batch.js +9 -1
  242. package/dist/core/scheduler/timer-sources.d.ts +1 -0
  243. package/dist/core/scheduler/timer-sources.js +11 -5
  244. package/dist/core/session-state.d.ts +0 -1
  245. package/dist/core/session-state.js +2 -2
  246. package/dist/core/start-workflow-validation.d.ts +34 -0
  247. package/dist/core/start-workflow-validation.js +19 -0
  248. package/dist/core/types/activity-verification.d.ts +67 -0
  249. package/dist/core/types/activity-verification.js +0 -0
  250. package/dist/core/types/activity.d.ts +80 -61
  251. package/dist/core/types/bulk.d.ts +50 -9
  252. package/dist/core/types/checkpoint.d.ts +44 -8
  253. package/dist/core/types/list-options.d.ts +146 -0
  254. package/dist/core/types/list-options.js +0 -0
  255. package/dist/core/types/options.d.ts +121 -165
  256. package/dist/core/types/schedules.d.ts +39 -3
  257. package/dist/core/types/services-resolution.d.ts +2 -2
  258. package/dist/core/types/workflow-builder-runtime.d.ts +12 -3
  259. package/dist/core/types/workflow-builder-runtime.js +11 -2
  260. package/dist/core/types/workflow-builder.d.ts +42 -11
  261. package/dist/core/types/workflow-concurrency.d.ts +39 -0
  262. package/dist/core/types/workflow-concurrency.js +0 -0
  263. package/dist/core/types/workflow-context.d.ts +157 -14
  264. package/dist/core/types/workflow-definition.d.ts +53 -10
  265. package/dist/core/types/workflow-function.d.ts +84 -9
  266. package/dist/core/types/workflow-log.d.ts +98 -0
  267. package/dist/core/types/workflow-log.js +0 -0
  268. package/dist/core/types/workflow-registries.d.ts +14 -3
  269. package/dist/core/types/workflow-registry.d.ts +3 -0
  270. package/dist/core/types.d.ts +4 -0
  271. package/dist/core/types.js +4 -0
  272. package/dist/core/versioning.d.ts +9 -39
  273. package/dist/core/versioning.js +2 -12
  274. package/dist/core/weft-error.d.ts +44 -1
  275. package/dist/core/weft-error.js +16 -0
  276. package/dist/core/worker-execution-strategy-options.d.ts +26 -0
  277. package/dist/core/worker-execution-strategy.js +40 -36
  278. package/dist/core/worker-inbound-message.d.ts +38 -0
  279. package/dist/core/worker-inbound-message.js +37 -0
  280. package/dist/core/worker-log-abuse-counter.d.ts +175 -0
  281. package/dist/core/worker-log-abuse-counter.js +107 -0
  282. package/dist/core/worker-message-helpers.d.ts +47 -0
  283. package/dist/core/worker-message-helpers.js +26 -0
  284. package/dist/core/worker-protocol-guard.js +1 -1
  285. package/dist/core/worker-protocol-log.d.ts +56 -0
  286. package/dist/core/worker-protocol-log.js +18 -0
  287. package/dist/core/worker-protocol.d.ts +23 -0
  288. package/dist/core/worker-protocol.js +12 -2
  289. package/dist/core/workflow-version-tuple.d.ts +3 -9
  290. package/dist/core/workflow-version-tuple.js +2 -3
  291. package/dist/diagnostics/format.js +1 -6
  292. package/dist/diagnostics/types.d.ts +4 -5
  293. package/dist/diagnostics/validate.d.ts +0 -1
  294. package/dist/diagnostics/version-check.d.ts +1 -1
  295. package/dist/diagnostics/version-check.js +4 -9
  296. package/dist/index.d.ts +12 -10
  297. package/dist/index.js +29 -3
  298. package/dist/json-schema.js +3 -3
  299. package/dist/mcp/cli.js +19 -19
  300. package/dist/mcp/dispatcher.js +1 -1
  301. package/dist/mcp/http.js +16 -6
  302. package/dist/mcp/protocol.d.ts +2 -0
  303. package/dist/mcp/protocol.js +1 -1
  304. package/dist/mcp/session.d.ts +16 -0
  305. package/dist/mcp/session.js +59 -6
  306. package/dist/mcp/tools.js +73 -6
  307. package/dist/observability/index.js +2 -2
  308. package/dist/server/asyncapi-channels.js +5 -2
  309. package/dist/server/attribute-filters.d.ts +8 -3
  310. package/dist/server/attribute-filters.js +6 -1
  311. package/dist/server/authentication/api-key.d.ts +2 -1
  312. package/dist/server/authentication/api-key.js +5 -2
  313. package/dist/server/authentication/constant-time-api-key.d.ts +15 -0
  314. package/dist/server/authentication/constant-time-api-key.js +24 -0
  315. package/dist/server/authentication/index.d.ts +1 -1
  316. package/dist/server/authentication/index.js +7 -4
  317. package/dist/server/authentication/rotating-api-key-store.d.ts +5 -3
  318. package/dist/server/authentication/rotating-api-key-store.js +19 -11
  319. package/dist/server/engine-event-feed-backend.d.ts +4 -5
  320. package/dist/server/fault-to-http.js +8 -1
  321. package/dist/server/fault-to-json-rpc.js +1 -0
  322. package/dist/server/fleet-event-feed.d.ts +31 -0
  323. package/dist/server/fleet-event-feed.js +157 -0
  324. package/dist/server/handler/index.js +1 -1
  325. package/dist/server/handler/response-helpers.js +2 -1
  326. package/dist/server/handler/route-dispatch.d.ts +6 -3
  327. package/dist/server/handler/route-dispatch.js +2 -2
  328. package/dist/server/handler.js +23 -23
  329. package/dist/server/index.d.ts +32 -2
  330. package/dist/server/index.js +32 -32
  331. package/dist/server/json-rpc-transport-helpers.d.ts +1 -0
  332. package/dist/server/json-rpc-transport-helpers.js +2 -1
  333. package/dist/server/json-rpc-websocket-runtime.d.ts +11 -2
  334. package/dist/server/json-rpc-websocket-runtime.js +1 -0
  335. package/dist/server/json-rpc-websocket-subscriptions.d.ts +10 -0
  336. package/dist/server/json-rpc-websocket-subscriptions.js +29 -0
  337. package/dist/server/json-rpc-websocket-types.d.ts +22 -0
  338. package/dist/server/json-rpc-websocket-types.js +0 -0
  339. package/dist/server/json-rpc-websocket-validation.js +20 -4
  340. package/dist/server/json-rpc-websocket.d.ts +2 -43
  341. package/dist/server/json-rpc-websocket.js +57 -74
  342. package/dist/server/openapi.d.ts +2 -1
  343. package/dist/server/openapi.js +1 -3
  344. package/dist/server/openrpc-document-schema.d.ts +78 -0
  345. package/dist/server/openrpc-document-schema.js +27 -1
  346. package/dist/server/openrpc-errors.d.ts +3 -0
  347. package/dist/server/openrpc-errors.js +2 -1
  348. package/dist/server/openrpc.js +32 -0
  349. package/dist/server/operation-catalog/index.d.ts +1 -1
  350. package/dist/server/operation-catalog/pipeline-helpers.js +1 -0
  351. package/dist/server/operation-catalog/pipeline-stages.js +26 -12
  352. package/dist/server/operation-catalog/pipeline.js +8 -1
  353. package/dist/server/operation-catalog/registry.js +13 -0
  354. package/dist/server/operation-catalog/types.d.ts +20 -9
  355. package/dist/server/operation-fault.d.ts +10 -0
  356. package/dist/server/operation-fault.js +2 -0
  357. package/dist/server/operation-registry.d.ts +12 -11
  358. package/dist/server/operation-registry.js +12 -3
  359. package/dist/server/operations/aggregate-workflows.d.ts +15 -15
  360. package/dist/server/operations/async-activity.d.ts +2 -2
  361. package/dist/server/operations/async-activity.js +12 -7
  362. package/dist/server/operations/bulk-cancel-workflows.d.ts +1 -1
  363. package/dist/server/operations/bulk-cancel-workflows.js +2 -2
  364. package/dist/server/operations/bulk-delete-workflows.d.ts +1 -1
  365. package/dist/server/operations/bulk-delete-workflows.js +2 -2
  366. package/dist/server/operations/bulk-filter-helpers.d.ts +8 -6
  367. package/dist/server/operations/bulk-filter-helpers.js +54 -24
  368. package/dist/server/operations/bulk-mutate-workflow-tags.d.ts +11 -9
  369. package/dist/server/operations/bulk-mutate-workflow-tags.js +2 -2
  370. package/dist/server/operations/bulk-operation-helpers.d.ts +2 -2
  371. package/dist/server/operations/bulk-retry-failed-workflows.d.ts +7 -0
  372. package/dist/server/operations/bulk-retry-failed-workflows.js +64 -0
  373. package/dist/server/operations/bulk-signal-workflows.d.ts +11 -9
  374. package/dist/server/operations/bulk-signal-workflows.js +2 -2
  375. package/dist/server/operations/cancel-schedule.d.ts +1 -1
  376. package/dist/server/operations/create-schedule.d.ts +3 -1
  377. package/dist/server/operations/create-schedule.js +29 -11
  378. package/dist/server/operations/fleet-events-subscription.d.ts +54 -0
  379. package/dist/server/operations/fleet-events-subscription.js +99 -0
  380. package/dist/server/operations/fork-workflow.d.ts +1 -1
  381. package/dist/server/operations/fork-workflow.js +3 -2
  382. package/dist/server/operations/get-checkpoint-at.d.ts +1 -1
  383. package/dist/server/operations/get-registry.d.ts +1 -1
  384. package/dist/server/operations/get-retention-overview.d.ts +1 -1
  385. package/dist/server/operations/get-review.d.ts +1 -1
  386. package/dist/server/operations/get-schedule.d.ts +1 -1
  387. package/dist/server/operations/get-stream-chunks.d.ts +1 -1
  388. package/dist/server/operations/get-system-metrics.d.ts +2 -2
  389. package/dist/server/operations/get-task-diagnostics.d.ts +45 -6
  390. package/dist/server/operations/get-task-diagnostics.js +101 -7
  391. package/dist/server/operations/get-update-result.d.ts +1 -1
  392. package/dist/server/operations/get-workflow-attributes.d.ts +1 -1
  393. package/dist/server/operations/get-workflow-events.d.ts +1 -1
  394. package/dist/server/operations/get-workflow-result.d.ts +1 -1
  395. package/dist/server/operations/get-workflow-timeline.d.ts +1 -1
  396. package/dist/server/operations/get-workflow.d.ts +1 -1
  397. package/dist/server/operations/list-checkpoints.d.ts +1 -1
  398. package/dist/server/operations/list-reviews.d.ts +1 -1
  399. package/dist/server/operations/list-schedules.d.ts +1 -1
  400. package/dist/server/operations/list-task-queues.d.ts +2 -2
  401. package/dist/server/operations/list-workers.d.ts +2 -2
  402. package/dist/server/operations/list-workflows.d.ts +1 -1
  403. package/dist/server/operations/operation-helpers.d.ts +16 -1
  404. package/dist/server/operations/operation-helpers.js +15 -3
  405. package/dist/server/operations/pause-schedule.d.ts +1 -1
  406. package/dist/server/operations/purge-workflows.d.ts +5 -5
  407. package/dist/server/operations/purge-workflows.js +2 -2
  408. package/dist/server/operations/query-workflow.d.ts +1 -1
  409. package/dist/server/operations/query-workflow.js +3 -2
  410. package/dist/server/operations/recover-all.d.ts +1 -1
  411. package/dist/server/operations/replay-workflow.d.ts +1 -1
  412. package/dist/server/operations/resume-schedule.d.ts +1 -1
  413. package/dist/server/operations/set-workflow-attributes.d.ts +1 -1
  414. package/dist/server/operations/set-workflow-attributes.js +6 -3
  415. package/dist/server/operations/signal-workflow.js +8 -3
  416. package/dist/server/operations/single-workflow-tag-mutation.js +13 -3
  417. package/dist/server/operations/start-or-signal-workflow.d.ts +6 -1
  418. package/dist/server/operations/start-or-signal-workflow.js +14 -24
  419. package/dist/server/operations/start-workflow-options.d.ts +6 -0
  420. package/dist/server/operations/start-workflow-rest-input.d.ts +14 -0
  421. package/dist/server/operations/start-workflow-rest-input.js +31 -0
  422. package/dist/server/operations/start-workflow.d.ts +1 -1
  423. package/dist/server/operations/start-workflow.js +8 -23
  424. package/dist/server/operations/storage.d.ts +6 -6
  425. package/dist/server/operations/storage.js +24 -14
  426. package/dist/server/operations/stream-workflow-sse.d.ts +1 -1
  427. package/dist/server/operations/submit-review-decision.d.ts +1 -1
  428. package/dist/server/operations/submit-review-decision.js +6 -3
  429. package/dist/server/operations/update-schedule.d.ts +1 -1
  430. package/dist/server/operations/update-schedule.js +7 -4
  431. package/dist/server/operations/update-workflow.d.ts +1 -1
  432. package/dist/server/operations/update-workflow.js +7 -3
  433. package/dist/server/operations/worker-drain.d.ts +8 -8
  434. package/dist/server/operations/worker-drain.js +11 -8
  435. package/dist/server/operations/workflow-events-subscription.d.ts +7 -8
  436. package/dist/server/operations/workflow-events-subscription.js +43 -8
  437. package/dist/server/rest-binding.d.ts +3 -1
  438. package/dist/server/rest-bindings.js +12 -0
  439. package/dist/server/rest-body.d.ts +10 -0
  440. package/dist/server/rest-body.js +80 -0
  441. package/dist/server/runtime/authentication-bridge.d.ts +1 -0
  442. package/dist/server/runtime/authentication-bridge.js +33 -6
  443. package/dist/server/runtime/client-visible-events.d.ts +3 -0
  444. package/dist/server/runtime/client-visible-events.js +65 -0
  445. package/dist/server/runtime/context.d.ts +7 -0
  446. package/dist/server/runtime/event-broadcasting.d.ts +6 -0
  447. package/dist/server/runtime/event-broadcasting.js +72 -38
  448. package/dist/server/runtime/retry.d.ts +1 -0
  449. package/dist/server/runtime/retry.js +14 -0
  450. package/dist/server/runtime/shutdown.d.ts +7 -6
  451. package/dist/server/runtime/shutdown.js +6 -1
  452. package/dist/server/runtime/task-polling.js +61 -20
  453. package/dist/server/runtime/task-reconciliation.js +9 -1
  454. package/dist/server/runtime/task-result-resolution.d.ts +15 -0
  455. package/dist/server/runtime/task-result-resolution.js +81 -0
  456. package/dist/server/runtime/websocket-stream.d.ts +20 -1
  457. package/dist/server/runtime/websocket-stream.js +173 -7
  458. package/dist/server/runtime/websocket-upgrade.js +22 -3
  459. package/dist/server/runtime/websocket-worker.d.ts +1 -1
  460. package/dist/server/runtime/websocket-worker.js +38 -30
  461. package/dist/server/serve-internals.d.ts +3 -1
  462. package/dist/server/serve-internals.js +18 -2
  463. package/dist/server/task-state.d.ts +30 -0
  464. package/dist/server/task-state.js +28 -0
  465. package/dist/server/workflow-event-feed.d.ts +36 -115
  466. package/dist/server/workflow-event-feed.js +92 -27
  467. package/dist/service-worker/index.js +30 -30
  468. package/dist/storage/auto.js +1 -1
  469. package/dist/storage/bun-sql.js +24 -0
  470. package/dist/storage/compressed-storage.js +1 -1
  471. package/dist/storage/default-scope.d.ts +7 -4
  472. package/dist/storage/http.js +2 -2
  473. package/dist/storage/index.d.ts +76 -4
  474. package/dist/storage/indexeddb.js +1 -1
  475. package/dist/storage/interface.d.ts +163 -0
  476. package/dist/storage/interface.js +1 -1
  477. package/dist/storage/key-prefixes.d.ts +1 -1
  478. package/dist/storage/key-prefixes.js +10 -0
  479. package/dist/storage/lmdb.d.ts +4 -3
  480. package/dist/storage/lmdb.js +1 -1
  481. package/dist/storage/memory.js +1 -1
  482. package/dist/storage/neon-batch.d.ts +30 -0
  483. package/dist/storage/neon-batch.js +30 -0
  484. package/dist/storage/neon-value-mapping.d.ts +30 -3
  485. package/dist/storage/neon-value-mapping.js +12 -0
  486. package/dist/storage/neon.d.ts +16 -0
  487. package/dist/storage/neon.js +9 -4
  488. package/dist/storage/node-sqlite.js +23 -0
  489. package/dist/storage/postgres-key-value-queries.d.ts +69 -44
  490. package/dist/storage/postgres-key-value-queries.js +62 -24
  491. package/dist/storage/resolve.js +1 -1
  492. package/dist/storage/scoped-storage.js +1 -1
  493. package/dist/storage/testing.d.ts +168 -0
  494. package/dist/storage/testing.js +2 -0
  495. package/dist/storage/turso.d.ts +8 -0
  496. package/dist/storage/turso.js +2 -2
  497. package/dist/storage/typed-storage.js +1 -1
  498. package/dist/storage/web-extension.js +1 -1
  499. package/dist/testing/index.js +20 -20
  500. package/dist/version.d.ts +1 -1
  501. package/dist/version.js +1 -1
  502. package/dist/worker/protocol.js +1 -1
  503. package/dist/workers/worker-replay-state.d.ts +32 -0
  504. package/dist/workers/worker-replay-state.js +35 -0
  505. package/dist/workers/worker-state-namespace.d.ts +21 -0
  506. package/dist/workers/worker-state-namespace.js +13 -0
  507. package/dist/workers/workflow-runner.d.ts +19 -15
  508. package/dist/workers/workflow-runner.js +72 -60
  509. package/dist/workers/workflow-worker-entry.js +5 -2
  510. package/package.json +5 -1
@@ -1,11 +1,14 @@
1
1
  import { KEYS } from "../../../storage/interface.js";
2
2
  import { deserializeCheckpoint, serializeCheckpoint } from "../../checkpoint.js";
3
+ import { RegExpExtensionDecodeError } from "../../codec/extension-codec.js";
3
4
  import { Context, setContextWorkflowInterceptor } from "../../context.js";
4
5
  import { EMPTY_EVENT_HEAD } from "../../event-log.js";
5
6
  import { WorkflowRecoverySkippedEvent, WorkflowStartedEvent } from "../../events.js";
6
7
  import { createCancelHandlerRegistration, resetCancelHandlers } from "../cancel-handlers.js";
7
8
  import { forgetCommittedCheckpointBytes } from "../checkpoint-commit-snapshots.js";
9
+ import { hydrateCheckpointReplayState } from "../checkpoint-replay.js";
8
10
  import { WorkflowTypeNotRegisteredForRecoveryError } from "../errors.js";
11
+ import { commitFencedEngineWrite } from "../fenced-write.js";
9
12
  import { getWorkflowExecutionStartedAt } from "../handles.js";
10
13
  import { normalizeForkStep, selectPersistedWorkflowStartHeaders } from "../state-utilities.js";
11
14
  import { loadWorkflowState } from "../storage-io.js";
@@ -73,7 +76,15 @@ export async function recoverAll(internals, callbacks, options) {
73
76
  callbacks.dispatchEvent(new WorkflowRecoverySkippedEvent(entry.workflow.workflowId, entry.workflow.type, "type-not-registered"));
74
77
  continue;
75
78
  }
76
- handles.push(await resume(internals, entry.workflowId, callbacks));
79
+ try {
80
+ handles.push(await resume(internals, entry.workflowId, callbacks));
81
+ } catch (error) {
82
+ if (error instanceof RegExpExtensionDecodeError) {
83
+ await callbacks.failWorkflowForCheckpointDecodeError(entry.workflowId, error);
84
+ continue;
85
+ }
86
+ throw error;
87
+ }
77
88
  }
78
89
  return handles;
79
90
  }
@@ -100,8 +111,8 @@ export async function fork(internals, sourceWorkflowId, options, callbacks) {
100
111
  throw Error(`Checkpoint not found at step ${String(fromStep)} for workflow "${sourceWorkflowId}"`);
101
112
  throw Error(`Checkpoint not found for workflow "${sourceWorkflowId}"`);
102
113
  }
103
- const sourceCheckpoint = deserializeCheckpoint(checkpointBytes), preparedExecutionState = derivePreparedExecutionState(internals, sourceWorkflowId, sourceState, sourceCheckpoint, registration, callbacks), sourceWorkflowHeaders = internals.workflowHeaders.get(sourceWorkflowId) ?? await loadWorkflowStartHeaders(internals, sourceWorkflowId, callbacks), persistedWorkflowStartHeaders = selectPersistedWorkflowStartHeaders(sourceWorkflowHeaders), workflowId = crypto.randomUUID(), forkedAt = internals.options.getNow(), lineage = createForkLineage(internals, sourceWorkflowId, sourceCheckpoint, callbacks), forkCheckpoint = {
104
- ...preparedExecutionState.checkpoint,
114
+ const storedSourceCheckpoint = deserializeCheckpoint(checkpointBytes), sourceCheckpoint = await hydrateCheckpointReplayState(internals.storage, sourceWorkflowId, storedSourceCheckpoint), preparedExecutionState = derivePreparedExecutionState(internals, sourceWorkflowId, sourceState, sourceCheckpoint, registration, callbacks), sourceWorkflowHeaders = internals.workflowHeaders.get(sourceWorkflowId) ?? await loadWorkflowStartHeaders(internals, sourceWorkflowId, callbacks), persistedWorkflowStartHeaders = selectPersistedWorkflowStartHeaders(sourceWorkflowHeaders), workflowId = crypto.randomUUID(), forkedAt = internals.options.getNow(), lineage = createForkLineage(internals, sourceWorkflowId, sourceCheckpoint, callbacks), { accumulatedResultReplayWatermark: _sourceReplayWatermark, ...sourceCheckpointForFork } = preparedExecutionState.checkpoint, forkCheckpoint = {
115
+ ...sourceCheckpointForFork,
105
116
  createdAt: forkedAt,
106
117
  workflowId,
107
118
  searchAttributes: buildForkSearchAttributes(internals, preparedExecutionState.checkpoint, lineage, callbacks)
@@ -109,7 +120,7 @@ export async function fork(internals, sourceWorkflowId, options, callbacks) {
109
120
  let forkStarted = !1;
110
121
  try {
111
122
  const forkCheckpointBytes = serializeCheckpoint(forkCheckpoint);
112
- await internals.storage.batch(buildForkBatchOperations(internals, workflowId, forkState, forkCheckpoint, forkCheckpointBytes, persistedWorkflowStartHeaders, callbacks));
123
+ await commitFencedEngineWrite(internals, buildForkBatchOperations(internals, workflowId, forkState, forkCheckpoint, forkCheckpointBytes, persistedWorkflowStartHeaders, callbacks), [], () => Error(`Fork of workflow "${workflowId}" lost its CAS race.`));
113
124
  internals.eventLogHeads.set(workflowId, EMPTY_EVENT_HEAD);
114
125
  setWorkflowStartHeaders(internals, workflowId, persistedWorkflowStartHeaders, callbacks);
115
126
  const handle = launchWorkflowFromCheckpoint(internals, workflowId, forkState, forkCheckpoint, registration, callbacks);
@@ -146,7 +157,8 @@ function launchInlineWorkflowFromCheckpoint(internals, workflowId, state, checkp
146
157
  searchAttributeSchema: registration.searchAttributes
147
158
  },
148
159
  sleepReferenceTime: checkpoint.createdAt,
149
- ...state.executionDeadline !== void 0 && { deadline: state.executionDeadline }
160
+ ...state.executionDeadline !== void 0 && { deadline: state.executionDeadline },
161
+ ...internals.options.onLog != null && { logSink: internals.options.onLog }
150
162
  });
151
163
  setContextWorkflowInterceptor(context, getComposedWorkflowInterceptor(internals));
152
164
  if (internals.options.development)
@@ -1,7 +1,7 @@
1
1
  export { EMPTY_STORAGE_VALUE, createWorkflowHandle, loadTerminalCleanupTrackedState, loadWorkflowStartHeaders, normalizeStartWorkflowTags, processPendingUpdatesAfterReplay, setWorkflowStartHeaders, type LifecycleCallbacks, type RecoverAllOptions, } from './lifecycle/shared.ts';
2
2
  export { createWorkflowVersionTuple, derivePreparedExecutionState, prepareResumeState, throwVersionMismatch, workflowStateWithVersionTuple, workflowVersionTupleFromState, } from './lifecycle/persist.ts';
3
3
  export { createInitialCheckpoint, createInitialWorkflowState, parseStartOptionDuration, resolveScheduledStartAt, start, startWorkflow, } from './lifecycle/start.ts';
4
- export { startOrSignal, startWithIdempotency, type StartOrSignalCallbacks, } from './lifecycle/start-or-signal.ts';
4
+ export { startOrSignal, startWithIdempotency, type StartOrSignalCallbacks, type StartOrSignalResult, } from './lifecycle/start-or-signal.ts';
5
5
  export { buildInitialSearchAttributeOperations, buildStartBatchOperations, validateSearchAttributes, } from './lifecycle/start-batch.ts';
6
6
  export { beginWorkflowExecution, runWorkflowStartInterceptor, startWorkflowExecution, } from './lifecycle/start-exec.ts';
7
7
  export { buildForkBatchOperations, buildForkSearchAttributes, createForkLineage, createForkedWorkflowState, } from './lifecycle/fork-helpers.ts';
@@ -1,5 +1,5 @@
1
1
  import { intersectIdentifierSets } from "./state-utilities.js";
2
- import { getWorkflowVisibilityWatermark } from "./workflow-indexes.js";
2
+ import { getCachedWorkflowVisibilityWatermark } from "./workflow-indexes.js";
3
3
  import { queryAttributeIndex, resolveConstrainedIds } from "./workflow-state-stream.js";
4
4
  import {
5
5
  queryWorkflowIdPrefixCandidates,
@@ -50,7 +50,7 @@ export async function resolveListCandidateIds(internals, filter, normalizedTagFi
50
50
  resolveConstrainedIds(internals, filter, normalizedTagFilters),
51
51
  resolveFailureCategoryCandidateIds(internals, filter?.failureCategory)
52
52
  ]);
53
- if (await getWorkflowVisibilityWatermark(internals.storage) === "stale") {
53
+ if (await getCachedWorkflowVisibilityWatermark(internals) === "stale") {
54
54
  const queries = filter === void 0 ? [] : collectVisibilityQueries(internals, filter, ["idPrefix"]), visibilitySets = await Promise.all(queries);
55
55
  return combineCandidateSets([
56
56
  baseConstrainedIds,
@@ -5,7 +5,12 @@ import { isFailureCategory, normalizeListFilter } from "../list-filter-validatio
5
5
  import { buildIndexOperations, validateAttributeType } from "../search-attributes.js";
6
6
  import { normalizeWorkflowTags } from "../workflow-tags.js";
7
7
  import { mutateWorkflowTags, validateAttributeValueSizes } from "./attributes-tags.js";
8
+ import { CONSTRAINED_ID_CHUNK_SIZE } from "./candidate-read-batching.js";
8
9
  import { resolveListCandidateIds } from "./list-candidate-resolution.js";
10
+ import {
11
+ readSearchAttributesForFilter,
12
+ readSearchAttributesForStates
13
+ } from "./search-attribute-records.js";
9
14
  import { matchesListFilter, paginateWorkflowSummaries } from "./state-utilities.js";
10
15
  import { decodeWorkflowState, normalizeBulkFilterNumber } from "./validation.js";
11
16
  import { MAX_LIST_SCAN_ROWS, WorkflowListScanCapExceededError } from "./workflow-indexes.js";
@@ -18,19 +23,18 @@ export async function list(internals, filter, options) {
18
23
  const normalizedFilter = filter === void 0 ? void 0 : normalizeListFilter(filter), normalizedTagFilters = normalizeWorkflowTags(normalizedFilter?.tags), constrainedIds = await resolveListCandidateIds(internals, normalizedFilter, normalizedTagFilters), items = constrainedIds !== null ? await collectSummariesFromConstrainedIds(internals, constrainedIds, normalizedFilter, normalizedTagFilters, options) : await collectSummariesFromFullScan(internals, normalizedFilter, normalizedTagFilters, options);
19
24
  return paginateWorkflowSummaries(sortSummariesByCreatedAtDescending(items), normalizedFilter);
20
25
  }
21
- const CONSTRAINED_ID_CHUNK_SIZE = 64;
22
26
  async function collectSummariesFromConstrainedIds(internals, constrainedIds, normalizedFilter, normalizedTagFilters, options) {
23
27
  const orderedIds = [...constrainedIds];
24
28
  if (orderedIds.length > MAX_LIST_SCAN_ROWS)
25
29
  throw new WorkflowListScanCapExceededError(MAX_LIST_SCAN_ROWS);
26
30
  const items = [];
27
31
  for (let start = 0;start < orderedIds.length; start += CONSTRAINED_ID_CHUNK_SIZE) {
28
- const chunkIds = orderedIds.slice(start, start + CONSTRAINED_ID_CHUNK_SIZE), chunkBytes = await Promise.all(chunkIds.map((workflowId) => internals.storage.get(KEYS.workflow(workflowId)))), matchingStates = [];
32
+ const chunkIds = orderedIds.slice(start, start + CONSTRAINED_ID_CHUNK_SIZE), chunkBytes = await Promise.all(chunkIds.map((workflowId) => internals.storage.get(KEYS.workflow(workflowId)))), searchAttributesByWorkflowId = await readSearchAttributesForStates(internals, chunkBytes, normalizedFilter), matchingStates = [];
29
33
  for (const stateBytes of chunkBytes) {
30
34
  if (!stateBytes)
31
35
  continue;
32
36
  const state = decodeWorkflowState(stateBytes);
33
- if (!matchesListFilter(state, normalizedFilter, constrainedIds, normalizedTagFilters))
37
+ if (!matchesListFilter(state, normalizedFilter, constrainedIds, normalizedTagFilters, searchAttributesByWorkflowId.get(state.id) ?? null))
34
38
  continue;
35
39
  matchingStates.push(state);
36
40
  }
@@ -47,8 +51,8 @@ async function collectSummariesFromFullScan(internals, normalizedFilter, normali
47
51
  scanned += 1;
48
52
  if (scanned > MAX_LIST_SCAN_ROWS)
49
53
  throw new WorkflowListScanCapExceededError(MAX_LIST_SCAN_ROWS);
50
- const state = decodeWorkflowState(value);
51
- if (!matchesListFilter(state, normalizedFilter, null, normalizedTagFilters))
54
+ const state = decodeWorkflowState(value), searchAttributes = await readSearchAttributesForFilter(internals, state.id, normalizedFilter);
55
+ if (!matchesListFilter(state, normalizedFilter, null, normalizedTagFilters, searchAttributes))
52
56
  continue;
53
57
  const attributeBytes = shouldReadFailureCategoryAttribute(state, options) ? await internals.storage.get(KEYS.attribute(state.id)) : null;
54
58
  items.push(summaryFromState(state, failureCategoryFromAttributeBytes(attributeBytes)));
@@ -1,9 +1,10 @@
1
1
  import type { ContextOperationRequest } from '../context.ts';
2
2
  import type { ComposedActivityInterceptor, ComposedWorkflowInterceptor } from '../interceptor.ts';
3
- import type { ActivityContext, ActivityVerificationResult } from '../types.ts';
3
+ import type { ActivityContext, ActivityVerificationResult, OperationOutcome } from '../types.ts';
4
4
  import { buildActivityVerificationContext, type ActivityReconciliationMetadata } from './activity-reconciliation.ts';
5
5
  import type { EngineInternals } from './internals.ts';
6
6
  import type { SpeculativeExecutionState } from './speculative-execution-state.ts';
7
+ import type { CapturedRejectionReason } from './strategy-helpers.ts';
7
8
  export type ActivityFunctionWithMetadata = ((...arguments_: unknown[]) => unknown) & ActivityReconciliationMetadata & {
8
9
  verify?: (result: unknown, context?: ReturnType<typeof buildActivityVerificationContext>) => Promise<ActivityVerificationResult> | ActivityVerificationResult;
9
10
  compensate?: (input: unknown, output: unknown) => Promise<void> | void;
@@ -13,19 +14,11 @@ type ActivityOperation = Extract<ContextOperationRequest, {
13
14
  }>;
14
15
  export type ActivityOperationCallbacks = {
15
16
  runOperationWithResult: (workflowId: string, operation: ActivityOperation, execute: () => Promise<unknown>) => Promise<void>;
17
+ finalizePendingTimelineEntry: (workflowId: string, status: 'completed' | 'failed', value: unknown) => void;
18
+ feedOperationResult: (workflowId: string, outcome: OperationOutcome, originalReason?: CapturedRejectionReason) => void;
16
19
  getComposedActivityInterceptor: () => ComposedActivityInterceptor | null;
17
20
  getComposedWorkflowInterceptor: () => ComposedWorkflowInterceptor | null;
18
21
  };
19
- export declare function getActivityFunctionWithMetadata(internals: EngineInternals, workflowId: string, operation: ActivityOperation): ActivityFunctionWithMetadata | undefined;
20
- /**
21
- * Resolve the activity function for a given operation. Uses the same
22
- * per-workflow-first-then-global ordering as `getActivityFunctionWithMetadata`.
23
- * For inline-mode callers that pass an `operation.fn` directly, the registries
24
- * are still consulted first so a workflow's locally-scoped activity wins over
25
- * the bare callable. Throws `ActivityResolutionError` when neither path
26
- * resolves.
27
- */
28
- export declare function resolveActivityFunction(internals: EngineInternals, workflowId: string, operation: ActivityOperation): (...arguments_: unknown[]) => unknown;
29
22
  export declare function buildActivityVerification(_internals: EngineInternals, activityName: string, verify: ActivityFunctionWithMetadata['verify'], context: ReturnType<typeof buildActivityVerificationContext>, result: unknown): Promise<void>;
30
23
  export declare function buildActivityCompensation(internals: EngineInternals, workflowId: string, operation: ActivityOperation, result: unknown): (() => Promise<void>) | undefined;
31
24
  export declare function invokeWorkerActivity(internals: EngineInternals, operationId: string, activityName: string, input: unknown, attempt: number): Promise<unknown>;
@@ -34,7 +27,7 @@ export declare function invokeInlineActivity(internals: EngineInternals, workflo
34
27
  * Execute an activity function, dispatching to a Web Worker pool when
35
28
  * `activityExecution` is configured, or running inline on the main thread.
36
29
  */
37
- export declare function executeActivity(internals: EngineInternals, workflowId: string, operation: ActivityOperation, callbacks: ActivityOperationCallbacks, attempt?: number): Promise<unknown>;
38
- export declare function executeActivityOperationResult(internals: EngineInternals, workflowId: string, operation: ActivityOperation, callbacks: ActivityOperationCallbacks, speculativeState?: SpeculativeExecutionState): Promise<unknown>;
30
+ export declare function executeActivity(internals: EngineInternals, workflowId: string, operation: ActivityOperation, callbacks: ActivityOperationCallbacks, attempt?: number, coordinatorSignal?: AbortSignal): Promise<unknown>;
31
+ export declare function executeActivityOperationResult(internals: EngineInternals, workflowId: string, operation: ActivityOperation, callbacks: ActivityOperationCallbacks, coordinatorSignal?: AbortSignal, speculativeState?: SpeculativeExecutionState): Promise<unknown>;
39
32
  export declare function processActivityOperation(internals: EngineInternals, workflowId: string, operation: ActivityOperation, callbacks: ActivityOperationCallbacks): Promise<void>;
40
33
  export {};
@@ -1,57 +1,27 @@
1
1
  import { assertPayloadWithinLimit } from "../payload-size.js";
2
+ import {
3
+ buildActivityContext,
4
+ clearLastHeartbeatForStep,
5
+ warnIfRetryMissingHeartbeat
6
+ } from "./activity-heartbeat-tracking.js";
7
+ import { resolvePerAttemptTimeout, withPerAttemptTimeout } from "./activity-per-attempt-timeout.js";
2
8
  import {
3
9
  buildActivityReconciliationReference,
4
10
  buildActivityVerificationContext,
5
11
  createCompletedActivityReconciliationRecord,
6
12
  resolveActivityIdempotencyKey,
7
13
  resolveStartedActivityReconciliationRecord,
8
- validateActivityResultForReconciliation,
9
- writeActivityReconciliationTransition
14
+ stageActivityReconciliationTransitionWithAtomicWorkflowCommit,
15
+ validateActivityResultForReconciliation
10
16
  } from "./activity-reconciliation.js";
17
+ import { getActivityFunctionWithMetadata, resolveActivityFunction } from "./activity-resolution.js";
11
18
  import {
12
19
  AsyncActivityDeferral,
13
20
  deriveAsyncActivityToken,
14
21
  driveWorkflowInterceptorGenerator,
15
22
  parkDeferredAsyncActivity
16
23
  } from "./async-activity-completion.js";
17
- import { ActivityResolutionError } from "./errors.js";
18
24
  import { callActivityFunction } from "./state-utilities.js";
19
- function resolveActivityViaRegistries(internals, workflowId, activityName) {
20
- const workflowType = internals.workflowTypeByWorkflowId.get(workflowId);
21
- if (workflowType !== void 0) {
22
- const perWorkflow = internals.activityRegistriesByWorkflow.get(workflowType);
23
- if (perWorkflow !== void 0) {
24
- const perWorkflowFn = perWorkflow.resolve(activityName);
25
- if (perWorkflowFn)
26
- return { fn: perWorkflowFn, workflowType };
27
- }
28
- const globalFn = internals.activityRegistry.resolve(activityName);
29
- if (globalFn)
30
- return { fn: globalFn, workflowType };
31
- return;
32
- }
33
- const globalFn = internals.activityRegistry.resolve(activityName);
34
- if (globalFn)
35
- return { fn: globalFn, workflowType: "<unknown>" };
36
- return;
37
- }
38
- export function getActivityFunctionWithMetadata(internals, workflowId, operation) {
39
- const resolved = resolveActivityViaRegistries(internals, workflowId, operation.activityName);
40
- if (resolved)
41
- return resolved.fn;
42
- if (typeof operation.fn === "function")
43
- return operation.fn;
44
- return;
45
- }
46
- export function resolveActivityFunction(internals, workflowId, operation) {
47
- const resolved = resolveActivityViaRegistries(internals, workflowId, operation.activityName);
48
- if (resolved)
49
- return resolved.fn;
50
- if (operation.fn)
51
- return operation.fn;
52
- const workflowType = internals.workflowTypeByWorkflowId.get(workflowId) ?? "<unknown>";
53
- throw new ActivityResolutionError(workflowType, operation.activityName);
54
- }
55
25
  export function buildActivityVerification(_internals, activityName, verify, context, result) {
56
26
  return (async () => {
57
27
  const verified = await verify?.(result, context);
@@ -99,16 +69,12 @@ function getActivityAttempt(operation) {
99
69
  const attempt = operation.attempt;
100
70
  return typeof attempt === "number" && Number.isInteger(attempt) && attempt > 0 ? attempt : 1;
101
71
  }
102
- export async function executeActivity(internals, workflowId, operation, callbacks, attempt = getActivityAttempt(operation)) {
103
- const activityInput = operation.input, abortController = internals.inlineStrategy?.getAbortController(workflowId), asyncToken = deriveAsyncActivityToken(workflowId, operation.step ?? 0, attempt), activityContext = {
104
- signal: abortController?.signal ?? new AbortController().signal,
105
- heartbeat: (details) => {
106
- internals.heartbeatDetails.set(workflowId, details);
107
- },
108
- completeAsync: () => {
109
- throw new AsyncActivityDeferral(asyncToken);
110
- }
111
- }, invokeActivity = internals.activityWorkerDispatcher ? (activityName, input) => invokeWorkerActivity(internals, operation.operationId, activityName, input, attempt) : (activityName, input) => invokeInlineActivity(internals, workflowId, operation, activityContext, activityName, input), composedActivity = callbacks.getComposedActivityInterceptor(), executeWithActivityInterceptors = async (activityName, input, headers) => {
72
+ export async function executeActivity(internals, workflowId, operation, callbacks, attempt = getActivityAttempt(operation), coordinatorSignal) {
73
+ const activityInput = operation.input, step = operation.step ?? 0;
74
+ warnIfRetryMissingHeartbeat(internals, workflowId, step, attempt);
75
+ const asyncToken = deriveAsyncActivityToken(workflowId, step, attempt), { perAttemptTimeoutMs, attemptAbortController, activitySignal } = resolvePerAttemptTimeout(internals, workflowId, operation, coordinatorSignal), activityContext = buildActivityContext(internals, workflowId, step, activitySignal, () => {
76
+ throw new AsyncActivityDeferral(asyncToken);
77
+ }), invokeActivity = internals.activityWorkerDispatcher ? (activityName, input) => invokeWorkerActivity(internals, operation.operationId, activityName, input, attempt) : (activityName, input) => withPerAttemptTimeout(invokeInlineActivity(internals, workflowId, operation, activityContext, activityName, input), perAttemptTimeoutMs, activityName, attempt, attemptAbortController), composedActivity = callbacks.getComposedActivityInterceptor(), executeWithActivityInterceptors = async (activityName, input, headers) => {
112
78
  if (!composedActivity)
113
79
  return invokeActivity(activityName, input);
114
80
  const activityInterception = {
@@ -141,7 +107,7 @@ export async function executeActivity(internals, workflowId, operation, callback
141
107
  copyActivityHeadersToOperation(operation, headers);
142
108
  return result;
143
109
  }
144
- export async function executeActivityOperationResult(internals, workflowId, operation, callbacks, speculativeState) {
110
+ export async function executeActivityOperationResult(internals, workflowId, operation, callbacks, coordinatorSignal, speculativeState) {
145
111
  const activity = getActivityFunctionWithMetadata(internals, workflowId, operation), idempotencyKey = resolveActivityIdempotencyKey(activity, operation), operationAttempt = getActivityAttempt(operation);
146
112
  if (idempotencyKey !== void 0) {
147
113
  const reference = await buildActivityReconciliationReference(workflowId, operation.activityName, idempotencyKey), started = await resolveStartedActivityReconciliationRecord(internals, workflowId, operation, reference, activity, idempotencyKey, operationAttempt);
@@ -149,16 +115,20 @@ export async function executeActivityOperationResult(internals, workflowId, oper
149
115
  validateActivityResultForReconciliation(started.completedResult, internals.options.payloadSizePolicy.maxBytes);
150
116
  return started.completedResult;
151
117
  }
152
- const result = await executeActivity(internals, workflowId, operation, callbacks, started.attempt);
118
+ const result = await executeActivity(internals, workflowId, operation, callbacks, started.attempt, coordinatorSignal);
153
119
  validateActivityResultForReconciliation(result, internals.options.payloadSizePolicy.maxBytes);
154
120
  await finalizeActivityResult(internals, workflowId, operation, result, activity, idempotencyKey, started.attempt, speculativeState, !0);
155
121
  const completedRecord = createCompletedActivityReconciliationRecord(started, result, internals.options.getNow());
156
- await writeActivityReconciliationTransition(internals.storage, reference, started, completedRecord);
122
+ stageActivityReconciliationTransitionWithAtomicWorkflowCommit(internals, workflowId, reference, started, completedRecord);
123
+ if (!speculativeState)
124
+ clearLastHeartbeatForStep(internals, workflowId, operation.step ?? 0);
157
125
  return result;
158
126
  }
159
- const result = await executeActivity(internals, workflowId, operation, callbacks, operationAttempt);
127
+ const result = await executeActivity(internals, workflowId, operation, callbacks, operationAttempt, coordinatorSignal);
160
128
  assertPayloadWithinLimit(result, internals.options.payloadSizePolicy.maxBytes, "activity result");
161
129
  await finalizeActivityResult(internals, workflowId, operation, result, activity, idempotencyKey, operationAttempt, speculativeState);
130
+ if (!speculativeState)
131
+ clearLastHeartbeatForStep(internals, workflowId, operation.step ?? 0);
162
132
  return result;
163
133
  }
164
134
  async function finalizeActivityResult(internals, workflowId, operation, result, activity, idempotencyKey, attempt, speculativeState, awaitSpeculativeVerification = !1) {
@@ -187,6 +157,9 @@ export async function processActivityOperation(internals, workflowId, operation,
187
157
  operationId: operation.operationId,
188
158
  step: operation.step ?? 0,
189
159
  attempt: getActivityAttempt(operation)
160
+ }, {
161
+ feedOperationResult: callbacks.feedOperationResult,
162
+ finalizeTimeline: callbacks.finalizePendingTimelineEntry
190
163
  });
191
164
  throw error;
192
165
  }
@@ -15,6 +15,16 @@ type RaceOperation = Extract<ContextOperationRequest, {
15
15
  type RunAllOperation = Extract<ContextOperationRequest, {
16
16
  type: 'run-all';
17
17
  }>;
18
+ /**
19
+ * Reject a `ctx.race` / `ctx.all` whose branches wait on the SAME signal name,
20
+ * recursively through nested `race` / `parallel` branches. Sibling wait-signal
21
+ * branches share the `${workflowId}:${signalName}` waiter key, so two anywhere in
22
+ * the coordination tree would clobber each other at registration, leaving one
23
+ * branch permanently unreachable (the run would hang). Reject the meaningless
24
+ * shape deterministically rather than silently dropping a branch. Distinct names
25
+ * (the event-or-close idiom) are unaffected.
26
+ */
27
+ export declare function assertSupportedSignalBranches(operations: readonly ContextOperationRequest[]): void;
18
28
  export type CoordinationOperationCallbacks = {
19
29
  completeOperation: (workflowId: string, value: unknown) => void;
20
30
  runOperationWithResult: (workflowId: string, operation: OperationWithCallerStack, execute: () => Promise<unknown>) => Promise<void>;
@@ -5,6 +5,7 @@ import {
5
5
  executeRunAllBranches,
6
6
  executeRunAllBranchesSettled
7
7
  } from "../engine-helpers.js";
8
+ import { finalizeAndUnwrap } from "./deferred-consume-envelope.js";
8
9
  import {
9
10
  executeActivityOperationResult as executeActivityOperationResultFromInternals
10
11
  } from "./operations-activity.js";
@@ -13,14 +14,30 @@ import {
13
14
  dispatchBranchesAllSettled,
14
15
  valuesFromSlots
15
16
  } from "./parallel-dispatch.js";
16
- import { consumeSignal, trackWaiterKey, untrackWaiterKey } from "./signals.js";
17
+ import {
18
+ consumeSignalWithAtomicWorkflowCommit,
19
+ trackWaiterKey,
20
+ untrackWaiterKey
21
+ } from "./signals.js";
17
22
  import { callActivityFunction } from "./state-utilities.js";
23
+ export function assertSupportedSignalBranches(operations) {
24
+ const seen = new Set, walk = (subOperations) => {
25
+ for (const subOperation of subOperations)
26
+ if (subOperation.type === "wait-signal") {
27
+ if (seen.has(subOperation.signalName))
28
+ throw Error(`ctx.race / ctx.all cannot have two branches waiting on the same signal "${subOperation.signalName}": sibling wait-signal branches share one waiter and would clobber each other. Wait on the signal once, or use distinct signal names.`);
29
+ seen.add(subOperation.signalName);
30
+ } else if (subOperation.type === "race" || subOperation.type === "parallel")
31
+ walk(subOperation.operations);
32
+ };
33
+ walk(operations);
34
+ }
18
35
  export async function processWaitSignalOperation(internals, workflowId, operation, callbacks) {
19
36
  const abortSignal = internals.abortController.signal, waiterKey = `${workflowId}:${operation.signalName}`;
20
37
  while (!0) {
21
38
  if (abortSignal.aborted)
22
39
  return;
23
- const existingPayload = await consumeSignal(internals, workflowId, operation.signalName);
40
+ const existingPayload = await consumeSignalWithAtomicWorkflowCommit(internals, workflowId, operation.signalName);
24
41
  if (existingPayload.found) {
25
42
  callbacks.completeOperation(workflowId, existingPayload.payload);
26
43
  return;
@@ -33,7 +50,7 @@ export async function processWaitSignalOperation(internals, workflowId, operatio
33
50
  untrackWaiterKey(internals.signalWaitersByWorkflow, workflowId, waiterKey);
34
51
  return;
35
52
  }
36
- const bufferedPayload = await consumeSignal(internals, workflowId, operation.signalName);
53
+ const bufferedPayload = await consumeSignalWithAtomicWorkflowCommit(internals, workflowId, operation.signalName);
37
54
  if (bufferedPayload.found) {
38
55
  if (internals.signalWaiters.get(waiterKey) === resolve) {
39
56
  internals.signalWaiters.delete(waiterKey);
@@ -49,19 +66,34 @@ export async function processWaitSignalOperation(internals, workflowId, operatio
49
66
  }
50
67
  export async function processParallelOperation(internals, workflowId, operation, callbacks) {
51
68
  return callbacks.runOperationWithResult(workflowId, operation, async () => {
52
- const resumedSlots = extractResumedSlots(operation.resumedCacheEntry), operationIds = operation.operations.map((sub, i) => typeof sub.operationId === "string" ? sub.operationId : `parallel:${operation.step}:${i}`), { slots, hasFirstError, firstError } = await dispatchBranchesAllSettled(operationIds, resumedSlots, (index) => callbacks.executeSubOperation(workflowId, operation.operations[index])), entry = buildEntryFromSlots("all", slots), partialEntryWritten = writePartialEntry(internals, workflowId, operation.step, entry);
53
- if (hasFirstError) {
54
- assertPartialFailurePersistenceSupported(partialEntryWritten, slots, "ctx.all", "worker execution mode");
69
+ assertSupportedSignalBranches(operation.operations);
70
+ const resumedSlots = extractResumedSlots(operation.resumedCacheEntry), operationIds = operation.operations.map((sub, i) => typeof sub.operationId === "string" ? sub.operationId : `parallel:${operation.step}:${i}`), { slots, hasFirstError, firstError } = await dispatchBranchesAllSettled(operationIds, resumedSlots, (index) => callbacks.executeSubOperation(workflowId, operation.operations[index]));
71
+ if (hasFirstError)
72
+ assertPartialFailurePersistenceSupported(canPersistPartialEntry(internals, workflowId), slots, "ctx.all", "worker execution mode");
73
+ await finalizeFulfilledSlots(slots);
74
+ const entry = buildEntryFromSlots("all", slots);
75
+ writePartialEntry(internals, workflowId, operation.step, entry);
76
+ if (hasFirstError)
55
77
  throw firstError;
56
- }
57
78
  return valuesFromSlots(slots);
58
79
  });
59
80
  }
81
+ async function finalizeFulfilledSlots(slots) {
82
+ const failure = (await Promise.allSettled(slots.map(async (slot) => {
83
+ if (slot.status === "fulfilled")
84
+ slot.value = await finalizeAndUnwrap(slot.value);
85
+ }))).find((outcome) => outcome.status === "rejected");
86
+ if (failure)
87
+ throw failure.reason;
88
+ }
60
89
  function extractResumedSlots(resumedCacheEntry) {
61
90
  if (!isParallelOperationCacheEntry(resumedCacheEntry))
62
91
  return;
63
92
  return resumedCacheEntry.branches;
64
93
  }
94
+ function canPersistPartialEntry(internals, workflowId) {
95
+ return internals.inlineStrategy?.getContext(workflowId) !== void 0;
96
+ }
65
97
  function writePartialEntry(internals, workflowId, step, entry) {
66
98
  const context = internals.inlineStrategy?.getContext(workflowId);
67
99
  if (context === void 0)
@@ -76,13 +108,16 @@ function assertPartialFailurePersistenceSupported(partialEntryWritten, slots, op
76
108
  }
77
109
  export async function processRaceOperation(_internals, workflowId, operation, callbacks) {
78
110
  return callbacks.runOperationWithResult(workflowId, operation, async () => {
111
+ assertSupportedSignalBranches(operation.operations);
79
112
  const controller = new AbortController, subOperations = operation.operations.map((subOperation) => callbacks.executeSubOperation(workflowId, subOperation, controller.signal));
80
113
  Promise.allSettled(subOperations);
114
+ let winner;
81
115
  try {
82
- return await Promise.race(subOperations);
116
+ winner = await Promise.race(subOperations);
83
117
  } finally {
84
118
  controller.abort();
85
119
  }
120
+ return finalizeAndUnwrap(winner);
86
121
  });
87
122
  }
88
123
  export async function processRunAllOperation(internals, workflowId, operation, callbacks) {
@@ -157,6 +192,6 @@ export async function executeRunAllOperationResult(internals, workflowId, operat
157
192
  activityName: fn.name,
158
193
  fn,
159
194
  input
160
- }, callbacks.getActivityOperationCallbacks(), speculativeState);
195
+ }, callbacks.getActivityOperationCallbacks(), void 0, speculativeState);
161
196
  });
162
197
  }
@@ -18,6 +18,12 @@ export type OperationRouterCallbacks = {
18
18
  processWaitUpdateOperation: (workflowId: string, operation: Extract<ContextOperationRequest, {
19
19
  type: 'wait-update';
20
20
  }>) => Promise<void>;
21
+ processWaitConditionOperation: (workflowId: string, operation: Extract<ContextOperationRequest, {
22
+ type: 'wait-condition';
23
+ }>) => Promise<void>;
24
+ processGetVersionOperation: (workflowId: string, operation: Extract<ContextOperationRequest, {
25
+ type: 'get-version';
26
+ }>) => Promise<void>;
21
27
  processParallelOperation: (workflowId: string, operation: Extract<ContextOperationRequest, {
22
28
  type: 'parallel';
23
29
  }>) => Promise<void>;
@@ -35,6 +35,8 @@ function operationProcessors(callbacks) {
35
35
  sleep: callbacks.processSleepOperation,
36
36
  "wait-signal": callbacks.processWaitSignalOperation,
37
37
  "wait-update": callbacks.processWaitUpdateOperation,
38
+ "wait-condition": callbacks.processWaitConditionOperation,
39
+ "get-version": callbacks.processGetVersionOperation,
38
40
  parallel: callbacks.processParallelOperation,
39
41
  race: callbacks.processRaceOperation,
40
42
  memo: callbacks.processMemoOperation,
@@ -1,3 +1,5 @@
1
+ import { finalizeAndUnwrap } from "./deferred-consume-envelope.js";
2
+ import { assertSupportedSignalBranches } from "./operations-coordination.js";
1
3
  import { SpeculativeExecutionState } from "./speculative-execution-state.js";
2
4
  export async function processSpeculateOperation(internals, workflowId, operation, callbacks) {
3
5
  return callbacks.runOperationWithResult(workflowId, operation, () => executeSpeculativeBranch(internals, workflowId, operation, callbacks));
@@ -30,8 +32,10 @@ export async function driveSpeculativeGenerator(workflowId, generator, speculati
30
32
  return iterationResult.value;
31
33
  const nextOperation = iterationResult.value;
32
34
  try {
33
- const nextResult = await callbacks.executeSubOperation(workflowId, nextOperation, void 0, speculativeState);
34
- return advance(nextResult, void 0);
35
+ if (nextOperation.type === "race" || nextOperation.type === "parallel")
36
+ assertSupportedSignalBranches(nextOperation.operations);
37
+ const nextResult = await callbacks.executeSubOperation(workflowId, nextOperation, void 0, speculativeState), finalizedResult = await finalizeAndUnwrap(nextResult);
38
+ return advance(finalizedResult, void 0);
35
39
  } catch (error) {
36
40
  return advance(lastResult, error instanceof Error ? error : Error(String(error)));
37
41
  }
@@ -1,7 +1,7 @@
1
1
  import { KEYS } from "../../storage/interface.js";
2
2
  import { encode } from "../codec.js";
3
3
  import { cleanupPartialStreamChunks, createCleanupErrorReporter } from "../engine-helpers.js";
4
- import { loadStoredStreamChunks } from "./stream-chunk-loading.js";
4
+ import { encodeStoredStreamTailSequence, loadStoredStreamChunks } from "./stream-chunk-loading.js";
5
5
  import { STREAM_CHUNK_KIND, TOKENS_STREAM_KEY, notifyWorkflowFeedCommit } from "./workflow-feed.js";
6
6
  export async function getStreamChunksFromInternals(internals, workflowId, key, options) {
7
7
  return loadStoredStreamChunks(internals.storage, workflowId, key, options);
@@ -33,7 +33,17 @@ export async function writeStreamChunksFromInternals(internals, workflowId, oper
33
33
  let chunkCount = 0, totalSizeBytes = 0;
34
34
  for await (const chunk of asyncGenerator) {
35
35
  const encoded = encode(chunk), sequence = chunkCount, chunkKey = KEYS.streamChunk(workflowId, operation.key, sequence);
36
- await internals.storage.put(chunkKey, encoded);
36
+ if (operation.key === TOKENS_STREAM_KEY)
37
+ await internals.storage.batch([
38
+ { type: "put", key: chunkKey, value: encoded },
39
+ {
40
+ type: "put",
41
+ key: KEYS.streamTail(workflowId, operation.key),
42
+ value: encodeStoredStreamTailSequence(sequence)
43
+ }
44
+ ]);
45
+ else
46
+ await internals.storage.put(chunkKey, encoded);
37
47
  writtenKeys.push(chunkKey);
38
48
  totalSizeBytes += encoded.byteLength;
39
49
  chunkCount++;
@@ -8,6 +8,7 @@ type SleepOperation = Extract<ContextOperationRequest, {
8
8
  }>;
9
9
  export type TimeOperationCallbacks = {
10
10
  completeOperation: (workflowId: string, value: unknown) => void;
11
+ dispatchEvent: (event: Event) => void;
11
12
  loadWorkflowState: (workflowId: string) => Promise<WorkflowState | null>;
12
13
  failWorkflow: (workflowId: string, error: Error) => Promise<void>;
13
14
  runSerializedWorkflowStateWrite: <Result>(workflowId: string, writeOperation: () => Promise<Result>) => Promise<Result>;
@@ -17,6 +18,7 @@ export type TimeOperationCallbacks = {
17
18
  loadWorkflowStartHeaders: (workflowId: string) => Promise<Map<string, string> | undefined>;
18
19
  parseStartOptionDuration: (value: Duration, fieldName: 'options.executionTimeout' | 'options.startAfter') => number;
19
20
  runDeferredTerminalCleanup: (workflowId: string, timerId: string) => Promise<void>;
21
+ runWorkflowFinalizer: (workflowId: string, timerId: string) => Promise<void>;
20
22
  handleScheduleTimer: (entry: TimerEntry) => Promise<void>;
21
23
  timeout: (workflowId: string) => Promise<void>;
22
24
  handleCleanupError: (source: string, error: unknown, workflowId: string) => void;
@@ -24,6 +26,6 @@ export type TimeOperationCallbacks = {
24
26
  export declare function createDelayedStartTimerEntry(_internals: EngineInternals, workflowId: string, scheduledStartAt: number, options: StartOptions | undefined, callbacks: Pick<TimeOperationCallbacks, 'parseStartOptionDuration'>): TimerEntry;
25
27
  export declare function processSleepOperation(internals: EngineInternals, workflowId: string, operation: SleepOperation, callbacks: Pick<TimeOperationCallbacks, 'completeOperation' | 'loadWorkflowState'>): Promise<void>;
26
28
  export declare function registerSleepResolver(internals: EngineInternals, workflowId: string, operationId: string, resolve: () => void): void;
27
- export declare function startDelayedWorkflow(internals: EngineInternals, entry: TimerEntry, callbacks: Pick<TimeOperationCallbacks, 'beginWorkflowExecution' | 'failWorkflow' | 'handleCleanupError' | 'loadWorkflowStartHeaders' | 'loadWorkflowState' | 'runSerializedWorkflowStateWrite' | 'setWorkflowStartHeaders' | 'workflowVersionTupleFromState'>): Promise<void>;
28
- export declare function handleTimerFired(internals: EngineInternals, entry: TimerEntry, callbacks: Pick<TimeOperationCallbacks, 'failWorkflow' | 'handleCleanupError' | 'loadWorkflowStartHeaders' | 'loadWorkflowState' | 'runDeferredTerminalCleanup' | 'runSerializedWorkflowStateWrite' | 'handleScheduleTimer' | 'setWorkflowStartHeaders' | 'timeout' | 'beginWorkflowExecution' | 'workflowVersionTupleFromState'>): Promise<void>;
29
+ export declare function startDelayedWorkflow(internals: EngineInternals, entry: TimerEntry, callbacks: Pick<TimeOperationCallbacks, 'beginWorkflowExecution' | 'dispatchEvent' | 'failWorkflow' | 'handleCleanupError' | 'loadWorkflowStartHeaders' | 'loadWorkflowState' | 'runSerializedWorkflowStateWrite' | 'setWorkflowStartHeaders' | 'workflowVersionTupleFromState'>): Promise<void>;
30
+ export declare function handleTimerFired(internals: EngineInternals, entry: TimerEntry, callbacks: Pick<TimeOperationCallbacks, 'failWorkflow' | 'handleCleanupError' | 'loadWorkflowStartHeaders' | 'loadWorkflowState' | 'runDeferredTerminalCleanup' | 'runWorkflowFinalizer' | 'runSerializedWorkflowStateWrite' | 'handleScheduleTimer' | 'setWorkflowStartHeaders' | 'timeout' | 'beginWorkflowExecution' | 'dispatchEvent' | 'workflowVersionTupleFromState'>): Promise<void>;
29
31
  export {};
@@ -2,6 +2,7 @@ import { KEYS, storageHas } from "../../storage/interface.js";
2
2
  import { deserializeCheckpoint } from "../checkpoint.js";
3
3
  import { encode } from "../codec.js";
4
4
  import { buildTimerBatchOperations, normalizeStorageTimestamp } from "../scheduler.js";
5
+ import { commitFencedEngineWrite } from "./fenced-write.js";
5
6
  import { reprovideRecoveredServices } from "./lifecycle/recovered-services.js";
6
7
  import { buildWorkflowVisibilityIndexTransition } from "./workflow-indexes.js";
7
8
  export function createDelayedStartTimerEntry(_internals, workflowId, scheduledStartAt, options, callbacks) {
@@ -81,12 +82,12 @@ export async function startDelayedWorkflow(internals, entry, callbacks) {
81
82
  fireAt: executionDeadline,
82
83
  kind: "execution-deadline"
83
84
  }));
84
- await internals.storage.batch(operations);
85
+ await commitFencedEngineWrite(internals, operations, [], () => Error(`Delayed-start transition for workflow "${entry.workflowId}" lost its CAS race.`));
85
86
  return nextRunningState;
86
87
  });
87
88
  if (!runningState)
88
89
  return;
89
- if (await reprovideRecoveredServices(internals, runningState, (workflowId, error) => callbacks.failWorkflow(workflowId, error), callbacks.handleCleanupError))
90
+ if (await reprovideRecoveredServices(internals, runningState, (workflowId, error) => callbacks.failWorkflow(workflowId, error), callbacks.handleCleanupError, callbacks.dispatchEvent))
90
91
  return;
91
92
  if (await storageHas(internals.storage, KEYS.terminalCleanupNeeded(entry.workflowId)))
92
93
  internals.workflowsNeedingTerminalCleanup.add(entry.workflowId);
@@ -133,15 +134,26 @@ export async function handleTimerFired(internals, entry, callbacks) {
133
134
  await callbacks.runDeferredTerminalCleanup(entry.workflowId, entry.id);
134
135
  return;
135
136
  }
137
+ if (entry.kind === "teardown") {
138
+ await callbacks.runWorkflowFinalizer(entry.workflowId, entry.id);
139
+ return;
140
+ }
136
141
  if (entry.kind === "schedule") {
137
142
  await callbacks.handleScheduleTimer(entry);
138
143
  return;
139
144
  }
140
145
  if (entry.kind === "sleep")
141
146
  resolveSleepTimer(internals, entry);
147
+ else if (entry.kind === "wait-condition")
148
+ resolveConditionTimer(internals, entry);
142
149
  else if (entry.kind === "execution-deadline")
143
150
  await callbacks.timeout(entry.workflowId);
144
151
  }
152
+ function resolveConditionTimer(internals, entry) {
153
+ const resolver = internals.conditionWaiters.get(entry.workflowId);
154
+ if (resolver)
155
+ resolver();
156
+ }
145
157
  async function handleReviewTimer(internals, entry, callbacks) {
146
158
  const reviewId = entry.id.split(":")[1];
147
159
  if (!reviewId)
@@ -0,0 +1,23 @@
1
+ import type { ContextOperationRequest } from '../context.ts';
2
+ import type { EngineInternals } from './internals.ts';
3
+ import type { CoordinationOperationCallbacks } from './operations-coordination.ts';
4
+ type WaitConditionOperation = Extract<ContextOperationRequest, {
5
+ type: 'wait-condition';
6
+ }>;
7
+ export type ConditionOperationCallbacks = Pick<CoordinationOperationCallbacks, 'completeOperation'> & {
8
+ /**
9
+ * Fail the pending operation, feeding the error to the generator so it
10
+ * re-throws at the `yield* ctx.waitUntil` site. Used when the user predicate
11
+ * throws — a throwing predicate must surface as a catchable workflow failure,
12
+ * not park the run forever.
13
+ */
14
+ failOperation: (workflowId: string, operation: WaitConditionOperation, error: unknown) => void;
15
+ /** Whether the workflow is still running — gates completion after a wake. */
16
+ isWorkflowRunning: (workflowId: string) => Promise<boolean>;
17
+ /** Schedule the deterministic deadline timer (`cond:${workflowId}:${step}`). */
18
+ scheduleConditionDeadline: (workflowId: string, step: number, fireAt: number) => Promise<void>;
19
+ /** Cancel the deadline timer in storage on teardown. */
20
+ cancelConditionDeadline: (workflowId: string, step: number) => Promise<void>;
21
+ };
22
+ export declare function processWaitConditionOperation(internals: EngineInternals, workflowId: string, operation: WaitConditionOperation, callbacks: ConditionOperationCallbacks): Promise<void>;
23
+ export {};