@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
@@ -0,0 +1,62 @@
1
+ function evaluateConditionOutcome(internals, predicate, deadline) {
2
+ if (predicate())
3
+ return { done: !0, value: deadline === void 0 ? void 0 : !0 };
4
+ if (deadline !== void 0 && internals.options.getNow() >= deadline)
5
+ return { done: !0, value: !1 };
6
+ return { done: !1 };
7
+ }
8
+ export async function processWaitConditionOperation(internals, workflowId, operation, callbacks) {
9
+ const abortSignal = internals.abortController.signal, { predicate, deadline } = operation;
10
+ let settled = !1;
11
+ const complete = (value) => {
12
+ if (settled)
13
+ return;
14
+ settled = !0;
15
+ callbacks.completeOperation(workflowId, value);
16
+ };
17
+ if (abortSignal.aborted)
18
+ return;
19
+ try {
20
+ const initial = evaluateConditionOutcome(internals, predicate, deadline);
21
+ if (initial.done) {
22
+ complete(initial.value);
23
+ return;
24
+ }
25
+ if (deadline !== void 0)
26
+ await callbacks.scheduleConditionDeadline(workflowId, operation.step, deadline);
27
+ try {
28
+ let step = await runConditionWaitStep(internals, workflowId, predicate, deadline, callbacks);
29
+ while (step.status === "continue")
30
+ step = await runConditionWaitStep(internals, workflowId, predicate, deadline, callbacks);
31
+ if (step.status === "complete")
32
+ complete(step.value);
33
+ } finally {
34
+ releaseConditionWaiter(internals, workflowId);
35
+ if (deadline !== void 0)
36
+ await callbacks.cancelConditionDeadline(workflowId, operation.step);
37
+ }
38
+ } catch (error) {
39
+ callbacks.failOperation(workflowId, operation, error);
40
+ }
41
+ }
42
+ async function runConditionWaitStep(internals, workflowId, predicate, deadline, callbacks) {
43
+ const abortSignal = internals.abortController.signal;
44
+ if (abortSignal.aborted)
45
+ return { status: "stop" };
46
+ const { promise, resolve } = Promise.withResolvers();
47
+ internals.conditionWaiters.set(workflowId, resolve);
48
+ const outcome = abortSignal.aborted ? { done: !0, value: void 0, aborted: !0 } : { ...evaluateConditionOutcome(internals, predicate, deadline), aborted: !1 };
49
+ if (outcome.done) {
50
+ releaseConditionWaiter(internals, workflowId);
51
+ return outcome.aborted ? { status: "stop" } : { status: "complete", value: outcome.value };
52
+ }
53
+ await promise;
54
+ if (abortSignal.aborted)
55
+ return { status: "stop" };
56
+ if (!await callbacks.isWorkflowRunning(workflowId))
57
+ return { status: "stop" };
58
+ return { status: "continue" };
59
+ }
60
+ function releaseConditionWaiter(internals, workflowId) {
61
+ internals.conditionWaiters.delete(workflowId);
62
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Resolution of the `ownership` posture options (`Engine.create({ ownership })`)
3
+ * into {@link ResolvedOptions}. Extracted from `construction.ts` to keep that
4
+ * file under the `max-lines` ceiling; mirrors the second-instance resolver's
5
+ * "only validate when the feature is enabled" discipline.
6
+ *
7
+ * @module core/engine/ownership-options
8
+ */
9
+ import type { EngineConstructorOptions, ResolvedOptions } from './engine-internal-types.ts';
10
+ /** Default lease time-to-live for `ownership: 'lease'`. */
11
+ export declare const DEFAULT_LEASE_TTL_MS = 30000;
12
+ /** Default lease renewal interval for `ownership: 'lease'`. */
13
+ export declare const DEFAULT_LEASE_RENEW_INTERVAL_MS = 5000;
14
+ /** Default boot-time lease acquisition wait window for `ownership: 'lease'`. */
15
+ export declare const DEFAULT_LEASE_WAIT_TIMEOUT_MS = 60000;
16
+ /**
17
+ * Resolve the ownership posture and lease tuning into their `ResolvedOptions`
18
+ * fields. Defaults to `'none'`. The lease durations are documented as "ignored
19
+ * when ownership is not 'lease'", so they are only normalized (and thus only
20
+ * able to throw on an invalid value) when lease ownership is actually enabled —
21
+ * an invalid duration must not make an off-by-default config fatal at boot.
22
+ */
23
+ export declare function resolveOwnershipFields(options: EngineConstructorOptions | undefined): Pick<ResolvedOptions, 'ownershipMode' | 'leaseTtlMs' | 'leaseRenewIntervalMs' | 'leaseWaitTimeoutMs'>;
@@ -0,0 +1,26 @@
1
+ import { normalizeRetentionDuration } from "./validation.js";
2
+ export const DEFAULT_LEASE_TTL_MS = 30000, DEFAULT_LEASE_RENEW_INTERVAL_MS = 5000, DEFAULT_LEASE_WAIT_TIMEOUT_MS = 60000;
3
+ export function resolveOwnershipFields(options) {
4
+ const ownershipMode = assertKnownOwnershipMode(options?.ownership ?? "none");
5
+ if (ownershipMode !== "lease")
6
+ return {
7
+ ownershipMode,
8
+ leaseTtlMs: DEFAULT_LEASE_TTL_MS,
9
+ leaseRenewIntervalMs: DEFAULT_LEASE_RENEW_INTERVAL_MS,
10
+ leaseWaitTimeoutMs: DEFAULT_LEASE_WAIT_TIMEOUT_MS
11
+ };
12
+ const leaseTtlMs = normalizeRetentionDuration(options?.leaseTtl, "options.leaseTtl") ?? DEFAULT_LEASE_TTL_MS, leaseRenewIntervalMs = normalizeRetentionDuration(options?.leaseRenewInterval, "options.leaseRenewInterval") ?? DEFAULT_LEASE_RENEW_INTERVAL_MS, leaseWaitTimeoutMs = normalizeRetentionDuration(options?.leaseWaitTimeout, "options.leaseWaitTimeout") ?? DEFAULT_LEASE_WAIT_TIMEOUT_MS;
13
+ assertLeaseTimingCoherent(leaseTtlMs, leaseRenewIntervalMs, leaseWaitTimeoutMs);
14
+ return { ownershipMode, leaseTtlMs, leaseRenewIntervalMs, leaseWaitTimeoutMs };
15
+ }
16
+ function assertKnownOwnershipMode(mode) {
17
+ if (mode !== "none" && mode !== "lease")
18
+ throw Error(`Unknown ownership posture "${String(mode)}". Expected 'none' or 'lease'.`);
19
+ return mode;
20
+ }
21
+ function assertLeaseTimingCoherent(leaseTtlMs, leaseRenewIntervalMs, leaseWaitTimeoutMs) {
22
+ if (leaseTtlMs <= 0 || leaseRenewIntervalMs <= 0 || leaseWaitTimeoutMs <= 0)
23
+ throw Error(`ownership: 'lease' requires positive leaseTtl, leaseRenewInterval, and leaseWaitTimeout (got leaseTtl=${leaseTtlMs}ms, leaseRenewInterval=${leaseRenewIntervalMs}ms, leaseWaitTimeout=${leaseWaitTimeoutMs}ms).`);
24
+ if (leaseRenewIntervalMs >= leaseTtlMs)
25
+ throw Error(`ownership: 'lease' requires leaseRenewInterval (${leaseRenewIntervalMs}ms) to be strictly less than leaseTtl (${leaseTtlMs}ms), so a renewal fires before the lease can lapse.`);
26
+ }
@@ -0,0 +1,3 @@
1
+ import type { Engine } from './index.ts';
2
+ /** Internal server bridge for the engine's normalized payload-size cap. */
3
+ export declare function getEnginePayloadSizeMaxBytes(engine: Engine): number | null;
@@ -0,0 +1,4 @@
1
+ import { getInternals } from "./internals.js";
2
+ export function getEnginePayloadSizeMaxBytes(engine) {
3
+ return getInternals(engine).options.payloadSizePolicy.maxBytes;
4
+ }
@@ -14,5 +14,22 @@ export declare function invokeUpdateHandler(internals: EngineInternals, name: st
14
14
  */
15
15
  export declare function processPendingUpdatesAfterInlineAdvance(internals: EngineInternals, workflowId: string, callbacks: PendingUpdateCallbacks): Promise<void>;
16
16
  export declare function schedulePendingInlineUpdateDrain(internals: EngineInternals, workflowId: string, callbacks: PendingUpdateCallbacks): void;
17
+ /**
18
+ * Drain a workflow's buffered coordinated updates and deliver each to its
19
+ * handler exactly once, even when several drains race.
20
+ *
21
+ * Several triggers can fire near-simultaneously: each `engine.update()` schedules
22
+ * a `setTimeout(0)` drain, and the post-advance path drains too. Their consume-
23
+ * deletes are durable (`storage.batch`) and lag the in-memory `getPendingUpdates`
24
+ * scan, so two overlapping drains both see the same pending set. Each update id
25
+ * is therefore CLAIMED synchronously in `deliveredPendingUpdateIds` before
26
+ * delivery (no `await` between the membership check and the add, so a concurrent
27
+ * drain cannot interleave): a racing drain that re-reads the same id skips it.
28
+ *
29
+ * After the drain, re-drive a parked `ctx.waitUntil` once. A coordinated update
30
+ * buffered before `ctx.onUpdate` was registered drains here (not on the inline
31
+ * `tryInlineUpdateHandler` path), and a handler may have mutated the workflow-
32
+ * local state a predicate reads, so the wait must be poked to re-evaluate.
33
+ */
17
34
  export declare function processPendingUpdatesForHandlers(internals: EngineInternals, workflowId: string, callbacks: PendingUpdateCallbacks): Promise<void>;
18
35
  export {};
@@ -1,5 +1,7 @@
1
1
  import { UpdateCompletedEvent, UpdateReceivedEvent } from "../events.js";
2
2
  import { UpdateValidationError } from "../updates.js";
3
+ import { notifyConditionWaiters } from "./condition-waiters.js";
4
+ import { commitFencedEngineWrite } from "./fenced-write.js";
3
5
  import {
4
6
  extractStandardSchemaIssues,
5
7
  invokeUpdateHandler as invokeUpdateHandlerFromInternals
@@ -71,17 +73,37 @@ export async function processPendingUpdatesForHandlers(internals, workflowId, ca
71
73
  const pendingUpdates = await internals.updateCoordinator.getPendingUpdates(workflowId);
72
74
  if (pendingUpdates.length === 0)
73
75
  return;
74
- for (const update of pendingUpdates) {
75
- const handler = handlers.get(update.name);
76
- if (!handler)
77
- continue;
78
- const validatorRejectionError = await runValidatorIfPresent(context, update);
79
- if (validatorRejectionError !== null) {
80
- await rejectPendingUpdate(internals, workflowId, update, validatorRejectionError, callbacks);
81
- continue;
76
+ let handlerRan = !1;
77
+ try {
78
+ for (const update of pendingUpdates) {
79
+ const handler = handlers.get(update.name);
80
+ if (!handler)
81
+ continue;
82
+ if (!claimPendingUpdateForDelivery(internals, workflowId, update.updateId))
83
+ continue;
84
+ const validatorRejectionError = await runValidatorIfPresent(context, update);
85
+ if (validatorRejectionError !== null) {
86
+ await rejectPendingUpdate(internals, workflowId, update, validatorRejectionError, callbacks);
87
+ continue;
88
+ }
89
+ handlerRan = !0;
90
+ await deliverPendingUpdate(internals, workflowId, update, handler, callbacks);
82
91
  }
83
- await deliverPendingUpdate(internals, workflowId, update, handler, callbacks);
92
+ } finally {
93
+ if (handlerRan)
94
+ notifyConditionWaiters(internals, workflowId);
95
+ }
96
+ }
97
+ function claimPendingUpdateForDelivery(internals, workflowId, updateId) {
98
+ let claimed = internals.deliveredPendingUpdateIds.get(workflowId);
99
+ if (claimed === void 0) {
100
+ claimed = new Set;
101
+ internals.deliveredPendingUpdateIds.set(workflowId, claimed);
84
102
  }
103
+ if (claimed.has(updateId))
104
+ return !1;
105
+ claimed.add(updateId);
106
+ return !0;
85
107
  }
86
108
  async function runValidatorIfPresent(context, update) {
87
109
  const validator = context.updateValidators?.get(update.name);
@@ -91,7 +113,7 @@ async function runValidatorIfPresent(context, update) {
91
113
  }
92
114
  async function rejectPendingUpdate(internals, workflowId, update, errorMessage, callbacks) {
93
115
  const responseOperations = internals.updateCoordinator.buildResponseOperations(update.updateId, workflowId, void 0, errorMessage, update.idempotencyKey);
94
- await internals.storage.batch(responseOperations);
116
+ await commitFencedEngineWrite(internals, responseOperations, [], () => Error(`Update rejection for workflow "${workflowId}" lost its CAS race.`));
95
117
  callbacks.broadcast({ type: "update:completed", workflowId, updateId: update.updateId });
96
118
  }
97
119
  async function deliverPendingUpdate(internals, workflowId, update, handler, callbacks) {
@@ -103,7 +125,7 @@ async function deliverPendingUpdate(internals, workflowId, update, handler, call
103
125
  error = handlerError instanceof Error ? handlerError.message : String(handlerError);
104
126
  }
105
127
  const responseOperations = internals.updateCoordinator.buildResponseOperations(update.updateId, workflowId, result, error, update.idempotencyKey);
106
- await internals.storage.batch(responseOperations);
128
+ await commitFencedEngineWrite(internals, responseOperations, [], () => Error(`Update response for workflow "${workflowId}" lost its CAS race.`));
107
129
  callbacks.dispatchEvent(new UpdateCompletedEvent(update.updateId, workflowId, update.name, result, error));
108
130
  callbacks.broadcast({ type: "update:completed", workflowId, updateId: update.updateId });
109
131
  }
@@ -4,7 +4,7 @@ export async function query(internals, workflowId, name, input) {
4
4
  const inlineStrategy = internals.inlineStrategy;
5
5
  if (!inlineStrategy)
6
6
  throw Error("Workflow queries are not supported when using the worker execution strategy.");
7
- const context = inlineStrategy.getContext(workflowId);
7
+ const context = inlineStrategy.getContext(workflowId) ?? inlineStrategy.getParkedContext(workflowId);
8
8
  if (!context)
9
9
  return;
10
10
  const queryHandler = context.queryHandlers.get(name);
@@ -1,6 +1,7 @@
1
1
  import type { EngineInternals } from './internals.ts';
2
2
  export type RegistrationCallbacks = {
3
3
  ensureRetentionSweepInterval: () => void;
4
+ dispatchEvent: (event: Event) => void;
4
5
  };
5
6
  export declare function register(internals: EngineInternals, definition: unknown, callbacks: RegistrationCallbacks): void;
6
7
  export declare function resolveWorkflowTypeTarget(internals: EngineInternals, target: string | Function, _callbacks: RegistrationCallbacks): string;
@@ -1,4 +1,5 @@
1
1
  import { ActivityRegistry } from "../activity-registry.js";
2
+ import { WorkflowDefinitionRegisteredEvent } from "../events.js";
2
3
  import {
3
4
  activity,
4
5
  validateDefinitionSchemaMetadata
@@ -31,16 +32,29 @@ function buildBaseRegistrationEntry(name, registration) {
31
32
  ...registration.outputSchema === void 0 ? {} : {
32
33
  outputSchema: validateDefinitionSchemaMetadata(registration.outputSchema, `registration("${name}").outputSchema`)
33
34
  },
34
- ...normalizedRetention !== null && { retention: normalizedRetention }
35
+ ...normalizedRetention !== null && { retention: normalizedRetention },
36
+ ...registration.concurrency !== void 0 ? {
37
+ concurrency: normalizeWorkflowConcurrencyOptions(registration.concurrency, `registration("${name}").concurrency`)
38
+ } : {}
35
39
  };
36
40
  }
41
+ function normalizeWorkflowConcurrencyOptions(concurrency, fieldName) {
42
+ if (!Number.isInteger(concurrency.max) || concurrency.max < 1)
43
+ throw RangeError(`${fieldName}.max must be a positive integer`);
44
+ if (concurrency.key !== void 0 && typeof concurrency.key !== "function")
45
+ throw TypeError(`${fieldName}.key must be a function when provided`);
46
+ return Object.freeze({
47
+ max: concurrency.max,
48
+ ...concurrency.key === void 0 ? {} : { key: concurrency.key }
49
+ });
50
+ }
37
51
  function applyOptionalRegistrationFields(entry, registration) {
38
- if (registration.migrate)
39
- entry.migrate = registration.migrate;
40
52
  if (registration.searchAttributes && Object.keys(registration.searchAttributes).length > 0)
41
53
  entry.searchAttributes = registration.searchAttributes;
42
54
  if (registration.constraints && registration.constraints.length > 0)
43
55
  entry.constraints = registration.constraints;
56
+ if (registration.finalizer !== void 0)
57
+ entry.finalizer = registration.finalizer;
44
58
  }
45
59
  function buildRegistrationEntry(name, registration) {
46
60
  const entry = buildBaseRegistrationEntry(name, registration);
@@ -55,6 +69,7 @@ function commitWorkflowDefinition(internals, definition, callbacks) {
55
69
  internals.registrations.set(name, entry);
56
70
  callbacks.ensureRetentionSweepInterval();
57
71
  internals.workflowTypesByHandler.set(definition.handler, name);
72
+ callbacks.dispatchEvent(new WorkflowDefinitionRegisteredEvent(name));
58
73
  }
59
74
  function hasNonNullObjectField(value, key) {
60
75
  if (!(key in value))
@@ -0,0 +1,5 @@
1
+ import type { ScheduleState } from '../types.ts';
2
+ type JitteredSchedule = Pick<ScheduleState, 'id' | 'jitterMs'>;
3
+ export declare function computeScheduleJitterOffset(scheduleId: string, nominalFireAt: number, jitterMs: number | undefined): number;
4
+ export declare function resolveEffectiveScheduleFireAt(schedule: JitteredSchedule, nominalFireAt: number): number;
5
+ export {};
@@ -0,0 +1,10 @@
1
+ import { hashString } from "../../runtime/portable.js";
2
+ export function computeScheduleJitterOffset(scheduleId, nominalFireAt, jitterMs) {
3
+ if (jitterMs === void 0 || jitterMs <= 0)
4
+ return 0;
5
+ const hash = BigInt(`0x${hashString(`${scheduleId}\x00${nominalFireAt}`)}`);
6
+ return Number(hash % BigInt(jitterMs));
7
+ }
8
+ export function resolveEffectiveScheduleFireAt(schedule, nominalFireAt) {
9
+ return nominalFireAt + computeScheduleJitterOffset(schedule.id, nominalFireAt, schedule.jitterMs);
10
+ }
@@ -0,0 +1,17 @@
1
+ import type { ScheduleState } from '../types.ts';
2
+ import type { EngineInternals } from './internals.ts';
3
+ import type { ScheduleCallbacks } from './schedules.ts';
4
+ /**
5
+ * Launch one scheduled occurrence's workflow run and emit `schedule:fired`.
6
+ *
7
+ * This is the single chokepoint every occurrence launch flows through — initial
8
+ * cadence ticks, `cancel-running` replacements, and `queue`-drained runs — so it
9
+ * is the one place that reliably holds the launched `workflowId` across all
10
+ * overlap policies. The blocked policies (`skip`, and `queue` while a run is
11
+ * active) never reach here, so they correctly do not fire.
12
+ *
13
+ * `occurrence` is the scheduled grid timestamp the run was due, threaded from the
14
+ * timer loop. It is `undefined` for a `queue`-drained run, whose grid slot was
15
+ * tracked only as a count and whose original timestamp is therefore gone.
16
+ */
17
+ export declare function startScheduledRun(internals: EngineInternals, state: ScheduleState, callbacks: Pick<ScheduleCallbacks, 'startWorkflow' | 'failWorkflow' | 'handleCleanupError'>, occurrence?: number): Promise<string>;
@@ -0,0 +1,38 @@
1
+ import { KEYS } from "../../storage/interface.js";
2
+ import { encode } from "../codec.js";
3
+ import { ScheduleFiredEvent } from "../events.js";
4
+ import { unavailableServicesError } from "./lifecycle/recovered-services.js";
5
+ import { EMPTY_STORAGE_VALUE } from "./lifecycle/shared.js";
6
+ export async function startScheduledRun(internals, state, callbacks, occurrence) {
7
+ const workflowId = crypto.randomUUID(), scheduleRunOperations = state.overlap === "allow" ? [] : [{ type: "put", key: KEYS.scheduleRun(workflowId), value: encode(state.id) }], resolution = await resolveScheduledRunServices(internals, workflowId, state);
8
+ if (resolution !== null) {
9
+ scheduleRunOperations.push({ type: "put", key: KEYS.workflowHasServices(workflowId), value: EMPTY_STORAGE_VALUE }, { type: "put", key: KEYS.terminalCleanupNeeded(workflowId), value: EMPTY_STORAGE_VALUE });
10
+ internals.workflowsNeedingTerminalCleanup.add(workflowId);
11
+ if (resolution.status === "available")
12
+ internals.workflowServices.set(workflowId, resolution.services);
13
+ }
14
+ await callbacks.startWorkflow(state.workflowType, state.input, { id: workflowId }, scheduleRunOperations);
15
+ internals.engine.dispatchEvent(new ScheduleFiredEvent(state.id, workflowId, internals.options.getNow(), occurrence));
16
+ if (resolution !== null && resolution.status === "unavailable") {
17
+ const unavailableError = unavailableServicesError(workflowId, resolution.reason);
18
+ try {
19
+ await callbacks.failWorkflow(workflowId, unavailableError);
20
+ } catch (error) {
21
+ callbacks.handleCleanupError("startScheduledRun", error, workflowId);
22
+ }
23
+ }
24
+ return workflowId;
25
+ }
26
+ async function resolveScheduledRunServices(internals, workflowId, state) {
27
+ const resolver = internals.options.resolveWorkflowServices;
28
+ if (internals.inlineStrategy === null || !resolver)
29
+ return null;
30
+ try {
31
+ return await resolver({ workflowId, workflowType: state.workflowType, input: state.input });
32
+ } catch (error) {
33
+ return {
34
+ status: "unavailable",
35
+ reason: error instanceof Error ? error.message : String(error)
36
+ };
37
+ }
38
+ }
@@ -1,6 +1,16 @@
1
+ import { ScheduleMissedFireEvent } from "../events/schedule-events.js";
2
+ import { resolveEffectiveScheduleFireAt } from "./schedule-jitter.js";
1
3
  import { collectDueScheduleOccurrences, getNextScheduleOccurrence } from "./schedule-occurrence.js";
2
4
  import { loadScheduleState, writeScheduleState } from "./storage-io.js";
3
- const SCHEDULE_LATE_GRACE_MILLISECONDS = 1000, MAX_SCHEDULE_BACKFILL_OCCURRENCES_PER_TICK = 256;
5
+ const SCHEDULE_LATE_GRACE_MILLISECONDS = 1000, MAX_SCHEDULE_BACKFILL_OCCURRENCES_PER_TICK = 256, MAX_MISSED_FIRE_COUNT_PER_TICK = MAX_SCHEDULE_BACKFILL_OCCURRENCES_PER_TICK;
6
+
7
+ class ScheduleStatePersistenceError extends Error {
8
+ scheduleId;
9
+ constructor(scheduleId, cause) {
10
+ super(`Failed to persist schedule "${scheduleId}" while processing its timer`, { cause });
11
+ this.scheduleId = scheduleId;
12
+ }
13
+ }
4
14
  export async function handleScheduleTimer(internals, entry, callbacks) {
5
15
  const state = await loadScheduleState(internals, entry.workflowId);
6
16
  if (!isCurrentActiveScheduleTimer(state, entry))
@@ -10,28 +20,43 @@ export async function handleScheduleTimer(internals, entry, callbacks) {
10
20
  const now = internals.options.getNow(), work = planScheduleTimerWork(state, entry, now);
11
21
  if (!work)
12
22
  return;
13
- nextState = await processScheduleTimerOccurrences(internals, state, work.occurrencesToProcess, now, callbacks, (processedState) => {
14
- nextState = processedState;
15
- });
16
- await writeScheduleState(internals, {
17
- ...nextState,
18
- updatedAt: now,
19
- nextFireAt: resolveNextScheduleFireAt(nextState, work, now)
23
+ if (work.occurrencesToProcess.length === 0) {
24
+ nextState = {
25
+ ...nextState,
26
+ updatedAt: now,
27
+ nextFireAt: resolveNextScheduleFireAt(nextState, work, now),
28
+ ...work.missedOccurrences && {
29
+ lastMissedFireAt: work.missedOccurrences.lastMissedFireAt,
30
+ missedFireCount: nextState.missedFireCount + work.missedOccurrences.count
31
+ }
32
+ };
33
+ await persistScheduleTimerState(internals, nextState);
34
+ if (work.missedOccurrences)
35
+ internals.engine.dispatchEvent(new ScheduleMissedFireEvent(nextState.id, work.missedOccurrences.count, work.missedOccurrences.windowStart, work.missedOccurrences.windowEnd));
36
+ return;
37
+ }
38
+ nextState = await processScheduleTimerOccurrences(internals, state, work, now, callbacks, {
39
+ onProcessedState: (processedState) => {
40
+ nextState = processedState;
41
+ }
20
42
  });
21
43
  } catch (error) {
44
+ if (error instanceof ScheduleStatePersistenceError)
45
+ throw error;
22
46
  await pauseScheduleAfterTimerFailure(internals, nextState, error);
23
47
  }
24
48
  }
25
49
  function isCurrentActiveScheduleTimer(state, entry) {
26
- return state?.status === "active" && state.nextFireAt === entry.fireAt;
50
+ return state?.status === "active" && state.nextFireAt !== null && resolveEffectiveScheduleFireAt(state, state.nextFireAt) === entry.fireAt;
27
51
  }
28
52
  function planScheduleTimerWork(state, entry, now) {
29
53
  const dueOccurrences = collectDueScheduleOccurrences(state, state.nextFireAt, Math.max(now, entry.fireAt), state.backfill ? MAX_SCHEDULE_BACKFILL_OCCURRENCES_PER_TICK : 2);
30
54
  if (dueOccurrences.length === 0)
31
55
  return null;
32
- if (!state.backfill && now - state.nextFireAt > SCHEDULE_LATE_GRACE_MILLISECONDS)
56
+ if (!state.backfill && now - entry.fireAt > SCHEDULE_LATE_GRACE_MILLISECONDS)
33
57
  return {
34
58
  dueOccurrences,
59
+ missedOccurrences: countMissedScheduleOccurrences(state, state.nextFireAt, now),
35
60
  occurrencesToProcess: [],
36
61
  skipMissedOccurrences: !0
37
62
  };
@@ -42,29 +67,68 @@ function planScheduleTimerWork(state, entry, now) {
42
67
  skipMissedOccurrences: !1
43
68
  };
44
69
  }
70
+ function countMissedScheduleOccurrences(state, firstDueAt, throughTimestamp) {
71
+ let count = 0, occurrence = firstDueAt, lastMissedFireAt = firstDueAt;
72
+ while (occurrence <= throughTimestamp && count < MAX_MISSED_FIRE_COUNT_PER_TICK) {
73
+ count += 1;
74
+ lastMissedFireAt = occurrence;
75
+ const nextOccurrence = getNextScheduleOccurrence(state, occurrence);
76
+ if (nextOccurrence <= occurrence)
77
+ throw Error(`Schedule "${state.id}" produced a non-advancing occurrence`);
78
+ occurrence = nextOccurrence;
79
+ }
80
+ const cappedBeforeThroughTimestamp = occurrence <= throughTimestamp;
81
+ return {
82
+ count,
83
+ lastMissedFireAt,
84
+ windowStart: firstDueAt,
85
+ windowEnd: cappedBeforeThroughTimestamp ? lastMissedFireAt : throughTimestamp
86
+ };
87
+ }
45
88
  function resolveNextScheduleFireAt(state, work, now) {
46
89
  if (work.skipMissedOccurrences)
47
- return getNextScheduleOccurrence(state, now);
90
+ return getNextScheduleOccurrence(state, work.missedOccurrences?.lastMissedFireAt ?? now);
48
91
  const anchorOccurrence = work.occurrencesToProcess.at(-1) ?? work.dueOccurrences.at(-1);
49
92
  return getNextScheduleOccurrence(state, anchorOccurrence);
50
93
  }
51
- async function processScheduleTimerOccurrences(internals, state, occurrencesToProcess, now, callbacks, onProcessedState) {
94
+ async function processScheduleTimerOccurrences(internals, state, work, now, callbacks, options) {
52
95
  let nextState = state;
53
- for (const occurrence of occurrencesToProcess) {
96
+ for (const [index, occurrence] of work.occurrencesToProcess.entries()) {
97
+ const finalOccurrence = index === work.occurrencesToProcess.length - 1;
54
98
  nextState = {
55
- ...await callbacks.applyScheduleOccurrence(nextState),
99
+ ...await callbacks.applyScheduleOccurrence(nextState, occurrence),
56
100
  lastFireAt: occurrence,
57
101
  updatedAt: now
58
102
  };
59
- onProcessedState(nextState);
60
- await writeScheduleState(internals, nextState, { includeTimer: !1 });
103
+ if (finalOccurrence)
104
+ nextState = {
105
+ ...nextState,
106
+ nextFireAt: resolveNextScheduleFireAt(nextState, work, now)
107
+ };
108
+ options.onProcessedState(nextState);
109
+ await persistScheduleTimerState(internals, nextState, { includeTimer: finalOccurrence });
61
110
  if (state.backfill && nextState.currentWorkflowId !== void 0) {
62
111
  nextState = await callbacks.settleBackfillScheduleState(nextState);
63
- onProcessedState(nextState);
112
+ if (finalOccurrence) {
113
+ nextState = {
114
+ ...nextState,
115
+ updatedAt: now,
116
+ nextFireAt: resolveNextScheduleFireAt(nextState, work, now)
117
+ };
118
+ await persistScheduleTimerState(internals, nextState);
119
+ }
120
+ options.onProcessedState(nextState);
64
121
  }
65
122
  }
66
123
  return nextState;
67
124
  }
125
+ async function persistScheduleTimerState(internals, state, options) {
126
+ try {
127
+ await writeScheduleState(internals, state, options);
128
+ } catch (error) {
129
+ throw new ScheduleStatePersistenceError(state.id, error);
130
+ }
131
+ }
68
132
  async function pauseScheduleAfterTimerFailure(internals, state, error) {
69
133
  const errorNow = internals.options.getNow(), pausedState = {
70
134
  ...state,
@@ -2,6 +2,7 @@ import type { BatchOperation } from '../../storage/interface.ts';
2
2
  import type { PaginatedResult, ScheduleFilter, ScheduleOptions, ScheduleSpec, ScheduleState, ScheduleSummary, WorkflowState } from '../types.ts';
3
3
  import type { EngineInternals } from './internals.ts';
4
4
  import { ScheduleHandle } from './schedule-handle.ts';
5
+ export { startScheduledRun } from './schedule-run.ts';
5
6
  export { handleScheduleTimer } from './schedule-timer.ts';
6
7
  export type RefreshedScheduleState = {
7
8
  state: ScheduleState;
@@ -15,20 +16,22 @@ export type ScheduleCallbacks = {
15
16
  cancelWorkflow: (workflowId: string) => Promise<void>;
16
17
  getWorkflowResult: (workflowId: string) => Promise<unknown>;
17
18
  refreshScheduledWorkflowState: (state: ScheduleState) => Promise<RefreshedScheduleState>;
18
- startScheduledRun: (state: ScheduleState) => Promise<string>;
19
- applyScheduleOccurrence: (state: ScheduleState) => Promise<ScheduleState>;
19
+ startScheduledRun: (state: ScheduleState, occurrence?: number) => Promise<string>;
20
+ applyScheduleOccurrence: (state: ScheduleState, occurrence?: number) => Promise<ScheduleState>;
20
21
  settleBackfillScheduleState: (state: ScheduleState) => Promise<ScheduleState>;
21
22
  flushQueuedInlineWorkflowStartsDirectly: () => Promise<void>;
23
+ failWorkflow: (workflowId: string, error: Error) => Promise<void>;
24
+ handleCleanupError: (source: string, error: unknown, workflowId: string) => void;
22
25
  };
23
26
  export declare function schedule(internals: EngineInternals, type: string, input: unknown, spec: string | ScheduleSpec, options?: ScheduleOptions): Promise<ScheduleHandle>;
24
27
  export declare function listSchedules(internals: EngineInternals, filter?: ScheduleFilter): Promise<PaginatedResult<ScheduleSummary>>;
28
+ export declare function recoverOrphanedScheduleTimers(internals: EngineInternals): Promise<void>;
25
29
  export declare function toScheduleSummary(state: ScheduleState): ScheduleSummary;
26
30
  export declare function pauseSchedule(internals: EngineInternals, scheduleId: string): Promise<void>;
27
31
  export declare function resumeSchedule(internals: EngineInternals, scheduleId: string): Promise<void>;
28
32
  export declare function cancelSchedule(internals: EngineInternals, scheduleId: string): Promise<void>;
29
33
  export declare function updateSchedule(internals: EngineInternals, scheduleId: string, newSpec: string | ScheduleSpec): Promise<void>;
30
34
  export declare function refreshScheduledWorkflowState(internals: EngineInternals, state: ScheduleState, callbacks: Pick<ScheduleCallbacks, 'loadWorkflowState'>): Promise<RefreshedScheduleState>;
31
- export declare function startScheduledRun(_internals: EngineInternals, state: ScheduleState, callbacks: Pick<ScheduleCallbacks, 'startWorkflow'>): Promise<string>;
32
- export declare function applyScheduleOccurrence(_internals: EngineInternals, state: ScheduleState, callbacks: ScheduleCallbacks): Promise<ScheduleState>;
35
+ export declare function applyScheduleOccurrence(_internals: EngineInternals, state: ScheduleState, callbacks: ScheduleCallbacks, occurrence?: number): Promise<ScheduleState>;
33
36
  export declare function settleBackfillScheduleState(internals: EngineInternals, state: ScheduleState, callbacks: Pick<ScheduleCallbacks, 'flushQueuedInlineWorkflowStartsDirectly' | 'refreshScheduledWorkflowState'>): Promise<ScheduleState>;
34
37
  export declare function handleScheduledWorkflowTerminal(internals: EngineInternals, workflowId: string, callbacks: ScheduleCallbacks): Promise<void>;