@temelj/workflow 0.0.0-alpha.1

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 (393) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +38 -0
  3. package/dist/attributes.d.mts +15 -0
  4. package/dist/attributes.mjs +30 -0
  5. package/dist/client/create.d.mts +31 -0
  6. package/dist/client/create.mjs +67 -0
  7. package/dist/client/facades.d.mts +21 -0
  8. package/dist/client/facades.mjs +142 -0
  9. package/dist/client/mod.d.mts +2 -0
  10. package/dist/client/mod.mjs +2 -0
  11. package/dist/client/run-handle.d.mts +66 -0
  12. package/dist/client/run-handle.mjs +156 -0
  13. package/dist/client/worker-options.d.mts +17 -0
  14. package/dist/client/worker-options.mjs +25 -0
  15. package/dist/collection.d.mts +15 -0
  16. package/dist/collection.mjs +33 -0
  17. package/dist/compiled-function.d.mts +27 -0
  18. package/dist/compiled-function.mjs +54 -0
  19. package/dist/definition.d.mts +37 -0
  20. package/dist/definition.mjs +83 -0
  21. package/dist/engine/child-workflow.d.mts +10 -0
  22. package/dist/engine/child-workflow.mjs +333 -0
  23. package/dist/engine/command-identity.d.mts +9 -0
  24. package/dist/engine/command-identity.mjs +14 -0
  25. package/dist/engine/create.d.mts +106 -0
  26. package/dist/engine/create.mjs +402 -0
  27. package/dist/engine/deterministic.d.mts +12 -0
  28. package/dist/engine/deterministic.mjs +102 -0
  29. package/dist/engine/durable-command.d.mts +10 -0
  30. package/dist/engine/durable-command.mjs +17 -0
  31. package/dist/engine/execution-api.d.mts +29 -0
  32. package/dist/engine/execution-api.mjs +33 -0
  33. package/dist/engine/execution-service.d.mts +41 -0
  34. package/dist/engine/execution-service.mjs +288 -0
  35. package/dist/engine/hooks.d.mts +56 -0
  36. package/dist/engine/hooks.mjs +237 -0
  37. package/dist/engine/inspection-api.d.mts +34 -0
  38. package/dist/engine/inspection-api.mjs +77 -0
  39. package/dist/engine/inspection.d.mts +18 -0
  40. package/dist/engine/inspection.mjs +149 -0
  41. package/dist/engine/lifecycle.d.mts +18 -0
  42. package/dist/engine/lifecycle.mjs +38 -0
  43. package/dist/engine/lock-replay.d.mts +30 -0
  44. package/dist/engine/lock-replay.mjs +38 -0
  45. package/dist/engine/lock.d.mts +21 -0
  46. package/dist/engine/lock.mjs +197 -0
  47. package/dist/engine/message.d.mts +47 -0
  48. package/dist/engine/message.mjs +357 -0
  49. package/dist/engine/mod.d.mts +4 -0
  50. package/dist/engine/mod.mjs +2 -0
  51. package/dist/engine/observation.d.mts +35 -0
  52. package/dist/engine/observation.mjs +201 -0
  53. package/dist/engine/recovery.d.mts +26 -0
  54. package/dist/engine/recovery.mjs +92 -0
  55. package/dist/engine/replay.d.mts +41 -0
  56. package/dist/engine/replay.mjs +122 -0
  57. package/dist/engine/retry-policy.d.mts +4 -0
  58. package/dist/engine/retry-policy.mjs +4 -0
  59. package/dist/engine/retry.d.mts +23 -0
  60. package/dist/engine/retry.mjs +75 -0
  61. package/dist/engine/run-data.d.mts +9 -0
  62. package/dist/engine/run-data.mjs +74 -0
  63. package/dist/engine/run-service.d.mts +38 -0
  64. package/dist/engine/run-service.mjs +133 -0
  65. package/dist/engine/run-utils.d.mts +16 -0
  66. package/dist/engine/run-utils.mjs +83 -0
  67. package/dist/engine/schedule.d.mts +25 -0
  68. package/dist/engine/schedule.mjs +207 -0
  69. package/dist/engine/serialization.d.mts +9 -0
  70. package/dist/engine/serialization.mjs +85 -0
  71. package/dist/engine/start-api.d.mts +30 -0
  72. package/dist/engine/start-api.mjs +98 -0
  73. package/dist/engine/state.d.mts +77 -0
  74. package/dist/engine/state.mjs +464 -0
  75. package/dist/engine/step-api.d.mts +9 -0
  76. package/dist/engine/step-api.mjs +25 -0
  77. package/dist/engine/stream.d.mts +55 -0
  78. package/dist/engine/stream.mjs +333 -0
  79. package/dist/engine/summary/active-events.d.mts +34 -0
  80. package/dist/engine/summary/active-events.mjs +69 -0
  81. package/dist/engine/summary/child-workflow-runs.d.mts +24 -0
  82. package/dist/engine/summary/child-workflow-runs.mjs +138 -0
  83. package/dist/engine/summary/child-workflow-waits.d.mts +21 -0
  84. package/dist/engine/summary/child-workflow-waits.mjs +67 -0
  85. package/dist/engine/summary/recovery-child-workflow-waits.d.mts +11 -0
  86. package/dist/engine/summary/recovery-child-workflow-waits.mjs +89 -0
  87. package/dist/engine/summary/recovery-due-runs.d.mts +16 -0
  88. package/dist/engine/summary/recovery-due-runs.mjs +52 -0
  89. package/dist/engine/summary/recovery-failed-runs.d.mts +14 -0
  90. package/dist/engine/summary/recovery-failed-runs.mjs +33 -0
  91. package/dist/engine/summary/recovery-lease-runs.d.mts +16 -0
  92. package/dist/engine/summary/recovery-lease-runs.mjs +69 -0
  93. package/dist/engine/summary/recovery-locks.d.mts +18 -0
  94. package/dist/engine/summary/recovery-locks.mjs +100 -0
  95. package/dist/engine/summary/recovery-message-waits.d.mts +11 -0
  96. package/dist/engine/summary/recovery-message-waits.mjs +74 -0
  97. package/dist/engine/summary/recovery-retry-runs.d.mts +17 -0
  98. package/dist/engine/summary/recovery-retry-runs.mjs +65 -0
  99. package/dist/engine/summary/recovery-run-timestamps.d.mts +13 -0
  100. package/dist/engine/summary/recovery-run-timestamps.mjs +18 -0
  101. package/dist/engine/summary/recovery-runs.d.mts +23 -0
  102. package/dist/engine/summary/recovery-runs.mjs +54 -0
  103. package/dist/engine/summary/recovery-schedules.d.mts +10 -0
  104. package/dist/engine/summary/recovery-schedules.mjs +46 -0
  105. package/dist/engine/summary/recovery-sleep-waits.d.mts +10 -0
  106. package/dist/engine/summary/recovery-sleep-waits.mjs +53 -0
  107. package/dist/engine/summary/recovery-waits.d.mts +21 -0
  108. package/dist/engine/summary/recovery-waits.mjs +29 -0
  109. package/dist/engine/summary/run-availability.d.mts +13 -0
  110. package/dist/engine/summary/run-availability.mjs +37 -0
  111. package/dist/engine/summary/run-cleanup.d.mts +14 -0
  112. package/dist/engine/summary/run-cleanup.mjs +44 -0
  113. package/dist/engine/summary/run-failure.d.mts +14 -0
  114. package/dist/engine/summary/run-failure.mjs +62 -0
  115. package/dist/engine/summary/run-hooks.d.mts +14 -0
  116. package/dist/engine/summary/run-hooks.mjs +63 -0
  117. package/dist/engine/summary/run-lease.d.mts +11 -0
  118. package/dist/engine/summary/run-lease.mjs +64 -0
  119. package/dist/engine/summary/run-message-waits.d.mts +15 -0
  120. package/dist/engine/summary/run-message-waits.mjs +62 -0
  121. package/dist/engine/summary/run-metrics.d.mts +31 -0
  122. package/dist/engine/summary/run-metrics.mjs +93 -0
  123. package/dist/engine/summary/run-retry.d.mts +9 -0
  124. package/dist/engine/summary/run-retry.mjs +69 -0
  125. package/dist/engine/summary/run-sleeps.d.mts +15 -0
  126. package/dist/engine/summary/run-sleeps.mjs +61 -0
  127. package/dist/engine/summary/run-state.d.mts +26 -0
  128. package/dist/engine/summary/run-state.mjs +48 -0
  129. package/dist/engine/summary/run-status.d.mts +16 -0
  130. package/dist/engine/summary/run-status.mjs +35 -0
  131. package/dist/engine/summary/run-streams.d.mts +14 -0
  132. package/dist/engine/summary/run-streams.mjs +46 -0
  133. package/dist/engine/summary/run-transition.d.mts +9 -0
  134. package/dist/engine/summary/run-transition.mjs +39 -0
  135. package/dist/engine/summary/run-workflow.d.mts +9 -0
  136. package/dist/engine/summary/run-workflow.mjs +47 -0
  137. package/dist/engine/summary/step-attempt-active-child-workflows.d.mts +13 -0
  138. package/dist/engine/summary/step-attempt-active-child-workflows.mjs +55 -0
  139. package/dist/engine/summary/step-attempt-active-fields.d.mts +23 -0
  140. package/dist/engine/summary/step-attempt-active-fields.mjs +14 -0
  141. package/dist/engine/summary/step-attempt-active-message-waits.d.mts +12 -0
  142. package/dist/engine/summary/step-attempt-active-message-waits.mjs +47 -0
  143. package/dist/engine/summary/step-attempt-active-sleeps.d.mts +19 -0
  144. package/dist/engine/summary/step-attempt-active-sleeps.mjs +44 -0
  145. package/dist/engine/summary/step-attempt-buckets.d.mts +22 -0
  146. package/dist/engine/summary/step-attempt-buckets.mjs +152 -0
  147. package/dist/engine/summary/step-attempt-failure.d.mts +12 -0
  148. package/dist/engine/summary/step-attempt-failure.mjs +61 -0
  149. package/dist/engine/summary/step-attempt-lifecycle.d.mts +13 -0
  150. package/dist/engine/summary/step-attempt-lifecycle.mjs +19 -0
  151. package/dist/engine/summary/step-attempts.d.mts +11 -0
  152. package/dist/engine/summary/step-attempts.mjs +43 -0
  153. package/dist/engine/summary.d.mts +32 -0
  154. package/dist/engine/summary.mjs +37 -0
  155. package/dist/engine/task.d.mts +6 -0
  156. package/dist/engine/task.mjs +207 -0
  157. package/dist/errors/base.d.mts +99 -0
  158. package/dist/errors/base.mjs +426 -0
  159. package/dist/errors/capability.d.mts +11 -0
  160. package/dist/errors/capability.mjs +23 -0
  161. package/dist/errors/definition.d.mts +21 -0
  162. package/dist/errors/definition.mjs +51 -0
  163. package/dist/errors/details.d.mts +13 -0
  164. package/dist/errors/details.mjs +65 -0
  165. package/dist/errors/failures.d.mts +81 -0
  166. package/dist/errors/failures.mjs +168 -0
  167. package/dist/errors/hook.d.mts +14 -0
  168. package/dist/errors/hook.mjs +30 -0
  169. package/dist/errors/implementation.d.mts +11 -0
  170. package/dist/errors/implementation.mjs +25 -0
  171. package/dist/errors/lock.d.mts +28 -0
  172. package/dist/errors/lock.mjs +70 -0
  173. package/dist/errors/message.d.mts +106 -0
  174. package/dist/errors/message.mjs +122 -0
  175. package/dist/errors/mod.d.mts +17 -0
  176. package/dist/errors/mod.mjs +17 -0
  177. package/dist/errors/record-view.d.mts +11 -0
  178. package/dist/errors/record-view.mjs +24 -0
  179. package/dist/errors/records.d.mts +7 -0
  180. package/dist/errors/records.mjs +280 -0
  181. package/dist/errors/run.d.mts +116 -0
  182. package/dist/errors/run.mjs +232 -0
  183. package/dist/errors/runtime.d.mts +12 -0
  184. package/dist/errors/runtime.mjs +24 -0
  185. package/dist/errors/schedule.d.mts +27 -0
  186. package/dist/errors/schedule.mjs +65 -0
  187. package/dist/errors/step.d.mts +76 -0
  188. package/dist/errors/step.mjs +113 -0
  189. package/dist/errors/stream.d.mts +24 -0
  190. package/dist/errors/stream.mjs +64 -0
  191. package/dist/esbuild.d.mts +7 -0
  192. package/dist/esbuild.mjs +6 -0
  193. package/dist/events/descriptors.d.mts +245 -0
  194. package/dist/events/descriptors.mjs +405 -0
  195. package/dist/events/mod.d.mts +3 -0
  196. package/dist/events/mod.mjs +2 -0
  197. package/dist/history/attempt-key.d.mts +6 -0
  198. package/dist/history/attempt-key.mjs +7 -0
  199. package/dist/history/mod.d.mts +71 -0
  200. package/dist/history/mod.mjs +195 -0
  201. package/dist/history/projection.d.mts +8 -0
  202. package/dist/history/projection.mjs +259 -0
  203. package/dist/history/replay-projection.d.mts +88 -0
  204. package/dist/history/replay-projection.mjs +369 -0
  205. package/dist/history/sequencer.d.mts +16 -0
  206. package/dist/history/sequencer.mjs +78 -0
  207. package/dist/history/step-attempts.d.mts +9 -0
  208. package/dist/history/step-attempts.mjs +50 -0
  209. package/dist/history/timeline.d.mts +16 -0
  210. package/dist/history/timeline.mjs +272 -0
  211. package/dist/history/validator.d.mts +9 -0
  212. package/dist/history/validator.mjs +110 -0
  213. package/dist/inspection/mod.d.mts +5 -0
  214. package/dist/inspection/mod.mjs +3 -0
  215. package/dist/message-options.d.mts +8 -0
  216. package/dist/message-options.mjs +25 -0
  217. package/dist/mod.d.mts +52 -0
  218. package/dist/mod.mjs +26 -0
  219. package/dist/otel/support.d.mts +18 -0
  220. package/dist/otel/support.mjs +102 -0
  221. package/dist/otel.d.mts +30 -0
  222. package/dist/otel.mjs +588 -0
  223. package/dist/pagination.d.mts +25 -0
  224. package/dist/pagination.mjs +73 -0
  225. package/dist/registry.d.mts +20 -0
  226. package/dist/registry.mjs +48 -0
  227. package/dist/rolldown.d.mts +7 -0
  228. package/dist/rolldown.mjs +6 -0
  229. package/dist/rollup.d.mts +7 -0
  230. package/dist/rollup.mjs +6 -0
  231. package/dist/rspack.d.mts +7 -0
  232. package/dist/rspack.mjs +6 -0
  233. package/dist/runtime.d.mts +34 -0
  234. package/dist/runtime.mjs +194 -0
  235. package/dist/step-definition.d.mts +10 -0
  236. package/dist/step-definition.mjs +15 -0
  237. package/dist/store/append-projection.d.mts +15 -0
  238. package/dist/store/append-projection.mjs +26 -0
  239. package/dist/store/capabilities.d.mts +14 -0
  240. package/dist/store/capabilities.mjs +42 -0
  241. package/dist/store/cleanup.d.mts +18 -0
  242. package/dist/store/cleanup.mjs +338 -0
  243. package/dist/store/compaction.d.mts +5 -0
  244. package/dist/store/compaction.mjs +8 -0
  245. package/dist/store/create.d.mts +52 -0
  246. package/dist/store/create.mjs +159 -0
  247. package/dist/store/event-append-project.d.mts +15 -0
  248. package/dist/store/event-append-project.mjs +77 -0
  249. package/dist/store/event-append.d.mts +37 -0
  250. package/dist/store/event-append.mjs +80 -0
  251. package/dist/store/event-history.d.mts +22 -0
  252. package/dist/store/event-history.mjs +75 -0
  253. package/dist/store/event.d.mts +10 -0
  254. package/dist/store/event.mjs +28 -0
  255. package/dist/store/idempotency.d.mts +10 -0
  256. package/dist/store/idempotency.mjs +167 -0
  257. package/dist/store/instrumentation.d.mts +7 -0
  258. package/dist/store/instrumentation.mjs +123 -0
  259. package/dist/store/lock.d.mts +8 -0
  260. package/dist/store/lock.mjs +28 -0
  261. package/dist/store/materialization.d.mts +30 -0
  262. package/dist/store/materialization.mjs +127 -0
  263. package/dist/store/message-index.d.mts +21 -0
  264. package/dist/store/message-index.mjs +121 -0
  265. package/dist/store/mod.d.mts +5 -0
  266. package/dist/store/mod.mjs +4 -0
  267. package/dist/store/query.d.mts +24 -0
  268. package/dist/store/query.mjs +82 -0
  269. package/dist/store/revision.d.mts +4 -0
  270. package/dist/store/revision.mjs +7 -0
  271. package/dist/store/run.d.mts +49 -0
  272. package/dist/store/run.mjs +236 -0
  273. package/dist/store/schedule.d.mts +12 -0
  274. package/dist/store/schedule.mjs +41 -0
  275. package/dist/store/schema.d.mts +14 -0
  276. package/dist/store/schema.mjs +17 -0
  277. package/dist/store/step-attempt.d.mts +14 -0
  278. package/dist/store/step-attempt.mjs +23 -0
  279. package/dist/store/storage-value.d.mts +5 -0
  280. package/dist/store/storage-value.mjs +6 -0
  281. package/dist/store/validation.d.mts +35 -0
  282. package/dist/store/validation.mjs +77 -0
  283. package/dist/store-keys.d.mts +49 -0
  284. package/dist/store-keys.mjs +63 -0
  285. package/dist/telemetry.d.mts +132 -0
  286. package/dist/telemetry.mjs +172 -0
  287. package/dist/temporal.d.mts +23 -0
  288. package/dist/temporal.mjs +59 -0
  289. package/dist/timer.d.mts +12 -0
  290. package/dist/timer.mjs +28 -0
  291. package/dist/types/cleanup.d.mts +112 -0
  292. package/dist/types/cleanup.mjs +22 -0
  293. package/dist/types/client.d.mts +270 -0
  294. package/dist/types/client.mjs +1 -0
  295. package/dist/types/common.d.mts +19 -0
  296. package/dist/types/common.mjs +15 -0
  297. package/dist/types/definition.d.mts +92 -0
  298. package/dist/types/definition.mjs +1 -0
  299. package/dist/types/engine-options.d.mts +76 -0
  300. package/dist/types/engine-options.mjs +1 -0
  301. package/dist/types/engine.d.mts +309 -0
  302. package/dist/types/engine.mjs +1 -0
  303. package/dist/types/error-code.d.mts +256 -0
  304. package/dist/types/error-code.mjs +131 -0
  305. package/dist/types/error.d.mts +236 -0
  306. package/dist/types/error.mjs +48 -0
  307. package/dist/types/events.d.mts +2869 -0
  308. package/dist/types/events.mjs +283 -0
  309. package/dist/types/hook.d.mts +149 -0
  310. package/dist/types/hook.mjs +66 -0
  311. package/dist/types/lock.d.mts +63 -0
  312. package/dist/types/lock.mjs +18 -0
  313. package/dist/types/message-id.d.mts +7 -0
  314. package/dist/types/message-id.mjs +5 -0
  315. package/dist/types/message.d.mts +87 -0
  316. package/dist/types/message.mjs +1 -0
  317. package/dist/types/observation.d.mts +146 -0
  318. package/dist/types/observation.mjs +1 -0
  319. package/dist/types/pagination.d.mts +32 -0
  320. package/dist/types/pagination.mjs +13 -0
  321. package/dist/types/result.d.mts +62 -0
  322. package/dist/types/result.mjs +1 -0
  323. package/dist/types/retry.d.mts +48 -0
  324. package/dist/types/retry.mjs +1 -0
  325. package/dist/types/run-id.d.mts +7 -0
  326. package/dist/types/run-id.mjs +5 -0
  327. package/dist/types/run-list.d.mts +43 -0
  328. package/dist/types/run-list.mjs +1 -0
  329. package/dist/types/run-options.d.mts +86 -0
  330. package/dist/types/run-options.mjs +1 -0
  331. package/dist/types/run.d.mts +355 -0
  332. package/dist/types/run.mjs +207 -0
  333. package/dist/types/runtime.d.mts +143 -0
  334. package/dist/types/runtime.mjs +21 -0
  335. package/dist/types/schedule.d.mts +127 -0
  336. package/dist/types/schedule.mjs +48 -0
  337. package/dist/types/step-attempts.d.mts +326 -0
  338. package/dist/types/step-attempts.mjs +43 -0
  339. package/dist/types/step-id.d.mts +7 -0
  340. package/dist/types/step-id.mjs +5 -0
  341. package/dist/types/step.d.mts +183 -0
  342. package/dist/types/step.mjs +5 -0
  343. package/dist/types/store.d.mts +254 -0
  344. package/dist/types/store.mjs +1 -0
  345. package/dist/types/stream-id.d.mts +7 -0
  346. package/dist/types/stream-id.mjs +5 -0
  347. package/dist/types/stream.d.mts +126 -0
  348. package/dist/types/stream.mjs +1 -0
  349. package/dist/types/summary.d.mts +318 -0
  350. package/dist/types/summary.mjs +1 -0
  351. package/dist/types/telemetry.d.mts +74 -0
  352. package/dist/types/telemetry.mjs +9 -0
  353. package/dist/types/timeline.d.mts +237 -0
  354. package/dist/types/timeline.mjs +1 -0
  355. package/dist/types/vite.d.mts +65 -0
  356. package/dist/types/vite.mjs +1 -0
  357. package/dist/types/worker-id.d.mts +7 -0
  358. package/dist/types/worker-id.mjs +5 -0
  359. package/dist/types/worker.d.mts +94 -0
  360. package/dist/types/worker.mjs +1 -0
  361. package/dist/utility.d.mts +49 -0
  362. package/dist/utility.mjs +122 -0
  363. package/dist/vite/ast.d.mts +23 -0
  364. package/dist/vite/ast.mjs +73 -0
  365. package/dist/vite/error.d.mts +19 -0
  366. package/dist/vite/error.mjs +47 -0
  367. package/dist/vite/generated-name.d.mts +7 -0
  368. package/dist/vite/generated-name.mjs +9 -0
  369. package/dist/vite/manifest.d.mts +7 -0
  370. package/dist/vite/manifest.mjs +106 -0
  371. package/dist/vite/plugin.d.mts +7 -0
  372. package/dist/vite/plugin.mjs +190 -0
  373. package/dist/vite/safety.d.mts +12 -0
  374. package/dist/vite/safety.mjs +96 -0
  375. package/dist/vite/source-edit.d.mts +12 -0
  376. package/dist/vite/source-edit.mjs +44 -0
  377. package/dist/vite/source-map.d.mts +11 -0
  378. package/dist/vite/source-map.mjs +53 -0
  379. package/dist/vite/source.d.mts +7 -0
  380. package/dist/vite/source.mjs +14 -0
  381. package/dist/vite/transform.d.mts +7 -0
  382. package/dist/vite/transform.mjs +405 -0
  383. package/dist/vite.d.mts +6 -0
  384. package/dist/vite.mjs +5 -0
  385. package/dist/webhook.d.mts +16 -0
  386. package/dist/webhook.mjs +17 -0
  387. package/dist/webpack.d.mts +7 -0
  388. package/dist/webpack.mjs +6 -0
  389. package/dist/worker/error.d.mts +11 -0
  390. package/dist/worker/error.mjs +40 -0
  391. package/dist/worker.d.mts +18 -0
  392. package/dist/worker.mjs +427 -0
  393. package/package.json +144 -0
