@auto-engineer/pipeline 0.14.0 → 0.16.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 (316) hide show
  1. package/.turbo/turbo-build.log +5 -6
  2. package/CHANGELOG.md +24 -0
  3. package/README.md +279 -0
  4. package/dist/src/builder/define.d.ts +6 -2
  5. package/dist/src/builder/define.d.ts.map +1 -1
  6. package/dist/src/builder/define.js +17 -7
  7. package/dist/src/builder/define.js.map +1 -1
  8. package/dist/src/core/descriptors.d.ts +6 -2
  9. package/dist/src/core/descriptors.d.ts.map +1 -1
  10. package/dist/src/graph/filter-graph.d.ts +3 -0
  11. package/dist/src/graph/filter-graph.d.ts.map +1 -0
  12. package/dist/src/graph/filter-graph.js +80 -0
  13. package/dist/src/graph/filter-graph.js.map +1 -0
  14. package/dist/src/graph/types.d.ts +8 -0
  15. package/dist/src/graph/types.d.ts.map +1 -1
  16. package/dist/src/index.d.ts +1 -0
  17. package/dist/src/index.d.ts.map +1 -1
  18. package/dist/src/index.js.map +1 -1
  19. package/dist/src/projections/await-tracker-projection.d.ts +31 -0
  20. package/dist/src/projections/await-tracker-projection.d.ts.map +1 -0
  21. package/dist/src/projections/await-tracker-projection.js +35 -0
  22. package/dist/src/projections/await-tracker-projection.js.map +1 -0
  23. package/dist/src/projections/index.d.ts +4 -0
  24. package/dist/src/projections/index.d.ts.map +1 -0
  25. package/dist/src/projections/index.js +4 -0
  26. package/dist/src/projections/index.js.map +1 -0
  27. package/dist/src/projections/item-status-projection.d.ts +22 -0
  28. package/dist/src/projections/item-status-projection.d.ts.map +1 -0
  29. package/dist/src/projections/item-status-projection.js +11 -0
  30. package/dist/src/projections/item-status-projection.js.map +1 -0
  31. package/dist/src/projections/latest-run-projection.d.ts +15 -0
  32. package/dist/src/projections/latest-run-projection.d.ts.map +1 -0
  33. package/dist/src/projections/latest-run-projection.js +7 -0
  34. package/dist/src/projections/latest-run-projection.js.map +1 -0
  35. package/dist/src/projections/message-log-projection.d.ts +51 -0
  36. package/dist/src/projections/message-log-projection.d.ts.map +1 -0
  37. package/dist/src/projections/message-log-projection.js +51 -0
  38. package/dist/src/projections/message-log-projection.js.map +1 -0
  39. package/dist/src/projections/node-status-projection.d.ts +23 -0
  40. package/dist/src/projections/node-status-projection.d.ts.map +1 -0
  41. package/dist/src/projections/node-status-projection.js +10 -0
  42. package/dist/src/projections/node-status-projection.js.map +1 -0
  43. package/dist/src/projections/phased-execution-projection.d.ts +77 -0
  44. package/dist/src/projections/phased-execution-projection.d.ts.map +1 -0
  45. package/dist/src/projections/phased-execution-projection.js +54 -0
  46. package/dist/src/projections/phased-execution-projection.js.map +1 -0
  47. package/dist/src/projections/settled-instance-projection.d.ts +67 -0
  48. package/dist/src/projections/settled-instance-projection.d.ts.map +1 -0
  49. package/dist/src/projections/settled-instance-projection.js +66 -0
  50. package/dist/src/projections/settled-instance-projection.js.map +1 -0
  51. package/dist/src/projections/stats-projection.d.ts +9 -0
  52. package/dist/src/projections/stats-projection.d.ts.map +1 -0
  53. package/dist/src/projections/stats-projection.js +16 -0
  54. package/dist/src/projections/stats-projection.js.map +1 -0
  55. package/dist/src/runtime/await-tracker.d.ts +17 -7
  56. package/dist/src/runtime/await-tracker.d.ts.map +1 -1
  57. package/dist/src/runtime/await-tracker.js +32 -29
  58. package/dist/src/runtime/await-tracker.js.map +1 -1
  59. package/dist/src/runtime/context.d.ts +1 -1
  60. package/dist/src/runtime/context.d.ts.map +1 -1
  61. package/dist/src/runtime/event-command-map.d.ts +3 -3
  62. package/dist/src/runtime/event-command-map.d.ts.map +1 -1
  63. package/dist/src/runtime/event-command-map.js +6 -2
  64. package/dist/src/runtime/event-command-map.js.map +1 -1
  65. package/dist/src/runtime/phased-executor.d.ts +14 -9
  66. package/dist/src/runtime/phased-executor.d.ts.map +1 -1
  67. package/dist/src/runtime/phased-executor.js +113 -105
  68. package/dist/src/runtime/phased-executor.js.map +1 -1
  69. package/dist/src/runtime/pipeline-runtime.d.ts.map +1 -1
  70. package/dist/src/runtime/pipeline-runtime.js +2 -2
  71. package/dist/src/runtime/pipeline-runtime.js.map +1 -1
  72. package/dist/src/runtime/settled-tracker.d.ts +12 -10
  73. package/dist/src/runtime/settled-tracker.d.ts.map +1 -1
  74. package/dist/src/runtime/settled-tracker.js +89 -80
  75. package/dist/src/runtime/settled-tracker.js.map +1 -1
  76. package/dist/src/server/pipeline-server.d.ts +31 -9
  77. package/dist/src/server/pipeline-server.d.ts.map +1 -1
  78. package/dist/src/server/pipeline-server.js +424 -123
  79. package/dist/src/server/pipeline-server.js.map +1 -1
  80. package/dist/src/server/sse-manager.d.ts +0 -1
  81. package/dist/src/server/sse-manager.d.ts.map +1 -1
  82. package/dist/src/server/sse-manager.js +0 -3
  83. package/dist/src/server/sse-manager.js.map +1 -1
  84. package/dist/src/store/index.d.ts +3 -0
  85. package/dist/src/store/index.d.ts.map +1 -0
  86. package/dist/src/store/index.js +3 -0
  87. package/dist/src/store/index.js.map +1 -0
  88. package/dist/src/store/pipeline-event-store.d.ts +10 -0
  89. package/dist/src/store/pipeline-event-store.d.ts.map +1 -0
  90. package/dist/src/store/pipeline-event-store.js +112 -0
  91. package/dist/src/store/pipeline-event-store.js.map +1 -0
  92. package/dist/src/store/pipeline-read-model.d.ts +49 -0
  93. package/dist/src/store/pipeline-read-model.d.ts.map +1 -0
  94. package/dist/src/store/pipeline-read-model.js +156 -0
  95. package/dist/src/store/pipeline-read-model.js.map +1 -0
  96. package/dist/src/store/sqlite-pipeline-event-store.d.ts +14 -0
  97. package/dist/src/store/sqlite-pipeline-event-store.d.ts.map +1 -0
  98. package/dist/src/store/sqlite-pipeline-event-store.js +20 -0
  99. package/dist/src/store/sqlite-pipeline-event-store.js.map +1 -0
  100. package/dist/src/testing/fixtures/kanban-full.pipeline.js +2 -2
  101. package/dist/src/testing/fixtures/kanban-full.pipeline.js.map +1 -1
  102. package/dist/src/testing/fixtures/kanban.pipeline.js +2 -2
  103. package/dist/src/testing/fixtures/kanban.pipeline.js.map +1 -1
  104. package/dist/tsconfig.tsbuildinfo +1 -1
  105. package/ketchup-plan.md +1216 -0
  106. package/package.json +6 -4
  107. package/src/builder/define.specs.ts +5 -4
  108. package/src/builder/define.ts +24 -11
  109. package/src/config/pipeline-config.specs.ts +32 -0
  110. package/src/core/descriptors.ts +7 -2
  111. package/src/graph/filter-graph.specs.ts +267 -0
  112. package/src/graph/filter-graph.ts +111 -0
  113. package/src/graph/types.specs.ts +0 -14
  114. package/src/graph/types.ts +10 -0
  115. package/src/index.ts +1 -0
  116. package/src/projections/await-tracker-projection.specs.ts +24 -0
  117. package/src/projections/await-tracker-projection.ts +68 -0
  118. package/src/projections/index.ts +11 -0
  119. package/src/projections/item-status-projection.specs.ts +130 -0
  120. package/src/projections/item-status-projection.ts +32 -0
  121. package/src/projections/latest-run-projection.ts +20 -0
  122. package/src/projections/message-log-projection.ts +113 -0
  123. package/src/projections/node-status-projection.ts +33 -0
  124. package/src/projections/phased-execution-projection.specs.ts +202 -0
  125. package/src/projections/phased-execution-projection.ts +146 -0
  126. package/src/projections/settled-instance-projection.specs.ts +296 -0
  127. package/src/projections/settled-instance-projection.ts +160 -0
  128. package/src/projections/stats-projection.ts +26 -0
  129. package/src/runtime/await-tracker.specs.ts +57 -34
  130. package/src/runtime/await-tracker.ts +43 -31
  131. package/src/runtime/context.ts +1 -1
  132. package/src/runtime/event-command-map.ts +11 -4
  133. package/src/runtime/phased-executor.specs.ts +357 -81
  134. package/src/runtime/phased-executor.ts +134 -128
  135. package/src/runtime/pipeline-runtime.specs.ts +65 -0
  136. package/src/runtime/pipeline-runtime.ts +6 -4
  137. package/src/runtime/settled-tracker.specs.ts +716 -120
  138. package/src/runtime/settled-tracker.ts +100 -102
  139. package/src/server/pipeline-server.e2e.specs.ts +10 -16
  140. package/src/server/pipeline-server.specs.ts +1441 -211
  141. package/src/server/pipeline-server.ts +535 -144
  142. package/src/server/sse-manager.specs.ts +67 -36
  143. package/src/server/sse-manager.ts +0 -4
  144. package/src/store/index.ts +2 -0
  145. package/src/store/pipeline-event-store.specs.ts +357 -0
  146. package/src/store/pipeline-event-store.ts +156 -0
  147. package/src/store/pipeline-read-model.specs.ts +1170 -0
  148. package/src/store/pipeline-read-model.ts +223 -0
  149. package/src/store/sqlite-pipeline-event-store.specs.ts +13 -0
  150. package/src/store/sqlite-pipeline-event-store.ts +36 -0
  151. package/src/testing/fixtures/kanban-full.pipeline.ts +2 -2
  152. package/src/testing/fixtures/kanban.pipeline.ts +2 -2
  153. package/tsconfig.json +1 -1
  154. package/vitest.config.ts +1 -8
  155. package/claude.md +0 -160
  156. package/dist/src/__tests__/e2e/helpers.d.ts +0 -48
  157. package/dist/src/__tests__/e2e/helpers.d.ts.map +0 -1
  158. package/dist/src/__tests__/e2e/helpers.js +0 -253
  159. package/dist/src/__tests__/e2e/helpers.js.map +0 -1
  160. package/dist/src/__tests__/e2e/kanban-migration.e2e.specs.d.ts +0 -2
  161. package/dist/src/__tests__/e2e/kanban-migration.e2e.specs.d.ts.map +0 -1
  162. package/dist/src/__tests__/e2e/kanban-migration.e2e.specs.js +0 -195
  163. package/dist/src/__tests__/e2e/kanban-migration.e2e.specs.js.map +0 -1
  164. package/dist/src/__tests__/e2e/types.d.ts +0 -107
  165. package/dist/src/__tests__/e2e/types.d.ts.map +0 -1
  166. package/dist/src/__tests__/e2e/types.js +0 -2
  167. package/dist/src/__tests__/e2e/types.js.map +0 -1
  168. package/dist/src/builder/define.specs.d.ts +0 -2
  169. package/dist/src/builder/define.specs.d.ts.map +0 -1
  170. package/dist/src/builder/define.specs.js +0 -435
  171. package/dist/src/builder/define.specs.js.map +0 -1
  172. package/dist/src/core/descriptors.specs.d.ts +0 -2
  173. package/dist/src/core/descriptors.specs.d.ts.map +0 -1
  174. package/dist/src/core/descriptors.specs.js +0 -24
  175. package/dist/src/core/descriptors.specs.js.map +0 -1
  176. package/dist/src/core/types.specs.d.ts +0 -2
  177. package/dist/src/core/types.specs.d.ts.map +0 -1
  178. package/dist/src/core/types.specs.js +0 -40
  179. package/dist/src/core/types.specs.js.map +0 -1
  180. package/dist/src/file-syncer/crypto/jwe-encryptor.d.ts +0 -15
  181. package/dist/src/file-syncer/crypto/jwe-encryptor.d.ts.map +0 -1
  182. package/dist/src/file-syncer/crypto/jwe-encryptor.js +0 -64
  183. package/dist/src/file-syncer/crypto/jwe-encryptor.js.map +0 -1
  184. package/dist/src/file-syncer/crypto/provider-resolver.d.ts +0 -24
  185. package/dist/src/file-syncer/crypto/provider-resolver.d.ts.map +0 -1
  186. package/dist/src/file-syncer/crypto/provider-resolver.js +0 -71
  187. package/dist/src/file-syncer/crypto/provider-resolver.js.map +0 -1
  188. package/dist/src/file-syncer/discovery/bareImports.d.ts +0 -3
  189. package/dist/src/file-syncer/discovery/bareImports.d.ts.map +0 -1
  190. package/dist/src/file-syncer/discovery/bareImports.js +0 -36
  191. package/dist/src/file-syncer/discovery/bareImports.js.map +0 -1
  192. package/dist/src/file-syncer/discovery/dts.d.ts +0 -8
  193. package/dist/src/file-syncer/discovery/dts.d.ts.map +0 -1
  194. package/dist/src/file-syncer/discovery/dts.js +0 -99
  195. package/dist/src/file-syncer/discovery/dts.js.map +0 -1
  196. package/dist/src/file-syncer/index.d.ts +0 -46
  197. package/dist/src/file-syncer/index.d.ts.map +0 -1
  198. package/dist/src/file-syncer/index.js +0 -392
  199. package/dist/src/file-syncer/index.js.map +0 -1
  200. package/dist/src/file-syncer/sync/resolveSyncFileSet.d.ts +0 -7
  201. package/dist/src/file-syncer/sync/resolveSyncFileSet.d.ts.map +0 -1
  202. package/dist/src/file-syncer/sync/resolveSyncFileSet.js +0 -86
  203. package/dist/src/file-syncer/sync/resolveSyncFileSet.js.map +0 -1
  204. package/dist/src/file-syncer/types/wire.d.ts +0 -14
  205. package/dist/src/file-syncer/types/wire.d.ts.map +0 -1
  206. package/dist/src/file-syncer/types/wire.js +0 -2
  207. package/dist/src/file-syncer/types/wire.js.map +0 -1
  208. package/dist/src/file-syncer/utils/hash.d.ts +0 -5
  209. package/dist/src/file-syncer/utils/hash.d.ts.map +0 -1
  210. package/dist/src/file-syncer/utils/hash.js +0 -19
  211. package/dist/src/file-syncer/utils/hash.js.map +0 -1
  212. package/dist/src/file-syncer/utils/path.d.ts +0 -13
  213. package/dist/src/file-syncer/utils/path.d.ts.map +0 -1
  214. package/dist/src/file-syncer/utils/path.js +0 -74
  215. package/dist/src/file-syncer/utils/path.js.map +0 -1
  216. package/dist/src/graph/types.specs.d.ts +0 -2
  217. package/dist/src/graph/types.specs.d.ts.map +0 -1
  218. package/dist/src/graph/types.specs.js +0 -148
  219. package/dist/src/graph/types.specs.js.map +0 -1
  220. package/dist/src/logging/event-logger.specs.d.ts +0 -2
  221. package/dist/src/logging/event-logger.specs.d.ts.map +0 -1
  222. package/dist/src/logging/event-logger.specs.js +0 -81
  223. package/dist/src/logging/event-logger.specs.js.map +0 -1
  224. package/dist/src/plugins/handler-adapter.specs.d.ts +0 -2
  225. package/dist/src/plugins/handler-adapter.specs.d.ts.map +0 -1
  226. package/dist/src/plugins/handler-adapter.specs.js +0 -129
  227. package/dist/src/plugins/handler-adapter.specs.js.map +0 -1
  228. package/dist/src/plugins/plugin-loader.specs.d.ts +0 -2
  229. package/dist/src/plugins/plugin-loader.specs.d.ts.map +0 -1
  230. package/dist/src/plugins/plugin-loader.specs.js +0 -246
  231. package/dist/src/plugins/plugin-loader.specs.js.map +0 -1
  232. package/dist/src/runtime/await-tracker.specs.d.ts +0 -2
  233. package/dist/src/runtime/await-tracker.specs.d.ts.map +0 -1
  234. package/dist/src/runtime/await-tracker.specs.js +0 -46
  235. package/dist/src/runtime/await-tracker.specs.js.map +0 -1
  236. package/dist/src/runtime/context.specs.d.ts +0 -2
  237. package/dist/src/runtime/context.specs.d.ts.map +0 -1
  238. package/dist/src/runtime/context.specs.js +0 -26
  239. package/dist/src/runtime/context.specs.js.map +0 -1
  240. package/dist/src/runtime/event-command-map.specs.d.ts +0 -2
  241. package/dist/src/runtime/event-command-map.specs.d.ts.map +0 -1
  242. package/dist/src/runtime/event-command-map.specs.js +0 -108
  243. package/dist/src/runtime/event-command-map.specs.js.map +0 -1
  244. package/dist/src/runtime/phased-executor.specs.d.ts +0 -2
  245. package/dist/src/runtime/phased-executor.specs.d.ts.map +0 -1
  246. package/dist/src/runtime/phased-executor.specs.js +0 -256
  247. package/dist/src/runtime/phased-executor.specs.js.map +0 -1
  248. package/dist/src/runtime/pipeline-runtime.specs.d.ts +0 -2
  249. package/dist/src/runtime/pipeline-runtime.specs.d.ts.map +0 -1
  250. package/dist/src/runtime/pipeline-runtime.specs.js +0 -192
  251. package/dist/src/runtime/pipeline-runtime.specs.js.map +0 -1
  252. package/dist/src/runtime/settled-tracker.specs.d.ts +0 -2
  253. package/dist/src/runtime/settled-tracker.specs.d.ts.map +0 -1
  254. package/dist/src/runtime/settled-tracker.specs.js +0 -361
  255. package/dist/src/runtime/settled-tracker.specs.js.map +0 -1
  256. package/dist/src/server/full-orchestration.e2e.specs.d.ts +0 -2
  257. package/dist/src/server/full-orchestration.e2e.specs.d.ts.map +0 -1
  258. package/dist/src/server/full-orchestration.e2e.specs.js +0 -561
  259. package/dist/src/server/full-orchestration.e2e.specs.js.map +0 -1
  260. package/dist/src/server/pipeline-server.e2e.specs.d.ts +0 -2
  261. package/dist/src/server/pipeline-server.e2e.specs.d.ts.map +0 -1
  262. package/dist/src/server/pipeline-server.e2e.specs.js +0 -381
  263. package/dist/src/server/pipeline-server.e2e.specs.js.map +0 -1
  264. package/dist/src/server/pipeline-server.specs.d.ts +0 -2
  265. package/dist/src/server/pipeline-server.specs.d.ts.map +0 -1
  266. package/dist/src/server/pipeline-server.specs.js +0 -662
  267. package/dist/src/server/pipeline-server.specs.js.map +0 -1
  268. package/dist/src/server/sse-manager.specs.d.ts +0 -2
  269. package/dist/src/server/sse-manager.specs.d.ts.map +0 -1
  270. package/dist/src/server/sse-manager.specs.js +0 -158
  271. package/dist/src/server/sse-manager.specs.js.map +0 -1
  272. package/dist/src/testing/event-capture.specs.d.ts +0 -2
  273. package/dist/src/testing/event-capture.specs.d.ts.map +0 -1
  274. package/dist/src/testing/event-capture.specs.js +0 -114
  275. package/dist/src/testing/event-capture.specs.js.map +0 -1
  276. package/dist/src/testing/fixtures/kanban-full.pipeline.specs.d.ts +0 -2
  277. package/dist/src/testing/fixtures/kanban-full.pipeline.specs.d.ts.map +0 -1
  278. package/dist/src/testing/fixtures/kanban-full.pipeline.specs.js +0 -263
  279. package/dist/src/testing/fixtures/kanban-full.pipeline.specs.js.map +0 -1
  280. package/dist/src/testing/fixtures/kanban.pipeline.specs.d.ts +0 -2
  281. package/dist/src/testing/fixtures/kanban.pipeline.specs.d.ts.map +0 -1
  282. package/dist/src/testing/fixtures/kanban.pipeline.specs.js +0 -29
  283. package/dist/src/testing/fixtures/kanban.pipeline.specs.js.map +0 -1
  284. package/dist/src/testing/kanban-todo.e2e.specs.d.ts +0 -2
  285. package/dist/src/testing/kanban-todo.e2e.specs.d.ts.map +0 -1
  286. package/dist/src/testing/kanban-todo.e2e.specs.js +0 -160
  287. package/dist/src/testing/kanban-todo.e2e.specs.js.map +0 -1
  288. package/dist/src/testing/mock-handlers.specs.d.ts +0 -2
  289. package/dist/src/testing/mock-handlers.specs.d.ts.map +0 -1
  290. package/dist/src/testing/mock-handlers.specs.js +0 -193
  291. package/dist/src/testing/mock-handlers.specs.js.map +0 -1
  292. package/dist/src/testing/real-execution.e2e.specs.d.ts +0 -2
  293. package/dist/src/testing/real-execution.e2e.specs.d.ts.map +0 -1
  294. package/dist/src/testing/real-execution.e2e.specs.js +0 -140
  295. package/dist/src/testing/real-execution.e2e.specs.js.map +0 -1
  296. package/dist/src/testing/real-plugin.e2e.specs.d.ts +0 -2
  297. package/dist/src/testing/real-plugin.e2e.specs.d.ts.map +0 -1
  298. package/dist/src/testing/real-plugin.e2e.specs.js +0 -65
  299. package/dist/src/testing/real-plugin.e2e.specs.js.map +0 -1
  300. package/dist/src/testing/server-startup.e2e.specs.d.ts +0 -2
  301. package/dist/src/testing/server-startup.e2e.specs.d.ts.map +0 -1
  302. package/dist/src/testing/server-startup.e2e.specs.js +0 -104
  303. package/dist/src/testing/server-startup.e2e.specs.js.map +0 -1
  304. package/dist/src/testing/snapshot-compare.specs.d.ts +0 -2
  305. package/dist/src/testing/snapshot-compare.specs.d.ts.map +0 -1
  306. package/dist/src/testing/snapshot-compare.specs.js +0 -112
  307. package/dist/src/testing/snapshot-compare.specs.js.map +0 -1
  308. package/dist/src/testing/snapshot-sanitize.specs.d.ts +0 -2
  309. package/dist/src/testing/snapshot-sanitize.specs.d.ts.map +0 -1
  310. package/dist/src/testing/snapshot-sanitize.specs.js +0 -104
  311. package/dist/src/testing/snapshot-sanitize.specs.js.map +0 -1
  312. package/docs/testing-analysis.md +0 -395
  313. package/pomodoro-plan.md +0 -651
  314. package/src/core/descriptors.specs.ts +0 -28
  315. package/src/core/types.specs.ts +0 -44
  316. package/src/runtime/context.specs.ts +0 -28
@@ -1,4 +1,6 @@
1
1
  import type { Command, Event } from '@auto-engineer/message-bus';
2
+ import type { SettledEvent, SettledInstanceDocument } from '../projections/settled-instance-projection';
3
+ import type { PipelineReadModel } from '../store/pipeline-read-model';
2
4
 
3
5
  type SendFunction = (commandType: string, data: unknown) => void;
4
6
 
@@ -9,45 +11,36 @@ interface SettledHandlerRegistration {
9
11
  handler: SettledHandler;
10
12
  }
11
13
 
12
- interface CommandTracker {
13
- commandType: string;
14
- hasStarted: boolean;
15
- hasCompleted: boolean;
16
- events: Event[];
17
- }
18
-
19
14
  interface HandlerTemplate {
20
15
  id: string;
21
16
  registration: SettledHandlerRegistration;
22
17
  }
23
18
 
24
- interface HandlerInstance {
25
- templateId: string;
26
- correlationId: string;
27
- registration: SettledHandlerRegistration;
28
- commandTrackers: Map<string, CommandTracker>;
29
- }
30
-
31
19
  interface SettledErrorContext {
32
20
  commandTypes: readonly string[];
33
21
  correlationId: string;
34
22
  }
35
23
 
36
24
  interface SettledTrackerOptions {
25
+ readModel: PipelineReadModel;
37
26
  onDispatch?: (commandType: string, data: unknown, correlationId: string) => void;
38
27
  onError?: (error: unknown, context: SettledErrorContext) => void;
28
+ onEventEmit?: (event: SettledEvent) => void | Promise<void>;
39
29
  }