@@ -0,0 +1,197 @@
1
+ import { WorkflowOptionsError } from "../errors/base.mjs";
2
+ import { WorkflowNonRetryableError, WorkflowRetryableError } from "../errors/failures.mjs";
3
+ import { isPositiveSafeInteger, positiveSafeInteger } from "../utility.mjs";
4
+ import { WorkflowLockError, WorkflowLockStateError } from "../errors/lock.mjs";
5
+ import "../errors/mod.mjs";
6
+ import { WorkflowSuspended, patchRun } from "./state.mjs";
7
+ import { recordWorkflowDeterministicValue } from "./deterministic.mjs";
8
+ import { requireLockReleaseReplayMatches, requireLockReplayMatches, requireLockWaitDeadlineReplayMatches, requireLockWaitReplayMatches } from "./lock-replay.mjs";
9
+ //#region src/engine/lock.ts
10
+ function createWorkflowStepLockApi(environment, engine, run) {
11
+ const { runId, history } = environment;
12
+ const acquire = async (commandId, key, options) => {
13
+ const requestedLeaseDuration = positiveSafeInteger(options.leaseDuration.total({ unit: "millisecond" }), "Workflow lock lease duration");
14
+ const waitDeadlineAt = options.waitTimeout === void 0 ? void 0 : await recordLockWaitDeadline(environment, commandId, options.waitTimeout);
15
+ const { waitTimeout: _waitTimeout, ...engineLockOptions } = options;
16
+ const lock = await run({
17
+ commandId,
18
+ retry: { maximumAttempts: options.wait === true ? 0 : 1 }
19
+ }, async (context) => {
20
+ return await engine.acquireLock(key, {
21
+ ...engineLockOptions,
22
+ holderId: options.holderId ?? runId,
23
+ holderRunId: runId,
24
+ holderStepId: context.step.id,
25
+ ...waitDeadlineAt === void 0 ? {} : { waitDeadlineAt }
26
+ });
27
+ });
28
+ requireLockReplayMatches(lock, {
29
+ key,
30
+ holderId: options.holderId ?? runId,
31
+ holderRunId: runId,
32
+ leaseDuration: requestedLeaseDuration
33
+ });
34
+ requireLockWaitReplayMatches(history.failedSteps(`run:${commandId}`), {
35
+ key,
36
+ wait: options.wait === true
37
+ });
38
+ return lock;
39
+ };
40
+ const release = async (commandId, key, options) => {
41
+ const holderId = options?.holderId ?? runId;
42
+ const lock = await run({
43
+ commandId,
44
+ retry: { maximumAttempts: 1 }
45
+ }, async () => {
46
+ return await engine.releaseLock(key, {
47
+ holderId,
48
+ ...options?.now === void 0 ? {} : { now: options.now }
49
+ });
50
+ });
51
+ requireLockReleaseReplayMatches(lock, {
52
+ key,
53
+ holderId
54
+ });
55
+ return lock;
56
+ };
57
+ return {
58
+ acquire,
59
+ release,
60
+ async with(commandId, key, options, callback) {
61
+ const lock = await acquire(`${commandId}:acquire`, key, options);
62
+ try {
63
+ const output = await callback(lock);
64
+ await release(`${commandId}:release`, key, {
65
+ ...options.holderId === void 0 ? {} : { holderId: options.holderId },
66
+ ...options.now === void 0 ? {} : { now: options.now }
67
+ });
68
+ return output;
69
+ } catch (error) {
70
+ if (error instanceof WorkflowSuspended) throw error;
71
+ await release(`${commandId}:release`, key, {
72
+ ...options.holderId === void 0 ? {} : { holderId: options.holderId },
73
+ ...options.now === void 0 ? {} : { now: options.now }
74
+ });
75
+ throw error;
76
+ }
77
+ }
78
+ };
79
+ }
80
+ async function acquireLock(store, key, lockOptions, acquiredAt) {
81
+ const holderId = lockOptions.holderId;
82
+ const leaseDuration = positiveDurationMilliseconds(lockOptions.leaseDuration, "Workflow lock lease duration");
83
+ const waitDeadlineAt = resolveLockWaitDeadline(lockOptions, acquiredAt);
84
+ const existing = await store.getLock(key);
85
+ if (existing !== void 0 && !(existing.holderId === holderId || existing.releasedAt !== void 0) && Temporal.Instant.compare(existing.leaseExpiresAt, acquiredAt) > 0) {
86
+ if (lockOptions.wait === true) {
87
+ if (waitDeadlineAt !== void 0 && Temporal.Instant.compare(waitDeadlineAt, acquiredAt) <= 0) WorkflowNonRetryableError.failed(`Workflow lock wait timed out: ${key}`, { details: {
88
+ key,
89
+ holderId,
90
+ currentHolderId: existing.holderId,
91
+ waitDeadlineAt: waitDeadlineAt.toString()
92
+ } });
93
+ const retryAt = workflowLockRetryAt(existing, acquiredAt, waitDeadlineAt);
94
+ throw WorkflowRetryableError.lockAlreadyHeld(key, {
95
+ retryAt,
96
+ details: {
97
+ key,
98
+ holderId,
99
+ currentHolderId: existing.holderId,
100
+ ...waitDeadlineAt === void 0 ? {} : { waitDeadlineAt: waitDeadlineAt.toString() }
101
+ }
102
+ });
103
+ }
104
+ WorkflowLockError.alreadyHeld(key);
105
+ }
106
+ const lock = {
107
+ key,
108
+ namespace: store.namespace,
109
+ holderId,
110
+ ...lockOptions.holderRunId === void 0 ? {} : { holderRunId: lockOptions.holderRunId },
111
+ ...lockOptions.holderStepId === void 0 ? {} : { holderStepId: lockOptions.holderStepId },
112
+ fencingToken: (existing?.fencingToken ?? 0) + 1,
113
+ acquiredAt,
114
+ leaseExpiresAt: acquiredAt.add(Temporal.Duration.from({ milliseconds: leaseDuration }))
115
+ };
116
+ const acquired = await store.updateLockIfCurrent(existing, lock);
117
+ if (acquired === void 0) WorkflowLockStateError.acquireConflictExhausted(key);
118
+ return acquired;
119
+ }
120
+ async function releaseLock(store, key, lockOptions, releasedAt) {
121
+ const holderId = lockOptions.holderId;
122
+ const current = await store.getLock(key);
123
+ if (current === void 0) WorkflowLockStateError.notFound(key);
124
+ if (current.holderId !== holderId) WorkflowLockError.holderMismatch(key);
125
+ const released = {
126
+ ...current,
127
+ releasedAt
128
+ };
129
+ const updated = await store.updateLockIfCurrent(current, released);
130
+ if (updated === void 0) WorkflowLockStateError.releaseConflictExhausted(key);
131
+ await wakeWorkflowRunsWaitingForLock(store, key, releasedAt);
132
+ return updated;
133
+ }
134
+ async function releaseStaleLock(store, key, releasedAt) {
135
+ const current = await store.getLock(key);
136
+ if (current === void 0) WorkflowLockStateError.notFound(key);
137
+ if (current.releasedAt !== void 0) WorkflowLockError.alreadyReleased(key);
138
+ if (Temporal.Instant.compare(current.leaseExpiresAt, releasedAt) > 0) WorkflowLockError.notStale(key);
139
+ const released = {
140
+ ...current,
141
+ releasedAt
142
+ };
143
+ const updated = await store.updateLockIfCurrent(current, released);
144
+ if (updated === void 0) WorkflowLockStateError.staleReleaseConflictExhausted(key);
145
+ await wakeWorkflowRunsWaitingForLock(store, key, releasedAt);
146
+ return updated;
147
+ }
148
+ function resolveLockWaitDeadline(options, now) {
149
+ if (options.waitTimeout !== void 0 && options.waitDeadlineAt !== void 0) WorkflowLockError.waitDeadlineConflict();
150
+ if ((options.waitTimeout !== void 0 || options.waitDeadlineAt !== void 0) && options.wait !== true) WorkflowLockError.timeoutRequiresWait();
151
+ if (options.waitDeadlineAt !== void 0) return options.waitDeadlineAt;
152
+ if (options.waitTimeout === void 0) return;
153
+ positiveDurationMilliseconds(options.waitTimeout, "Workflow lock waitTimeout");
154
+ return now.add(options.waitTimeout);
155
+ }
156
+ function positiveDurationMilliseconds(duration, label) {
157
+ const milliseconds = duration.total({ unit: "millisecond" });
158
+ if (!isPositiveSafeInteger(milliseconds)) WorkflowOptionsError.positiveSafeIntegerDuration(label);
159
+ return milliseconds;
160
+ }
161
+ async function recordLockWaitDeadline(environment, name, timeout) {
162
+ const resolvedTimeout = positiveSafeInteger(timeout.total({ unit: "millisecond" }), "Workflow lock waitTimeout");
163
+ return await recordWorkflowDeterministicValue(environment, `${name}:wait-deadline`, () => environment.now().add(Temporal.Duration.from({ milliseconds: resolvedTimeout })), (recorded) => requireLockWaitDeadlineReplayMatches(recorded, resolvedTimeout));
164
+ }
165
+ function workflowLockRetryAt(lock, now, waitDeadlineAt) {
166
+ const retryAt = Temporal.Instant.compare(lock.leaseExpiresAt, now) <= 0 ? now : lock.leaseExpiresAt;
167
+ if (waitDeadlineAt !== void 0 && Temporal.Instant.compare(waitDeadlineAt, retryAt) < 0) return waitDeadlineAt;
168
+ return retryAt;
169
+ }
170
+ async function wakeWorkflowRunsWaitingForLock(store, key, timestamp) {
171
+ const wakeAt = timestamp;
172
+ const waitingRuns = await store.listRuns({
173
+ status: "waiting",
174
+ retryReason: "step"
175
+ });
176
+ await Promise.all(waitingRuns.map(async (run) => {
177
+ if (run.availableAt !== void 0 && Temporal.Instant.compare(run.availableAt, wakeAt) <= 0) return;
178
+ if (!(await store.listStepAttempts(run.id, {
179
+ kind: "run",
180
+ status: "failed"
181
+ })).some((attempt) => WorkflowRetryableError.isLockAlreadyHeld(attempt.error, key))) return;
182
+ await patchRun(store, run, {
183
+ availableAt: wakeAt,
184
+ retryAt: wakeAt,
185
+ updatedAt: wakeAt,
186
+ lastTransitionAt: wakeAt,
187
+ lastTransitionReason: "retry",
188
+ deadlineAt: run.deadlineAt,
189
+ startedAt: run.startedAt ?? wakeAt,
190
+ error: run.error,
191
+ output: void 0,
192
+ finishedAt: void 0
193
+ });
194
+ }));
195
+ }
196
+ //#endregion
197
+ export { acquireLock, createWorkflowStepLockApi, releaseLock, releaseStaleLock };
@@ -0,0 +1,47 @@
1
+ import { RunId } from "../types/run-id.mjs";
2
+ import { BroadcastMessageChannelOptions, BroadcastMessageInput, BroadcastMessageResult, MessageChannel, SendMessageChannelOptions, SendMessageInput, SendMessageOptions, WaitForMessageOptions } from "../types/message.mjs";
3
+ import { WorkflowStepMessageApi } from "../types/step.mjs";
4
+ import { Telemetry, TelemetryContext } from "../types/telemetry.mjs";
5
+ import { WorkflowStepIdentity } from "../types/run.mjs";
6
+ import { EventRecord } from "../types/events.mjs";
7
+ import "../history/mod.mjs";
8
+ import { WorkflowConditionalEventAppender, WorkflowEventReader, WorkflowMessageIdempotencyIndexLookup, WorkflowRunConditionalWriterRepository, WorkflowRunListerRepository, WorkflowRunReaderRepository } from "../types/store.mjs";
9
+ import { WorkflowExecutionLimits } from "../types/engine-options.mjs";
10
+ import { WorkflowExecutionEnvironment } from "../types/engine.mjs";
11
+ import { Schema } from "@temelj/standard-schema";
12
+ //#region src/engine/message.d.ts
13
+ type MessageWaitSource = Extract<EventRecord, {
14
+ readonly kind: "message_wait_started";
15
+ }>["source"];
16
+ type WorkflowMessageWaitOptions = WaitForMessageOptions<Schema | undefined> & {
17
+ readonly source?: MessageWaitSource;
18
+ };
19
+ type WorkflowMessageDeliveryStore = WorkflowMessageIdempotencyIndexLookup & WorkflowRunReaderRepository & WorkflowEventReader & WorkflowConditionalEventAppender & WorkflowRunConditionalWriterRepository;
20
+ type WorkflowMessageStore = WorkflowMessageDeliveryStore & WorkflowRunListerRepository;
21
+ interface WorkflowMessageServiceOptions {
22
+ readonly store: WorkflowMessageStore;
23
+ readonly now: () => Temporal.Instant;
24
+ readonly limits: WorkflowExecutionLimits;
25
+ readonly observeMessageSent?: (runId: RunId, event: Extract<EventRecord, {
26
+ readonly kind: "message_sent";
27
+ }>) => void;
28
+ readonly telemetry?: Telemetry;
29
+ }
30
+ declare function createWorkflowStepMessageApi(environment: WorkflowExecutionEnvironment): WorkflowStepMessageApi;
31
+ declare function sendWorkflowMessageInput<TPayload, TKey = void>(service: WorkflowMessageServiceOptions, runId: RunId, messageInput: SendMessageInput | MessageChannel<TPayload, TKey>, channelOptions: SendMessageChannelOptions<TPayload, TKey> | undefined): Promise<void>;
32
+ declare function broadcastWorkflowMessageInput<TPayload, TKey = void>(service: WorkflowMessageServiceOptions, messageInput: BroadcastMessageInput | MessageChannel<TPayload, TKey>, channelOptions: BroadcastMessageChannelOptions<TPayload, TKey> | undefined): Promise<BroadcastMessageResult>;
33
+ declare function sendWorkflowMessage(store: WorkflowMessageDeliveryStore, runId: RunId, options: SendMessageOptions, now: () => Temporal.Instant, limits: WorkflowExecutionLimits, observeMessageSent?: (runId: RunId, event: Extract<EventRecord, {
34
+ readonly kind: "message_sent";
35
+ }>) => void, telemetry?: Telemetry, traceContext?: TelemetryContext): Promise<void>;
36
+ declare function waitForWorkflowMessage(environment: WorkflowExecutionEnvironment, options: WorkflowMessageWaitOptions): Promise<unknown>;
37
+ declare function requireMessageWaitReplayMatches(identity: WorkflowStepIdentity, started: Extract<EventRecord, {
38
+ readonly kind: "message_wait_started";
39
+ }> | undefined, event: Extract<EventRecord, {
40
+ readonly kind: "message_wait_started" | "message_wait_completed" | "message_wait_failed";
41
+ }>, options: WorkflowMessageWaitOptions): void;
42
+ declare function messageWaitAvailableAt(now: () => Temporal.Instant, timeoutAt: Temporal.Instant | undefined, deadlineAt: Temporal.Instant | undefined): Temporal.Instant;
43
+ declare function wakeRunForMessageEvent(store: WorkflowRunReaderRepository & WorkflowEventReader & WorkflowRunConditionalWriterRepository, runId: RunId, messageEvent: Extract<EventRecord, {
44
+ readonly kind: "message_sent";
45
+ }>): Promise<void>;
46
+ //#endregion
47
+ export { broadcastWorkflowMessageInput, createWorkflowStepMessageApi, messageWaitAvailableAt, requireMessageWaitReplayMatches, sendWorkflowMessage, sendWorkflowMessageInput, waitForWorkflowMessage, wakeRunForMessageEvent };
@@ -0,0 +1,357 @@
1
+ import { WorkflowStateError } from "../errors/base.mjs";
2
+ import { WorkflowDurationError, WorkflowReplayDivergenceError } from "../errors/failures.mjs";
3
+ import { getRequiredRun, safeDuration } from "../utility.mjs";
4
+ import { WorkflowMessageDeliveryError, WorkflowMessageIdempotencyConflictError, WorkflowMessageWaitTimeoutError } from "../errors/message.mjs";
5
+ import { resolveBroadcastMessageInput, resolveSendMessageInput, resolveWaitForMessageInput } from "../message-options.mjs";
6
+ import { workflowErrorFromRecord } from "../errors/records.mjs";
7
+ import { captureTelemetryContext } from "../telemetry.mjs";
8
+ import { serializeError, toOptionalPersistedValue } from "./serialization.mjs";
9
+ import { WorkflowHistory } from "../history/mod.mjs";
10
+ import { enforceWorkflowEventHistoryNextLimit } from "./retry.mjs";
11
+ import { WorkflowSuspended } from "./state.mjs";
12
+ import { resolveWorkflowCommandIdentity, resolveWorkflowCommandIdentityFromCandidates } from "./command-identity.mjs";
13
+ import { appendDurableStepStartedEvent, appendDurableStepTerminalEvent } from "./durable-command.mjs";
14
+ import { requireMessageSendReplayMatches, requireRecordedDurableTerminalStarted } from "./replay.mjs";
15
+ import { validateStandardSchema } from "@temelj/standard-schema";
16
+ import { deepEquals } from "@temelj/value";
17
+ //#region src/engine/message.ts
18
+ const MAX_MESSAGE_DELIVERY_APPEND_ATTEMPTS = 16;
19
+ function createWorkflowStepMessageApi(environment) {
20
+ const { store, history, now, limits } = environment;
21
+ return {
22
+ async send(targetRunId, messageInput, channelOptions) {
23
+ const options = await resolveSendMessageInput(messageInput, channelOptions);
24
+ const idempotencyKey = options.idempotencyKey;
25
+ const identity = resolveWorkflowCommandIdentity(history, "message-send", options.messageId);
26
+ const started = history.startedMessageSend(identity.id);
27
+ const completed = history.completedMessageSend(identity.id);
28
+ if (completed !== void 0) {
29
+ requireRecordedDurableTerminalStarted(identity, history.hasStartedEventBeforeTerminalEvent(completed));
30
+ requireMessageSendReplayMatches(identity, started, completed, {
31
+ targetRunId,
32
+ messageId: options.messageId,
33
+ payload: toOptionalPersistedValue(options.payload, "message payload", limits),
34
+ idempotencyKey
35
+ });
36
+ if (!(completed.timestamp instanceof Temporal.Instant)) WorkflowReplayDivergenceError.diverged(`recorded message-send step ${identity.id} has invalid completion timestamp: ` + String(completed.timestamp), {
37
+ expectedStepId: identity.id,
38
+ actualStepId: identity.id
39
+ });
40
+ return;
41
+ }
42
+ const failed = history.failedMessageSend(identity.id);
43
+ if (failed !== void 0) {
44
+ requireRecordedDurableTerminalStarted(identity, history.hasStartedEventBeforeTerminalEvent(failed));
45
+ requireMessageSendReplayMatches(identity, started, failed, {
46
+ targetRunId,
47
+ messageId: options.messageId,
48
+ payload: toOptionalPersistedValue(options.payload, "message payload", limits),
49
+ idempotencyKey
50
+ });
51
+ if (!(failed.timestamp instanceof Temporal.Instant)) WorkflowReplayDivergenceError.diverged(`recorded message-send step ${identity.id} has invalid failure timestamp: ` + String(failed.timestamp), {
52
+ expectedStepId: identity.id,
53
+ actualStepId: identity.id
54
+ });
55
+ throw workflowErrorFromRecord(failed.error);
56
+ }
57
+ const nextMessageSend = {
58
+ targetRunId,
59
+ messageId: options.messageId,
60
+ payload: toOptionalPersistedValue(options.payload, "message payload", limits),
61
+ idempotencyKey
62
+ };
63
+ if (started === void 0) await appendDurableStepStartedEvent(environment, {
64
+ kind: "message_send_started",
65
+ timestamp: now(),
66
+ stepId: identity.id,
67
+ stepName: identity.name,
68
+ count: identity.count,
69
+ targetRunId: nextMessageSend.targetRunId,
70
+ messageId: nextMessageSend.messageId,
71
+ payload: nextMessageSend.payload,
72
+ ...nextMessageSend.idempotencyKey === void 0 ? {} : { idempotencyKey: nextMessageSend.idempotencyKey }
73
+ });
74
+ else requireMessageSendReplayMatches(identity, started, started, nextMessageSend);
75
+ try {
76
+ await sendWorkflowMessage(store, targetRunId, {
77
+ ...options,
78
+ idempotencyKey
79
+ }, now, limits, environment.observeMessageSent, environment.telemetry);
80
+ } catch (error) {
81
+ await appendDurableStepTerminalEvent(environment, {
82
+ kind: "message_send_failed",
83
+ timestamp: now(),
84
+ stepId: identity.id,
85
+ stepName: identity.name,
86
+ targetRunId,
87
+ messageId: options.messageId,
88
+ error: serializeError(error)
89
+ });
90
+ throw error;
91
+ }
92
+ await appendDurableStepTerminalEvent(environment, {
93
+ kind: "message_send_completed",
94
+ timestamp: now(),
95
+ stepId: identity.id,
96
+ stepName: identity.name,
97
+ targetRunId,
98
+ messageId: options.messageId
99
+ });
100
+ },
101
+ async wait(messageInput, channelOptions) {
102
+ return await waitForWorkflowMessage(environment, resolveWaitForMessageInput(messageInput, channelOptions));
103
+ }
104
+ };
105
+ }
106
+ async function sendWorkflowMessageInput(service, runId, messageInput, channelOptions) {
107
+ const telemetryContext = captureTelemetryContext(service.telemetry);
108
+ const messageOptions = await resolveSendMessageInput(messageInput, channelOptions);
109
+ await sendWorkflowMessage(service.store, runId, messageOptions, service.now, service.limits, service.observeMessageSent, service.telemetry, telemetryContext);
110
+ }
111
+ async function broadcastWorkflowMessageInput(service, messageInput, channelOptions) {
112
+ const telemetryContext = captureTelemetryContext(service.telemetry);
113
+ const messageOptions = await resolveBroadcastMessageInput(messageInput, channelOptions);
114
+ toOptionalPersistedValue(messageOptions.payload, "message payload", service.limits);
115
+ const targets = await broadcastMessageTargets(service.store, messageOptions.target);
116
+ for (const target of targets) await sendWorkflowMessage(service.store, target.id, messageOptions, service.now, service.limits, service.observeMessageSent, service.telemetry, telemetryContext);
117
+ return {
118
+ messageId: messageOptions.messageId,
119
+ runIds: targets.map((target) => target.id),
120
+ deliveredMessages: targets.length
121
+ };
122
+ }
123
+ async function sendWorkflowMessage(store, runId, options, now, limits, observeMessageSent, telemetry, traceContext) {
124
+ const targetRunId = runId;
125
+ const idempotencyKey = options.idempotencyKey;
126
+ const telemetryContext = traceContext ?? captureTelemetryContext(telemetry);
127
+ const run = await getRequiredRun(store, targetRunId);
128
+ const payload = toOptionalPersistedValue(options.payload, "message payload", limits);
129
+ let timestamp;
130
+ let appendedEvents;
131
+ for (let attempt = 0; attempt < MAX_MESSAGE_DELIVERY_APPEND_ATTEMPTS && appendedEvents === void 0; attempt++) {
132
+ const currentRun = attempt === 0 ? run : await getRequiredRun(store, targetRunId);
133
+ const currentEvents = await store.getEvents(targetRunId);
134
+ const currentHistory = new WorkflowHistory(currentEvents);
135
+ if (idempotencyKey !== void 0) {
136
+ const existingMessage = currentHistory.messageByIdempotencyKey(idempotencyKey);
137
+ if (existingMessage !== void 0) {
138
+ if (existingMessage.messageId === options.messageId && deepEquals(existingMessage.payload, payload)) {
139
+ await wakeRunForMessageEvent(store, targetRunId, existingMessage);
140
+ return;
141
+ }
142
+ WorkflowMessageIdempotencyConflictError.conflict({
143
+ runId: targetRunId,
144
+ messageId: options.messageId,
145
+ idempotencyKey
146
+ });
147
+ }
148
+ await requireMessageIdempotencyIndexUnclaimed(store, targetRunId, options.messageId, idempotencyKey);
149
+ }
150
+ if (currentRun.status === "completed" || currentRun.status === "failed" || currentRun.status === "canceled") WorkflowMessageDeliveryError.cannotSend({
151
+ runId: targetRunId,
152
+ status: currentRun.status,
153
+ messageId: options.messageId
154
+ });
155
+ const waiterStepIds = currentHistory.activeMessageWaitStepIds(options.messageId);
156
+ timestamp ??= now();
157
+ enforceWorkflowEventHistoryNextLimit(currentEvents, limits);
158
+ appendedEvents = await store.appendEventIfRunCurrent(currentRun, {
159
+ kind: "message_sent",
160
+ timestamp,
161
+ messageId: options.messageId,
162
+ payload,
163
+ ...waiterStepIds.length === 0 ? {} : { waiterStepIds },
164
+ ...idempotencyKey === void 0 ? {} : { idempotencyKey },
165
+ ...telemetryContext === void 0 ? {} : { telemetryContext }
166
+ });
167
+ }
168
+ if (appendedEvents === void 0) {
169
+ const currentRun = await getRequiredRun(store, targetRunId);
170
+ if (currentRun.status === "completed" || currentRun.status === "failed" || currentRun.status === "canceled") WorkflowMessageDeliveryError.cannotSend({
171
+ runId: targetRunId,
172
+ status: currentRun.status,
173
+ messageId: options.messageId
174
+ });
175
+ WorkflowStateError.failedMessageAppend(targetRunId);
176
+ }
177
+ const appendedHistory = new WorkflowHistory(appendedEvents);
178
+ if (idempotencyKey !== void 0) {
179
+ const existingMessage = appendedHistory.messageByIdempotencyKey(idempotencyKey);
180
+ if (existingMessage !== void 0 && !workflowMessageSendMatches(existingMessage, options, payload)) WorkflowMessageIdempotencyConflictError.conflict({
181
+ runId: targetRunId,
182
+ messageId: options.messageId,
183
+ idempotencyKey
184
+ });
185
+ }
186
+ const messageEvent = appendedHistory.messageForSend(options.messageId, idempotencyKey) ?? {
187
+ kind: "message_sent",
188
+ timestamp: timestamp ?? now(),
189
+ messageId: options.messageId,
190
+ payload,
191
+ ...telemetryContext === void 0 ? {} : { telemetryContext }
192
+ };
193
+ observeMessageSent?.(targetRunId, messageEvent);
194
+ await wakeRunForMessageEvent(store, targetRunId, messageEvent);
195
+ }
196
+ async function broadcastMessageTargets(store, target) {
197
+ return (await store.listRuns(target)).filter((run) => !(run.status === "completed" || run.status === "failed" || run.status === "canceled"));
198
+ }
199
+ async function requireMessageIdempotencyIndexUnclaimed(store, runId, messageId, idempotencyKey) {
200
+ if (await store.hasMessageIdempotencyKey(runId, idempotencyKey)) WorkflowMessageIdempotencyConflictError.conflict({
201
+ runId,
202
+ messageId,
203
+ idempotencyKey
204
+ });
205
+ }
206
+ function workflowMessageSendMatches(event, options, payload) {
207
+ return event.messageId === options.messageId && deepEquals(event.payload, payload);
208
+ }
209
+ async function waitForWorkflowMessage(environment, options) {
210
+ const { runId, history, now, limits, executionOwner } = environment;
211
+ const identity = resolveWorkflowCommandIdentityFromCandidates(history, "message-wait", [
212
+ options.commandId,
213
+ options.name,
214
+ options.messageId
215
+ ], "Workflow message commandId, name, or messageId");
216
+ const started = history.startedMessageWait(identity.id);
217
+ const completed = history.completedMessageWait(identity.id);
218
+ if (completed !== void 0) {
219
+ requireRecordedDurableTerminalStarted(identity, history.hasStartedEventBeforeTerminalEvent(completed));
220
+ requireMessageWaitReplayMatches(identity, started, completed, options);
221
+ return options.schema === void 0 ? completed.payload : await validateStandardSchema(options.schema, completed.payload, "Workflow message validation failed");
222
+ }
223
+ const failed = history.failedMessageWait(identity.id);
224
+ if (failed !== void 0) {
225
+ requireRecordedDurableTerminalStarted(identity, history.hasStartedEventBeforeTerminalEvent(failed));
226
+ requireMessageWaitReplayMatches(identity, started, failed, options);
227
+ throw workflowErrorFromRecord(failed.error);
228
+ }
229
+ if (started !== void 0) requireMessageWaitReplayMatches(identity, started, started, options);
230
+ const timeoutAt = started?.timeoutAt === void 0 ? options.timeout === void 0 ? void 0 : (() => {
231
+ const timeout = safeDuration(options.timeout.total({ unit: "millisecond" }), "Workflow messageId timeout");
232
+ if (timeout <= 0) WorkflowDurationError.signalTimeoutPositive();
233
+ return now().add(Temporal.Duration.from({ milliseconds: timeout }));
234
+ })() : (() => {
235
+ if (!(started.timeoutAt instanceof Temporal.Instant)) WorkflowReplayDivergenceError.diverged(`recorded message-wait step ${identity.id} has invalid timeout timestamp: ` + String(started.timeoutAt), {
236
+ expectedStepId: identity.id,
237
+ actualStepId: identity.id
238
+ });
239
+ return started.timeoutAt;
240
+ })();
241
+ let waitStartedAt;
242
+ if (started === void 0) {
243
+ waitStartedAt = now();
244
+ await appendDurableStepStartedEvent(environment, {
245
+ kind: "message_wait_started",
246
+ timestamp: waitStartedAt,
247
+ stepId: identity.id,
248
+ stepName: identity.name,
249
+ count: identity.count,
250
+ messageId: options.messageId,
251
+ ...options.source === void 0 ? {} : { source: options.source },
252
+ ...timeoutAt === void 0 ? {} : { timeoutAt }
253
+ });
254
+ }
255
+ const messageId = history.messageForWait(options.messageId, identity.id, timeoutAt);
256
+ if (messageId !== void 0) {
257
+ let payload;
258
+ try {
259
+ payload = options.schema === void 0 ? messageId.payload : await validateStandardSchema(options.schema, messageId.payload, "Workflow message validation failed");
260
+ } catch (error) {
261
+ await appendDurableStepTerminalEvent(environment, {
262
+ kind: "message_wait_failed",
263
+ timestamp: now(),
264
+ stepId: identity.id,
265
+ stepName: identity.name,
266
+ messageId: options.messageId,
267
+ error: serializeError(error)
268
+ });
269
+ throw error;
270
+ }
271
+ const persistedPayload = toOptionalPersistedValue(payload, "messageId payload", limits);
272
+ await appendDurableStepTerminalEvent(environment, {
273
+ kind: "message_wait_completed",
274
+ timestamp: now(),
275
+ stepId: identity.id,
276
+ stepName: identity.name,
277
+ messageId: options.messageId,
278
+ ...persistedPayload === void 0 ? {} : { payload: persistedPayload },
279
+ messageTimestamp: messageId.timestamp,
280
+ ...messageId.telemetryContext === void 0 ? {} : { telemetryContext: messageId.telemetryContext }
281
+ });
282
+ return payload;
283
+ }
284
+ if (timeoutAt !== void 0 && Temporal.Instant.compare(timeoutAt, now()) <= 0) {
285
+ const error = WorkflowMessageWaitTimeoutError.create({
286
+ runId,
287
+ stepId: identity.id,
288
+ stepName: identity.name,
289
+ messageId: options.messageId,
290
+ timeoutAt
291
+ });
292
+ await appendDurableStepTerminalEvent(environment, {
293
+ kind: "message_wait_failed",
294
+ timestamp: now(),
295
+ stepId: identity.id,
296
+ stepName: identity.name,
297
+ messageId: options.messageId,
298
+ error: serializeError(error)
299
+ });
300
+ throw error;
301
+ }
302
+ WorkflowSuspended.until(messageWaitAvailableAt(now, timeoutAt, executionOwner.deadlineAt));
303
+ }
304
+ function requireMessageWaitReplayMatches(identity, started, event, options) {
305
+ const recordedMessage = started?.messageId ?? event.messageId;
306
+ if (started !== void 0 && !(started.timestamp instanceof Temporal.Instant)) WorkflowReplayDivergenceError.diverged(`recorded message-wait step ${identity.id} has invalid start timestamp: ` + String(started.timestamp), {
307
+ expectedStepId: identity.id,
308
+ actualStepId: identity.id
309
+ });
310
+ if (recordedMessage !== options.messageId) WorkflowReplayDivergenceError.diverged(`recorded message-wait step ${identity.id} waited for ${recordedMessage}, but replay waited for ${options.messageId}`, {
311
+ expectedStepId: identity.id,
312
+ actualStepId: identity.id
313
+ });
314
+ if (started !== void 0 && started.source !== options.source) {
315
+ const recordedSource = started.source ?? "message";
316
+ const replaySource = options.source ?? "message";
317
+ WorkflowReplayDivergenceError.diverged(`recorded message-wait step ${identity.id} was created by ${recordedSource}, but replay used ${replaySource}`, {
318
+ expectedStepId: identity.id,
319
+ actualStepId: identity.id
320
+ });
321
+ }
322
+ if (started !== void 0 && started.timeoutAt === void 0 !== (options.timeout === void 0)) {
323
+ const recordedTimeout = started.timeoutAt === void 0 ? "no timeout" : started.timeoutAt;
324
+ const replayTimeout = options.timeout === void 0 ? "no timeout" : "a timeout";
325
+ WorkflowReplayDivergenceError.diverged(`recorded message-wait step ${identity.id} had ${String(recordedTimeout)}, but replay used ${replayTimeout}`, {
326
+ expectedStepId: identity.id,
327
+ actualStepId: identity.id
328
+ });
329
+ }
330
+ if (event.kind === "message_wait_completed" && !(event.messageTimestamp instanceof Temporal.Instant)) WorkflowReplayDivergenceError.diverged(`recorded message-wait step ${identity.id} has invalid messageId timestamp: ` + String(event.messageTimestamp), {
331
+ expectedStepId: identity.id,
332
+ actualStepId: identity.id
333
+ });
334
+ }
335
+ function messageWaitAvailableAt(now, timeoutAt, deadlineAt) {
336
+ return [timeoutAt, deadlineAt].filter((value) => value !== void 0).sort((left, right) => Temporal.Instant.compare(left, right))[0] ?? now().add(Temporal.Duration.from({ milliseconds: 2 ** 31 - 1 }));
337
+ }
338
+ async function wakeRunForMessageEvent(store, runId, messageEvent) {
339
+ const run = await store.getRun(runId);
340
+ if (run === void 0 || run.status !== "waiting") return;
341
+ const activeWaits = new WorkflowHistory(await store.getEvents(runId)).activeMessageWaitStepIds(messageEvent.messageId);
342
+ if (!(messageEvent.waiterStepIds === void 0 ? activeWaits.length > 0 : activeWaits.some((stepId) => messageEvent.waiterStepIds?.includes(stepId)))) return;
343
+ await store.updateRunIfCurrent(run, {
344
+ ...run,
345
+ availableAt: run.availableAt !== void 0 && Temporal.Instant.compare(run.availableAt, messageEvent.timestamp) <= 0 ? run.availableAt : messageEvent.timestamp,
346
+ updatedAt: messageEvent.timestamp,
347
+ lastTransitionAt: messageEvent.timestamp,
348
+ lastTransitionReason: "waiting",
349
+ deadlineAt: run.deadlineAt,
350
+ retryAt: run.retryAt,
351
+ error: void 0,
352
+ output: void 0,
353
+ finishedAt: void 0
354
+ });
355
+ }
356
+ //#endregion
357
+ export { broadcastWorkflowMessageInput, createWorkflowStepMessageApi, messageWaitAvailableAt, requireMessageWaitReplayMatches, sendWorkflowMessage, sendWorkflowMessageInput, waitForWorkflowMessage, wakeRunForMessageEvent };
@@ -0,0 +1,4 @@
1
+ import { CreateWorkflowEngineOptions, WorkflowDeterministicBytesContext, WorkflowDeterministicValueContext, WorkflowEngineSerializationLimits, WorkflowExecutionLimits, WorkflowRecordedIdContext } from "../types/engine-options.mjs";
2
+ import { LockManager, WorkflowAdmin, WorkflowCleanupAdmin, WorkflowClientEngine, WorkflowEngineLike, WorkflowExecutionEnvironment, WorkflowExecutionEnvironmentStore, WorkflowExecutor, WorkflowHookManager, WorkflowMessageIdempotencyMaintenance, WorkflowMessageSender, WorkflowRunCanceler, WorkflowRunHandleReader, WorkflowRunMaintenance, WorkflowRunReader, WorkflowRunRerunner, WorkflowRunStarter, WorkflowScheduleRunObserver, WorkflowScheduler, WorkflowStarter, WorkflowStepAttemptLookupReader, WorkflowStepAttemptMaintenance, WorkflowStepAttemptReader, WorkflowStreamReader, WorkflowWorkerEngine, WorkflowWorkerEngineStore, WorkflowWorkerOperationObserver } from "../types/engine.mjs";
3
+ import { WorkflowEngine, createWorkflowEngine } from "./create.mjs";
4
+ export { type CreateWorkflowEngineOptions, type LockManager, type WorkflowAdmin, type WorkflowCleanupAdmin, type WorkflowClientEngine, type WorkflowDeterministicBytesContext, type WorkflowDeterministicValueContext, WorkflowEngine, type WorkflowEngineLike, type WorkflowEngineSerializationLimits, type WorkflowExecutionEnvironment, type WorkflowExecutionEnvironmentStore, type WorkflowExecutionLimits, type WorkflowExecutor, type WorkflowHookManager, type WorkflowMessageIdempotencyMaintenance, type WorkflowMessageSender, type WorkflowRecordedIdContext, type WorkflowRunCanceler, type WorkflowRunHandleReader, type WorkflowRunMaintenance, type WorkflowRunReader, type WorkflowRunRerunner, type WorkflowRunStarter, type WorkflowScheduleRunObserver, type WorkflowScheduler, type WorkflowStarter, type WorkflowStepAttemptLookupReader, type WorkflowStepAttemptMaintenance, type WorkflowStepAttemptReader, type WorkflowStreamReader, type WorkflowWorkerEngine, type WorkflowWorkerEngineStore, type WorkflowWorkerOperationObserver, createWorkflowEngine };
@@ -0,0 +1,2 @@
1
+ import { WorkflowEngine, createWorkflowEngine } from "./create.mjs";
2
+ export { WorkflowEngine, createWorkflowEngine };
@@ -0,0 +1,35 @@
1
+ import { MessageId } from "../types/message-id.mjs";
2
+ import { RunId } from "../types/run-id.mjs";
3
+ import { CleanupRunsResult } from "../types/cleanup.mjs";
4
+ import { ChildWorkflowStartedObservationEvent, ObservationEmitter as ObservationEmitter$1, ObservationEventHandler, ObservationEventPattern, ScheduleRunCreatedObservationEvent, ScheduleTickObservationEvent, WorkerOperationObservationEvent } from "../types/observation.mjs";
5
+ import { Telemetry, TelemetryContext } from "../types/telemetry.mjs";
6
+ import { WorkflowRunRecord } from "../types/run.mjs";
7
+ import { EventRecord, MessageSentEvent } from "../types/events.mjs";
8
+ import { StorageValue } from "@temelj/storage";
9
+ //#region src/engine/observation.d.ts
10
+ declare function createObservationEmitter(telemetry?: Telemetry): ObservationEmitter$1;
11
+ declare class ObservationEmitter implements ObservationEmitter$1 {
12
+ #private;
13
+ constructor(telemetry?: Telemetry);
14
+ on<Pattern extends ObservationEventPattern>(pattern: Pattern, handler: ObservationEventHandler<Pattern>): () => void;
15
+ once<Pattern extends ObservationEventPattern>(pattern: Pattern, handler: ObservationEventHandler<Pattern>): () => void;
16
+ off<Pattern extends ObservationEventPattern>(pattern: Pattern, handler: ObservationEventHandler<Pattern>): void;
17
+ clearListeners(pattern?: ObservationEventPattern): void;
18
+ listenerCount(pattern?: ObservationEventPattern): number;
19
+ listeners(): readonly ObservationEventHandler[];
20
+ listeners<Pattern extends ObservationEventPattern>(pattern: Pattern): readonly ObservationEventHandler<Pattern>[];
21
+ emitRunEvent(run: WorkflowRunRecord, previousRun?: WorkflowRunRecord): void;
22
+ emitRunMetadataUpdated(run: WorkflowRunRecord, previousRun?: WorkflowRunRecord): void;
23
+ emitDurableEventAppended(runId: RunId, event: EventRecord, appendedEvents: readonly EventRecord[]): void;
24
+ emitMessageSent(runId: RunId, event: MessageSentEvent): void;
25
+ emitHookResumed(runId: RunId, messageId: MessageId, payload: StorageValue | undefined, traceContext: TelemetryContext | undefined): void;
26
+ emitWebhookResumed(runId: RunId, messageId: MessageId, payload: StorageValue | undefined, traceContext: TelemetryContext | undefined): void;
27
+ emitChildWorkflowStarted(event: ChildWorkflowStartedObservationEvent): void;
28
+ emitCleanupCompleted(result: CleanupRunsResult): void;
29
+ emitRetentionApplied(result: CleanupRunsResult): void;
30
+ emitWorkerOperation(event: WorkerOperationObservationEvent): void;
31
+ emitScheduleTicked(event: ScheduleTickObservationEvent): void;
32
+ emitScheduleRunCreated(event: ScheduleRunCreatedObservationEvent): void;
33
+ }
34
+ //#endregion
35
+ export { ObservationEmitter, createObservationEmitter };