40
30
 
41
31
  export class SettledTracker {
42
32
  private handlerTemplates = new Map<string, HandlerTemplate>();
43
- private handlerInstances = new Map<string, HandlerInstance>();
44
33
  private commandToTemplateIds = new Map<string, Set<string>>();
34
+ private readonly readModel: PipelineReadModel;
45
35
  private readonly onDispatch?: (commandType: string, data: unknown, correlationId: string) => void;
46
36
  private readonly onError?: (error: unknown, context: SettledErrorContext) => void;
37
+ private readonly onEventEmit?: (event: SettledEvent) => void | Promise<void>;
47
38
 
48
- constructor(options?: SettledTrackerOptions) {
49
- this.onDispatch = options?.onDispatch;
50
- this.onError = options?.onError;
39
+ constructor(options: SettledTrackerOptions) {
40
+ this.readModel = options.readModel;
41
+ this.onDispatch = options.onDispatch;
42
+ this.onError = options.onError;
43
+ this.onEventEmit = options.onEventEmit;
51
44
  }
52
45
 
53
46
  registerHandler(registration: SettledHandlerRegistration): void {
@@ -65,15 +58,7 @@ export class SettledTracker {
65
58
  }
66
59
  }
67
60
 
68
- getRegisteredHandlerCount(): number {
69
- return this.handlerTemplates.size;
70
- }
71
-
72
- getActiveInstanceCount(): number {
73
- return this.handlerInstances.size;
74
- }
75
-
76
- onCommandStarted(command: Command): void {
61
+ async onCommandStarted(command: Command): Promise<void> {
77
62
  const { type: commandType, correlationId, requestId } = command;
78
63
 
79
64
  if (!this.isValidId(correlationId) || !this.isValidId(requestId)) {
@@ -88,41 +73,49 @@ export class SettledTracker {
88
73
  for (const templateId of templateIds) {
89
74
  const template = this.handlerTemplates.get(templateId);
90
75
  if (template) {
91
- this.ensureInstanceExists(template, correlationId);
92
- this.markCommandStarted(template.id, correlationId, commandType);
76
+ await this.ensureInstanceExists(template, correlationId);
77
+ await this.markCommandStarted(template.id, correlationId, commandType);
93
78
  }
94
79
  }
95
80
  }
96
81
 
97
- isWaitingFor(correlationId: string, commandType: string): boolean {
98
- for (const instance of this.handlerInstances.values()) {
99
- if (instance.correlationId === correlationId) {
100
- const tracker = instance.commandTrackers.get(commandType);
101
- if (tracker?.hasStarted === true && tracker.hasCompleted === false) {
102
- return true;
103
- }
82
+ async isWaitingForAsync(correlationId: string, commandType: string): Promise<boolean> {
83
+ const instances = await this.readModel.getActiveSettledInstances(correlationId);
84
+ for (const instance of instances) {
85
+ const tracker = instance.commandTrackers.find((t) => t.commandType === commandType);
86
+ if (tracker?.hasStarted === true && tracker.hasCompleted === false) {
87
+ return true;
104
88
  }
105
89
  }
106
90
  return false;
107
91
  }
108
92
 
109
- onEventReceived(event: Event, sourceCommandType: string): void {
93
+ async onEventReceived(event: Event, sourceCommandType: string): Promise<void> {
110
94
  const correlationId = event.correlationId;
111
95
 
112
96
  if (!this.isValidId(correlationId)) {
113
97
  return;
114
98
  }
115
99
 
116
- for (const [instanceId, instance] of this.handlerInstances) {
117
- if (instance.correlationId !== correlationId) {
118
- continue;
119
- }
100
+ const instances = await this.readModel.getActiveSettledInstances(correlationId);
120
101
 
121
- const tracker = instance.commandTrackers.get(sourceCommandType);
102
+ for (const instanceDoc of instances) {
103
+ const tracker = instanceDoc.commandTrackers.find((t) => t.commandType === sourceCommandType);
122
104
  if (tracker && !tracker.hasCompleted) {
123
- tracker.events.push(event);
124
- tracker.hasCompleted = true;
125
- this.checkAndFireHandler(instanceId, instance);
105
+ await this.emitEvent({
106
+ type: 'SettledEventReceived',
107
+ data: {
108
+ templateId: instanceDoc.templateId,
109
+ correlationId,
110
+ commandType: sourceCommandType,
111
+ event,
112
+ },
113
+ });
114
+
115
+ const updatedInstance = await this.readModel.getSettledInstance(instanceDoc.templateId, correlationId);
116
+ if (updatedInstance) {
117
+ await this.checkAndFireHandler(updatedInstance);
118
+ }
126
119
  }
127
120
  }
128
121
  }
@@ -135,84 +128,97 @@ export class SettledTracker {
135
128
  return `template-${registration.commandTypes.join(',')}`;
136
129
  }
137
130
 
138
- private generateInstanceId(templateId: string, correlationId: string): string {
139
- return `${templateId}-${correlationId}`;
140
- }
141
-
142
- private ensureInstanceExists(template: HandlerTemplate, correlationId: string): void {
143
- const instanceId = this.generateInstanceId(template.id, correlationId);
144
-
145
- if (this.handlerInstances.has(instanceId)) {
146
- return;
147
- }
131
+ private async ensureInstanceExists(template: HandlerTemplate, correlationId: string): Promise<boolean> {
132
+ const existing = await this.readModel.getSettledInstance(template.id, correlationId);
133
+ const isActiveInstance = existing !== null && existing.status === 'active';
148
134
 
149
- const commandTrackers = new Map<string, CommandTracker>();
150
- for (const commandType of template.registration.commandTypes) {
151
- commandTrackers.set(commandType, {
152
- commandType,
153
- hasStarted: false,
154
- hasCompleted: false,
155
- events: [],
156
- });
135
+ if (isActiveInstance) {
136
+ return false;
157
137
  }
158
138
 
159
- this.handlerInstances.set(instanceId, {
160
- templateId: template.id,
161
- correlationId,
162
- registration: template.registration,
163
- commandTrackers,
139
+ await this.emitEvent({
140
+ type: 'SettledInstanceCreated',
141
+ data: {
142
+ templateId: template.id,
143
+ correlationId,
144
+ commandTypes: template.registration.commandTypes,
145
+ },
164
146
  });
147
+
148
+ return true;
165
149
  }
166
150
 
167
- private markCommandStarted(templateId: string, correlationId: string, commandType: string): void {
168
- const instanceId = this.generateInstanceId(templateId, correlationId);
169
- const instance = this.handlerInstances.get(instanceId);
151
+ private async markCommandStarted(templateId: string, correlationId: string, commandType: string): Promise<void> {
152
+ await this.emitEvent({
153
+ type: 'SettledCommandStarted',
154
+ data: {
155
+ templateId,
156
+ correlationId,
157
+ commandType,
158
+ },
159
+ });
160
+ }
170
161
 
171
- const tracker = instance?.commandTrackers.get(commandType);
172
- if (tracker) {
173
- tracker.hasStarted = true;
174
- tracker.hasCompleted = false;
175
- }
162
+ private async emitEvent(event: SettledEvent): Promise<void> {
163
+ await this.onEventEmit?.(event);
176
164
  }
177
165
 
178
- private checkAndFireHandler(instanceId: string, instance: HandlerInstance): void {
179
- const allComplete = Array.from(instance.commandTrackers.values()).every(
180
- (tracker) => tracker.hasStarted && tracker.hasCompleted,
181
- );
166
+ private async checkAndFireHandler(instanceDoc: SettledInstanceDocument): Promise<void> {
167
+ const allComplete = instanceDoc.commandTrackers.every((tracker) => tracker.hasStarted && tracker.hasCompleted);
182
168
 
183
169
  if (!allComplete) {
184
170
  return;
185
171
  }
186
172
 
187
- const eventsByCommandType = this.collectEvents(instance);
173
+ const template = this.handlerTemplates.get(instanceDoc.templateId)!;
174
+ const eventsByCommandType = this.collectEventsFromDoc(instanceDoc);
188
175
 
189
176
  try {
190
177
  const send: SendFunction = (commandType, data) => {
191
178
  if (this.onDispatch) {
192
- this.onDispatch(commandType, data, instance.correlationId);
179
+ this.onDispatch(commandType, data, instanceDoc.correlationId);
193
180
  }
194
181
  };
195
182
 
196
- const result = instance.registration.handler(eventsByCommandType, send);
183
+ const result = template.registration.handler(eventsByCommandType, send);
184
+ const persist = this.shouldPersist(result);
197
185
 
198
- if (this.shouldPersist(result)) {
199
- this.resetTrackers(instance);
200
- } else {
201
- this.handlerInstances.delete(instanceId);
202
- }
186
+ await this.emitEvent({
187
+ type: 'SettledHandlerFired',
188
+ data: {
189
+ templateId: instanceDoc.templateId,
190
+ correlationId: instanceDoc.correlationId,
191
+ persist,
192
+ },
193
+ });
194
+
195
+ await this.emitEvent({
196
+ type: 'SettledInstanceReset',
197
+ data: {
198
+ templateId: instanceDoc.templateId,
199
+ correlationId: instanceDoc.correlationId,
200
+ },
201
+ });
203
202
  } catch (error) {
203
+ const commandTypes = instanceDoc.commandTrackers.map((t) => t.commandType);
204
204
  this.onError?.(error, {
205
- commandTypes: instance.registration.commandTypes,
206
- correlationId: instance.correlationId,
205
+ commandTypes,
206
+ correlationId: instanceDoc.correlationId,
207
+ });
208
+ await this.emitEvent({
209
+ type: 'SettledInstanceCleaned',
210
+ data: {
211
+ templateId: instanceDoc.templateId,
212
+ correlationId: instanceDoc.correlationId,
213
+ },
207
214
  });
208
- this.handlerInstances.delete(instanceId);
209
215
  }
210
216
  }
211
217
 
212
- private collectEvents(instance: HandlerInstance): Record<string, Event[]> {
218
+ private collectEventsFromDoc(instanceDoc: SettledInstanceDocument): Record<string, Event[]> {
213
219
  const events: Record<string, Event[]> = {};
214
- for (const [commandType, tracker] of instance.commandTrackers) {
215
- events[commandType] = [...tracker.events];
220
+ for (const tracker of instanceDoc.commandTrackers) {
221
+ events[tracker.commandType] = [...tracker.events];
216
222
  }
217
223
  return events;
218
224
  }
@@ -226,12 +232,4 @@ export class SettledTracker {
226
232
  result.persist === true
227
233
  );
228
234
  }
229
-
230
- private resetTrackers(instance: HandlerInstance): void {
231
- for (const tracker of instance.commandTrackers.values()) {
232
- tracker.hasStarted = false;
233
- tracker.hasCompleted = false;
234
- tracker.events = [];
235
- }
236
- }
237
235
  }
@@ -20,11 +20,16 @@ interface PipelineNode {
20
20
  status?: string;
21
21
  }
22
22
 
23
+ interface GraphNode {
24
+ id: string;
25
+ type: string;
26
+ label: string;
27
+ }
28
+
23
29
  interface PipelineResponse {
24
- nodes: PipelineNode[];
30
+ nodes: GraphNode[];
25
31
  edges: Array<{ from: string; to: string }>;
26
- commandToEvents: Record<string, string[]>;
27
- eventToCommand: Record<string, string>;
32
+ pipelineNodes: PipelineNode[];
28
33
  }
29
34
 
30
35
  interface CommandAck {
@@ -97,20 +102,9 @@ describe('PipelineServer E2E', () => {
97
102
 
98
103
  const pipelineRes = await fetchJson<PipelineResponse>(`http://localhost:${server.port}/pipeline`);
99
104
 
100
- expect(pipelineRes.commandToEvents).toEqual({ ExportSchema: ['SchemaExported'] });
101
- expect(pipelineRes.eventToCommand).toEqual({ SchemaExported: 'GenerateServer' });
102
- expect(pipelineRes.nodes.some((n) => n.id === 'ExportSchema')).toBe(true);
103
105
  expect(pipelineRes.nodes.some((n) => n.id === 'evt:SchemaExported')).toBe(true);
104
-
105
- await server.stop();
106
- });
107
-
108
- it('should return sessions array', async () => {
109
- const server = new PipelineServer({ port: 0 });
110
- await server.start();
111
-
112
- const sessions = await fetchJson<unknown[]>(`http://localhost:${server.port}/sessions`);
113
- expect(Array.isArray(sessions)).toBe(true);
106
+ expect(pipelineRes.nodes.some((n) => n.id === 'cmd:GenerateServer')).toBe(true);
107
+ expect(pipelineRes.pipelineNodes.some((n) => n.id === 'ExportSchema')).toBe(true);
114
108
 
115
109
  await server.stop();
116
110
  });