@adonis-agora/durable 0.1.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/LICENSE +21 -0
  2. package/README.md +29 -0
  3. package/dist/assets/dashboard.html +446 -0
  4. package/dist/commands/main.d.ts +15 -0
  5. package/dist/commands/main.d.ts.map +1 -0
  6. package/dist/commands/main.js +15 -0
  7. package/dist/commands/main.js.map +1 -0
  8. package/dist/commands/retry.d.ts +16 -0
  9. package/dist/commands/retry.d.ts.map +1 -0
  10. package/dist/commands/retry.js +34 -0
  11. package/dist/commands/retry.js.map +1 -0
  12. package/dist/commands/runs.d.ts +17 -0
  13. package/dist/commands/runs.d.ts.map +1 -0
  14. package/dist/commands/runs.js +40 -0
  15. package/dist/commands/runs.js.map +1 -0
  16. package/dist/commands/work.d.ts +18 -0
  17. package/dist/commands/work.d.ts.map +1 -0
  18. package/dist/commands/work.js +58 -0
  19. package/dist/commands/work.js.map +1 -0
  20. package/dist/configure.d.ts +15 -0
  21. package/dist/configure.d.ts.map +1 -0
  22. package/dist/configure.js +26 -0
  23. package/dist/configure.js.map +1 -0
  24. package/dist/providers/dashboard_provider.d.ts +27 -0
  25. package/dist/providers/dashboard_provider.d.ts.map +1 -0
  26. package/dist/providers/dashboard_provider.js +94 -0
  27. package/dist/providers/dashboard_provider.js.map +1 -0
  28. package/dist/providers/durable_provider.d.ts +36 -0
  29. package/dist/providers/durable_provider.d.ts.map +1 -0
  30. package/dist/providers/durable_provider.js +113 -0
  31. package/dist/providers/durable_provider.js.map +1 -0
  32. package/dist/src/admission-redis/index.d.ts +2 -0
  33. package/dist/src/admission-redis/index.d.ts.map +1 -0
  34. package/dist/src/admission-redis/index.js +2 -0
  35. package/dist/src/admission-redis/index.js.map +1 -0
  36. package/dist/src/admission-redis/redis-admission-backend.d.ts +83 -0
  37. package/dist/src/admission-redis/redis-admission-backend.d.ts.map +1 -0
  38. package/dist/src/admission-redis/redis-admission-backend.js +200 -0
  39. package/dist/src/admission-redis/redis-admission-backend.js.map +1 -0
  40. package/dist/src/admission.d.ts +49 -0
  41. package/dist/src/admission.d.ts.map +1 -0
  42. package/dist/src/admission.js +30 -0
  43. package/dist/src/admission.js.map +1 -0
  44. package/dist/src/backoff.d.ts +5 -0
  45. package/dist/src/backoff.d.ts.map +1 -0
  46. package/dist/src/backoff.js +11 -0
  47. package/dist/src/backoff.js.map +1 -0
  48. package/dist/src/checkpoints.d.ts +42 -0
  49. package/dist/src/checkpoints.d.ts.map +1 -0
  50. package/dist/src/checkpoints.js +57 -0
  51. package/dist/src/checkpoints.js.map +1 -0
  52. package/dist/src/codec-state-store.d.ts +60 -0
  53. package/dist/src/codec-state-store.d.ts.map +1 -0
  54. package/dist/src/codec-state-store.js +129 -0
  55. package/dist/src/codec-state-store.js.map +1 -0
  56. package/dist/src/commands/index.d.ts +3 -0
  57. package/dist/src/commands/index.d.ts.map +1 -0
  58. package/dist/src/commands/index.js +3 -0
  59. package/dist/src/commands/index.js.map +1 -0
  60. package/dist/src/commands/runs.d.ts +24 -0
  61. package/dist/src/commands/runs.d.ts.map +1 -0
  62. package/dist/src/commands/runs.js +39 -0
  63. package/dist/src/commands/runs.js.map +1 -0
  64. package/dist/src/commands/worker.d.ts +61 -0
  65. package/dist/src/commands/worker.d.ts.map +1 -0
  66. package/dist/src/commands/worker.js +74 -0
  67. package/dist/src/commands/worker.js.map +1 -0
  68. package/dist/src/completion.d.ts +15 -0
  69. package/dist/src/completion.d.ts.map +1 -0
  70. package/dist/src/completion.js +10 -0
  71. package/dist/src/completion.js.map +1 -0
  72. package/dist/src/dashboard/define_config.d.ts +48 -0
  73. package/dist/src/dashboard/define_config.d.ts.map +1 -0
  74. package/dist/src/dashboard/define_config.js +57 -0
  75. package/dist/src/dashboard/define_config.js.map +1 -0
  76. package/dist/src/dashboard/handlers.d.ts +47 -0
  77. package/dist/src/dashboard/handlers.d.ts.map +1 -0
  78. package/dist/src/dashboard/handlers.js +163 -0
  79. package/dist/src/dashboard/handlers.js.map +1 -0
  80. package/dist/src/dashboard/html.d.ts +7 -0
  81. package/dist/src/dashboard/html.d.ts.map +1 -0
  82. package/dist/src/dashboard/html.js +24 -0
  83. package/dist/src/dashboard/html.js.map +1 -0
  84. package/dist/src/dashboard/index.d.ts +8 -0
  85. package/dist/src/dashboard/index.d.ts.map +1 -0
  86. package/dist/src/dashboard/index.js +6 -0
  87. package/dist/src/dashboard/index.js.map +1 -0
  88. package/dist/src/define_config.d.ts +72 -0
  89. package/dist/src/define_config.d.ts.map +1 -0
  90. package/dist/src/define_config.js +8 -0
  91. package/dist/src/define_config.js.map +1 -0
  92. package/dist/src/diagnostics-bridge.d.ts +22 -0
  93. package/dist/src/diagnostics-bridge.d.ts.map +1 -0
  94. package/dist/src/diagnostics-bridge.js +25 -0
  95. package/dist/src/diagnostics-bridge.js.map +1 -0
  96. package/dist/src/duration.d.ts +6 -0
  97. package/dist/src/duration.d.ts.map +1 -0
  98. package/dist/src/duration.js +39 -0
  99. package/dist/src/duration.js.map +1 -0
  100. package/dist/src/engine.d.ts +583 -0
  101. package/dist/src/engine.d.ts.map +1 -0
  102. package/dist/src/engine.js +1894 -0
  103. package/dist/src/engine.js.map +1 -0
  104. package/dist/src/entities.d.ts +44 -0
  105. package/dist/src/entities.d.ts.map +1 -0
  106. package/dist/src/entities.js +64 -0
  107. package/dist/src/entities.js.map +1 -0
  108. package/dist/src/errors.d.ts +68 -0
  109. package/dist/src/errors.d.ts.map +1 -0
  110. package/dist/src/errors.js +102 -0
  111. package/dist/src/errors.js.map +1 -0
  112. package/dist/src/event-accumulators.d.ts +39 -0
  113. package/dist/src/event-accumulators.d.ts.map +1 -0
  114. package/dist/src/event-accumulators.js +70 -0
  115. package/dist/src/event-accumulators.js.map +1 -0
  116. package/dist/src/events.d.ts +9 -0
  117. package/dist/src/events.d.ts.map +1 -0
  118. package/dist/src/events.js +35 -0
  119. package/dist/src/events.js.map +1 -0
  120. package/dist/src/index.d.ts +36 -0
  121. package/dist/src/index.d.ts.map +1 -0
  122. package/dist/src/index.js +37 -0
  123. package/dist/src/index.js.map +1 -0
  124. package/dist/src/interfaces.d.ts +909 -0
  125. package/dist/src/interfaces.d.ts.map +1 -0
  126. package/dist/src/interfaces.js +2 -0
  127. package/dist/src/interfaces.js.map +1 -0
  128. package/dist/src/metrics.d.ts +44 -0
  129. package/dist/src/metrics.d.ts.map +1 -0
  130. package/dist/src/metrics.js +78 -0
  131. package/dist/src/metrics.js.map +1 -0
  132. package/dist/src/otel/durable-metrics.d.ts +42 -0
  133. package/dist/src/otel/durable-metrics.d.ts.map +1 -0
  134. package/dist/src/otel/durable-metrics.js +75 -0
  135. package/dist/src/otel/durable-metrics.js.map +1 -0
  136. package/dist/src/otel/durable-otel.d.ts +20 -0
  137. package/dist/src/otel/durable-otel.d.ts.map +1 -0
  138. package/dist/src/otel/durable-otel.js +74 -0
  139. package/dist/src/otel/durable-otel.js.map +1 -0
  140. package/dist/src/otel/index.d.ts +4 -0
  141. package/dist/src/otel/index.d.ts.map +1 -0
  142. package/dist/src/otel/index.js +4 -0
  143. package/dist/src/otel/index.js.map +1 -0
  144. package/dist/src/otel/traceparent.d.ts +17 -0
  145. package/dist/src/otel/traceparent.d.ts.map +1 -0
  146. package/dist/src/otel/traceparent.js +21 -0
  147. package/dist/src/otel/traceparent.js.map +1 -0
  148. package/dist/src/pollers.d.ts +33 -0
  149. package/dist/src/pollers.d.ts.map +1 -0
  150. package/dist/src/pollers.js +76 -0
  151. package/dist/src/pollers.js.map +1 -0
  152. package/dist/src/protocol.d.ts +17 -0
  153. package/dist/src/protocol.d.ts.map +1 -0
  154. package/dist/src/protocol.js +47 -0
  155. package/dist/src/protocol.js.map +1 -0
  156. package/dist/src/queue.d.ts +113 -0
  157. package/dist/src/queue.d.ts.map +1 -0
  158. package/dist/src/queue.js +128 -0
  159. package/dist/src/queue.js.map +1 -0
  160. package/dist/src/remote-step-factory.d.ts +15 -0
  161. package/dist/src/remote-step-factory.d.ts.map +1 -0
  162. package/dist/src/remote-step-factory.js +12 -0
  163. package/dist/src/remote-step-factory.js.map +1 -0
  164. package/dist/src/remote-workflow-executor.d.ts +24 -0
  165. package/dist/src/remote-workflow-executor.d.ts.map +1 -0
  166. package/dist/src/remote-workflow-executor.js +70 -0
  167. package/dist/src/remote-workflow-executor.js.map +1 -0
  168. package/dist/src/scheduler.d.ts +67 -0
  169. package/dist/src/scheduler.d.ts.map +1 -0
  170. package/dist/src/scheduler.js +111 -0
  171. package/dist/src/scheduler.js.map +1 -0
  172. package/dist/src/search-attributes.d.ts +48 -0
  173. package/dist/src/search-attributes.d.ts.map +1 -0
  174. package/dist/src/search-attributes.js +98 -0
  175. package/dist/src/search-attributes.js.map +1 -0
  176. package/dist/src/singleton-gate.d.ts +44 -0
  177. package/dist/src/singleton-gate.d.ts.map +1 -0
  178. package/dist/src/singleton-gate.js +90 -0
  179. package/dist/src/singleton-gate.js.map +1 -0
  180. package/dist/src/step-logger.d.ts +9 -0
  181. package/dist/src/step-logger.d.ts.map +1 -0
  182. package/dist/src/step-logger.js +89 -0
  183. package/dist/src/step-logger.js.map +1 -0
  184. package/dist/src/stores/factory.d.ts +42 -0
  185. package/dist/src/stores/factory.d.ts.map +1 -0
  186. package/dist/src/stores/factory.js +29 -0
  187. package/dist/src/stores/factory.js.map +1 -0
  188. package/dist/src/stores/lucid-helpers.d.ts +11 -0
  189. package/dist/src/stores/lucid-helpers.d.ts.map +1 -0
  190. package/dist/src/stores/lucid-helpers.js +38 -0
  191. package/dist/src/stores/lucid-helpers.js.map +1 -0
  192. package/dist/src/stores/lucid-mappers.d.ts +58 -0
  193. package/dist/src/stores/lucid-mappers.d.ts.map +1 -0
  194. package/dist/src/stores/lucid-mappers.js +174 -0
  195. package/dist/src/stores/lucid-mappers.js.map +1 -0
  196. package/dist/src/stores/lucid-schema.d.ts +28 -0
  197. package/dist/src/stores/lucid-schema.d.ts.map +1 -0
  198. package/dist/src/stores/lucid-schema.js +115 -0
  199. package/dist/src/stores/lucid-schema.js.map +1 -0
  200. package/dist/src/stores/lucid.d.ts +69 -0
  201. package/dist/src/stores/lucid.d.ts.map +1 -0
  202. package/dist/src/stores/lucid.js +342 -0
  203. package/dist/src/stores/lucid.js.map +1 -0
  204. package/dist/src/telescope/dashboard.d.ts +15 -0
  205. package/dist/src/telescope/dashboard.d.ts.map +1 -0
  206. package/dist/src/telescope/dashboard.js +113 -0
  207. package/dist/src/telescope/dashboard.js.map +1 -0
  208. package/dist/src/telescope/data-providers.d.ts +20 -0
  209. package/dist/src/telescope/data-providers.d.ts.map +1 -0
  210. package/dist/src/telescope/data-providers.js +322 -0
  211. package/dist/src/telescope/data-providers.js.map +1 -0
  212. package/dist/src/telescope/extension.d.ts +22 -0
  213. package/dist/src/telescope/extension.d.ts.map +1 -0
  214. package/dist/src/telescope/extension.js +38 -0
  215. package/dist/src/telescope/extension.js.map +1 -0
  216. package/dist/src/telescope/index.d.ts +5 -0
  217. package/dist/src/telescope/index.d.ts.map +1 -0
  218. package/dist/src/telescope/index.js +4 -0
  219. package/dist/src/telescope/index.js.map +1 -0
  220. package/dist/src/telescope/telescope-sdk.d.ts +123 -0
  221. package/dist/src/telescope/telescope-sdk.d.ts.map +1 -0
  222. package/dist/src/telescope/telescope-sdk.js +12 -0
  223. package/dist/src/telescope/telescope-sdk.js.map +1 -0
  224. package/dist/src/test-helpers.d.ts +11 -0
  225. package/dist/src/test-helpers.d.ts.map +1 -0
  226. package/dist/src/test-helpers.js +12 -0
  227. package/dist/src/test-helpers.js.map +1 -0
  228. package/dist/src/testing/in-memory-state-store.d.ts +64 -0
  229. package/dist/src/testing/in-memory-state-store.d.ts.map +1 -0
  230. package/dist/src/testing/in-memory-state-store.js +259 -0
  231. package/dist/src/testing/in-memory-state-store.js.map +1 -0
  232. package/dist/src/testing/in-memory-transport.d.ts +25 -0
  233. package/dist/src/testing/in-memory-transport.d.ts.map +1 -0
  234. package/dist/src/testing/in-memory-transport.js +49 -0
  235. package/dist/src/testing/in-memory-transport.js.map +1 -0
  236. package/dist/src/testing-kit/admission-backend-conformance.d.ts +18 -0
  237. package/dist/src/testing-kit/admission-backend-conformance.d.ts.map +1 -0
  238. package/dist/src/testing-kit/admission-backend-conformance.js +81 -0
  239. package/dist/src/testing-kit/admission-backend-conformance.js.map +1 -0
  240. package/dist/src/testing-kit/assertions.d.ts +10 -0
  241. package/dist/src/testing-kit/assertions.d.ts.map +1 -0
  242. package/dist/src/testing-kit/assertions.js +41 -0
  243. package/dist/src/testing-kit/assertions.js.map +1 -0
  244. package/dist/src/testing-kit/harness.d.ts +28 -0
  245. package/dist/src/testing-kit/harness.d.ts.map +1 -0
  246. package/dist/src/testing-kit/harness.js +42 -0
  247. package/dist/src/testing-kit/harness.js.map +1 -0
  248. package/dist/src/testing-kit/index.d.ts +8 -0
  249. package/dist/src/testing-kit/index.d.ts.map +1 -0
  250. package/dist/src/testing-kit/index.js +8 -0
  251. package/dist/src/testing-kit/index.js.map +1 -0
  252. package/dist/src/testing-kit/replay.d.ts +22 -0
  253. package/dist/src/testing-kit/replay.d.ts.map +1 -0
  254. package/dist/src/testing-kit/replay.js +38 -0
  255. package/dist/src/testing-kit/replay.js.map +1 -0
  256. package/dist/src/testing-kit/state-store-conformance.d.ts +51 -0
  257. package/dist/src/testing-kit/state-store-conformance.d.ts.map +1 -0
  258. package/dist/src/testing-kit/state-store-conformance.js +430 -0
  259. package/dist/src/testing-kit/state-store-conformance.js.map +1 -0
  260. package/dist/src/testing-kit/steps.d.ts +5 -0
  261. package/dist/src/testing-kit/steps.d.ts.map +1 -0
  262. package/dist/src/testing-kit/steps.js +15 -0
  263. package/dist/src/testing-kit/steps.js.map +1 -0
  264. package/dist/src/testing-kit/transport-conformance.d.ts +16 -0
  265. package/dist/src/testing-kit/transport-conformance.d.ts.map +1 -0
  266. package/dist/src/testing-kit/transport-conformance.js +64 -0
  267. package/dist/src/testing-kit/transport-conformance.js.map +1 -0
  268. package/dist/src/tokens.d.ts +18 -0
  269. package/dist/src/tokens.d.ts.map +1 -0
  270. package/dist/src/tokens.js +18 -0
  271. package/dist/src/tokens.js.map +1 -0
  272. package/dist/src/transport-pool.d.ts +30 -0
  273. package/dist/src/transport-pool.d.ts.map +1 -0
  274. package/dist/src/transport-pool.js +82 -0
  275. package/dist/src/transport-pool.js.map +1 -0
  276. package/dist/src/transports/db-helpers.d.ts +10 -0
  277. package/dist/src/transports/db-helpers.d.ts.map +1 -0
  278. package/dist/src/transports/db-helpers.js +33 -0
  279. package/dist/src/transports/db-helpers.js.map +1 -0
  280. package/dist/src/transports/db-schema.d.ts +28 -0
  281. package/dist/src/transports/db-schema.d.ts.map +1 -0
  282. package/dist/src/transports/db-schema.js +98 -0
  283. package/dist/src/transports/db-schema.js.map +1 -0
  284. package/dist/src/transports/db.d.ts +81 -0
  285. package/dist/src/transports/db.d.ts.map +1 -0
  286. package/dist/src/transports/db.js +340 -0
  287. package/dist/src/transports/db.js.map +1 -0
  288. package/dist/src/transports/factory.d.ts +79 -0
  289. package/dist/src/transports/factory.d.ts.map +1 -0
  290. package/dist/src/transports/factory.js +57 -0
  291. package/dist/src/transports/factory.js.map +1 -0
  292. package/dist/src/transports/queue-mock-adapter.d.ts +39 -0
  293. package/dist/src/transports/queue-mock-adapter.d.ts.map +1 -0
  294. package/dist/src/transports/queue-mock-adapter.js +86 -0
  295. package/dist/src/transports/queue-mock-adapter.js.map +1 -0
  296. package/dist/src/transports/queue.d.ts +84 -0
  297. package/dist/src/transports/queue.d.ts.map +1 -0
  298. package/dist/src/transports/queue.js +210 -0
  299. package/dist/src/transports/queue.js.map +1 -0
  300. package/dist/src/workflow-ctx.d.ts +64 -0
  301. package/dist/src/workflow-ctx.d.ts.map +1 -0
  302. package/dist/src/workflow-ctx.js +457 -0
  303. package/dist/src/workflow-ctx.js.map +1 -0
  304. package/dist/src/workflow-ref.d.ts +34 -0
  305. package/dist/src/workflow-ref.d.ts.map +1 -0
  306. package/dist/src/workflow-ref.js +28 -0
  307. package/dist/src/workflow-ref.js.map +1 -0
  308. package/dist/stubs/config/durable.stub +49 -0
  309. package/dist/stubs/config/durable_dashboard.stub +17 -0
  310. package/dist/stubs/database/migrations/create_durable_tables.stub +87 -0
  311. package/dist/stubs/database/migrations/create_durable_transport_tables.stub +75 -0
  312. package/dist/stubs/main.d.ts +3 -0
  313. package/dist/stubs/main.d.ts.map +1 -0
  314. package/dist/stubs/main.js +4 -0
  315. package/dist/stubs/main.js.map +1 -0
  316. package/package.json +154 -0
@@ -0,0 +1,64 @@
1
+ import type { RunQuery, SignalWaiter, StateStore, StepCheckpoint, WorkflowRun } from '../interfaces.js';
2
+ /**
3
+ * A non-durable, in-process `StateStore` for tests and local development.
4
+ * The shipped `@dudousxd/nestjs-durable-store` package re-exports an equivalent.
5
+ */
6
+ export declare class InMemoryStateStore implements StateStore {
7
+ private readonly runs;
8
+ private readonly checkpoints;
9
+ private readonly signalWaiters;
10
+ /**
11
+ * Normalized search-attribute side-table, the in-memory analog of the SQL stores'
12
+ * `durable_run_attributes`: `key -> (runId -> row)`. Maintained on every create/update so an
13
+ * attribute query can be pushed DOWN to a key-indexed candidate set instead of scanning every run
14
+ * and comparing in-process. Mirrors {@link normalizeAttributeRows} so behavior matches the SQL path.
15
+ */
16
+ private readonly attributeIndex;
17
+ /** Test/observability hook: how many candidate runs the last attribute query's index produced. */
18
+ lastAttributeCandidates: number;
19
+ /**
20
+ * Test/observability hook: how many checkpoint rows the LAST checkpoint read materialized (the rows
21
+ * actually returned to the caller). `listCheckpoints` returns all rows for the run; the targeted
22
+ * {@link getLatestCheckpointByName} / {@link listCheckpointsByNamePrefix} return only the matches —
23
+ * so this lets the benchmark contrast "fetch N, scan in JS" against "fetch the k that match".
24
+ */
25
+ lastCheckpointRowsRead: number;
26
+ private key;
27
+ /** Drop then re-add a run's normalized attribute rows so the index tracks its current attributes. */
28
+ private reindexAttributes;
29
+ createRun(run: WorkflowRun): Promise<void>;
30
+ updateRun(runId: string, patch: Partial<WorkflowRun>): Promise<void>;
31
+ getRun(runId: string): Promise<WorkflowRun | null>;
32
+ deleteRun(runId: string): Promise<void>;
33
+ getCheckpoint(runId: string, seq: number): Promise<StepCheckpoint | null>;
34
+ saveCheckpoint(checkpoint: StepCheckpoint): Promise<void>;
35
+ listIncompleteRuns(): Promise<WorkflowRun[]>;
36
+ listPendingRuns(limit: number): Promise<WorkflowRun[]>;
37
+ listDueTimers(nowMs: number): Promise<WorkflowRun[]>;
38
+ tryLockRun(runId: string, owner: string, leaseUntilMs: number, nowMs: number): Promise<boolean>;
39
+ releaseRunLock(runId: string): Promise<void>;
40
+ renewRunLock(runId: string, owner: string, leaseUntilMs: number): Promise<boolean>;
41
+ putSignalWaiter(waiter: SignalWaiter): Promise<void>;
42
+ takeSignalWaiter(token: string): Promise<SignalWaiter | null>;
43
+ listSignalWaiters(prefix: string): Promise<SignalWaiter[]>;
44
+ transaction<T>(work: (tx: {
45
+ raw: unknown;
46
+ saveCheckpoint: (cp: StepCheckpoint) => Promise<void>;
47
+ }) => Promise<T>): Promise<T>;
48
+ private readonly bufferedSignals;
49
+ bufferSignal(token: string, payload: unknown): Promise<void>;
50
+ takeBufferedSignal(token: string): Promise<{
51
+ payload: unknown;
52
+ } | null>;
53
+ /**
54
+ * Candidate run ids satisfying ONE attribute predicate, served from {@link attributeIndex} — the
55
+ * pushdown step. Numeric predicates scan only `numValue` rows under the key; string/boolean ones
56
+ * scan `strValue` rows. This is the in-memory analog of the SQL EXISTS on `durable_run_attributes`.
57
+ */
58
+ private candidatesForFilter;
59
+ listRuns(query: RunQuery): Promise<WorkflowRun[]>;
60
+ listCheckpoints(runId: string): Promise<StepCheckpoint[]>;
61
+ getLatestCheckpointByName(runId: string, name: string): Promise<StepCheckpoint | undefined>;
62
+ listCheckpointsByNamePrefix(runId: string, prefixes: string[]): Promise<StepCheckpoint[]>;
63
+ }
64
+ //# sourceMappingURL=in-memory-state-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-memory-state-store.d.ts","sourceRoot":"","sources":["../../../src/testing/in-memory-state-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,QAAQ,EACR,YAAY,EACZ,UAAU,EACV,cAAc,EACd,WAAW,EACZ,MAAM,kBAAkB,CAAC;AAI1B;;;GAGG;AACH,qBAAa,kBAAmB,YAAW,UAAU;IACnD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAkC;IACvD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqC;IACjE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAmC;IAEjE;;;;;OAKG;IACH,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAmD;IAClF,kGAAkG;IAClG,uBAAuB,SAAK;IAC5B;;;;;OAKG;IACH,sBAAsB,SAAK;IAE3B,OAAO,CAAC,GAAG;IAIX,qGAAqG;IACrG,OAAO,CAAC,iBAAiB;IAYnB,SAAS,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAK1C,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAQpE,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAKlD,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYvC,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAKzE,cAAc,CAAC,UAAU,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAIzD,kBAAkB,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAI5C,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAQtD,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAMpD,UAAU,CACd,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,OAAO,CAAC;IASb,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ5C,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAOlF,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpD,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAO7D,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAQ1D,WAAW,CAAC,CAAC,EACjB,IAAI,EAAE,CAAC,EAAE,EAAE;QACT,GAAG,EAAE,OAAO,CAAC;QACb,cAAc,EAAE,CAAC,EAAE,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KACvD,KAAK,OAAO,CAAC,CAAC,CAAC,GACf,OAAO,CAAC,CAAC,CAAC;IAIb,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAgC;IAC1D,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAK5D,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IAQ7E;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;IAmCrB,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IA+BjD,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IASzD,yBAAyB,CAC7B,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC;IAUhC,2BAA2B,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;CAQhG"}
@@ -0,0 +1,259 @@
1
+ import { normalizeAttributeRows } from '../search-attributes.js';
2
+ /**
3
+ * A non-durable, in-process `StateStore` for tests and local development.
4
+ * The shipped `@dudousxd/nestjs-durable-store` package re-exports an equivalent.
5
+ */
6
+ export class InMemoryStateStore {
7
+ runs = new Map();
8
+ checkpoints = new Map();
9
+ signalWaiters = new Map();
10
+ /**
11
+ * Normalized search-attribute side-table, the in-memory analog of the SQL stores'
12
+ * `durable_run_attributes`: `key -> (runId -> row)`. Maintained on every create/update so an
13
+ * attribute query can be pushed DOWN to a key-indexed candidate set instead of scanning every run
14
+ * and comparing in-process. Mirrors {@link normalizeAttributeRows} so behavior matches the SQL path.
15
+ */
16
+ attributeIndex = new Map();
17
+ /** Test/observability hook: how many candidate runs the last attribute query's index produced. */
18
+ lastAttributeCandidates = 0;
19
+ /**
20
+ * Test/observability hook: how many checkpoint rows the LAST checkpoint read materialized (the rows
21
+ * actually returned to the caller). `listCheckpoints` returns all rows for the run; the targeted
22
+ * {@link getLatestCheckpointByName} / {@link listCheckpointsByNamePrefix} return only the matches —
23
+ * so this lets the benchmark contrast "fetch N, scan in JS" against "fetch the k that match".
24
+ */
25
+ lastCheckpointRowsRead = 0;
26
+ key(runId, seq) {
27
+ return `${runId}:${seq}`;
28
+ }
29
+ /** Drop then re-add a run's normalized attribute rows so the index tracks its current attributes. */
30
+ reindexAttributes(runId, attributes) {
31
+ for (const byRun of this.attributeIndex.values())
32
+ byRun.delete(runId);
33
+ for (const row of normalizeAttributeRows(runId, attributes)) {
34
+ let byRun = this.attributeIndex.get(row.key);
35
+ if (!byRun) {
36
+ byRun = new Map();
37
+ this.attributeIndex.set(row.key, byRun);
38
+ }
39
+ byRun.set(runId, row);
40
+ }
41
+ }
42
+ async createRun(run) {
43
+ this.runs.set(run.id, { ...run });
44
+ this.reindexAttributes(run.id, run.searchAttributes);
45
+ }
46
+ async updateRun(runId, patch) {
47
+ const existing = this.runs.get(runId);
48
+ if (!existing)
49
+ throw new Error(`run ${runId} not found`);
50
+ const next = { ...existing, ...patch };
51
+ this.runs.set(runId, next);
52
+ if ('searchAttributes' in patch)
53
+ this.reindexAttributes(runId, next.searchAttributes);
54
+ }
55
+ async getRun(runId) {
56
+ const run = this.runs.get(runId);
57
+ return run ? { ...run } : null;
58
+ }
59
+ async deleteRun(runId) {
60
+ this.runs.delete(runId);
61
+ for (const [key, cp] of this.checkpoints) {
62
+ if (cp.runId === runId)
63
+ this.checkpoints.delete(key);
64
+ }
65
+ for (const [token, waiter] of this.signalWaiters) {
66
+ if (waiter.runId === runId)
67
+ this.signalWaiters.delete(token);
68
+ }
69
+ // Drop the run's normalized attribute rows (reindex with no attributes clears them).
70
+ this.reindexAttributes(runId, undefined);
71
+ }
72
+ async getCheckpoint(runId, seq) {
73
+ const cp = this.checkpoints.get(this.key(runId, seq));
74
+ return cp ? { ...cp } : null;
75
+ }
76
+ async saveCheckpoint(checkpoint) {
77
+ this.checkpoints.set(this.key(checkpoint.runId, checkpoint.seq), { ...checkpoint });
78
+ }
79
+ async listIncompleteRuns() {
80
+ return [...this.runs.values()].filter((r) => r.status === 'running').map((r) => ({ ...r }));
81
+ }
82
+ async listPendingRuns(limit) {
83
+ return [...this.runs.values()]
84
+ .filter((r) => r.status === 'pending')
85
+ .sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime() || a.id.localeCompare(b.id))
86
+ .slice(0, limit)
87
+ .map((r) => ({ ...r }));
88
+ }
89
+ async listDueTimers(nowMs) {
90
+ return [...this.runs.values()]
91
+ .filter((r) => r.status === 'suspended' && r.wakeAt !== undefined && r.wakeAt <= nowMs)
92
+ .map((r) => ({ ...r }));
93
+ }
94
+ async tryLockRun(runId, owner, leaseUntilMs, nowMs) {
95
+ const run = this.runs.get(runId);
96
+ if (!run)
97
+ return false;
98
+ if (run.lockedUntil !== undefined && run.lockedUntil > nowMs)
99
+ return false;
100
+ run.lockedBy = owner;
101
+ run.lockedUntil = leaseUntilMs;
102
+ return true;
103
+ }
104
+ async releaseRunLock(runId) {
105
+ const run = this.runs.get(runId);
106
+ if (run) {
107
+ run.lockedBy = undefined;
108
+ run.lockedUntil = undefined;
109
+ }
110
+ }
111
+ async renewRunLock(runId, owner, leaseUntilMs) {
112
+ const run = this.runs.get(runId);
113
+ if (!run || run.lockedBy !== owner)
114
+ return false;
115
+ run.lockedUntil = leaseUntilMs;
116
+ return true;
117
+ }
118
+ async putSignalWaiter(waiter) {
119
+ this.signalWaiters.set(waiter.token, { ...waiter });
120
+ }
121
+ async takeSignalWaiter(token) {
122
+ const waiter = this.signalWaiters.get(token);
123
+ if (!waiter)
124
+ return null;
125
+ this.signalWaiters.delete(token);
126
+ return { ...waiter };
127
+ }
128
+ async listSignalWaiters(prefix) {
129
+ return [...this.signalWaiters.values()]
130
+ .filter((w) => w.token.startsWith(prefix))
131
+ .map((w) => ({ ...w }));
132
+ }
133
+ // No real DB transaction (there's no DB) — run the work and save the checkpoint. Exactly-once
134
+ // across a crash needs a SQL store; this keeps `ctx.transaction` usable in tests / local dev.
135
+ async transaction(work) {
136
+ return work({ raw: this, saveCheckpoint: (cp) => this.saveCheckpoint(cp) });
137
+ }
138
+ bufferedSignals = new Map();
139
+ async bufferSignal(token, payload) {
140
+ const queue = this.bufferedSignals.get(token) ?? [];
141
+ queue.push(payload);
142
+ this.bufferedSignals.set(token, queue);
143
+ }
144
+ async takeBufferedSignal(token) {
145
+ const queue = this.bufferedSignals.get(token);
146
+ if (!queue || queue.length === 0)
147
+ return null;
148
+ const payload = queue.shift();
149
+ if (queue.length === 0)
150
+ this.bufferedSignals.delete(token);
151
+ return { payload };
152
+ }
153
+ /**
154
+ * Candidate run ids satisfying ONE attribute predicate, served from {@link attributeIndex} — the
155
+ * pushdown step. Numeric predicates scan only `numValue` rows under the key; string/boolean ones
156
+ * scan `strValue` rows. This is the in-memory analog of the SQL EXISTS on `durable_run_attributes`.
157
+ */
158
+ candidatesForFilter(f) {
159
+ const byRun = this.attributeIndex.get(f.key);
160
+ const out = new Set();
161
+ if (!byRun)
162
+ return out;
163
+ const numeric = typeof f.value === 'number';
164
+ const operand = typeof f.value === 'boolean' ? (f.value ? 'true' : 'false') : f.value;
165
+ for (const row of byRun.values()) {
166
+ const actual = numeric ? row.numValue : row.strValue;
167
+ if (actual == null)
168
+ continue;
169
+ let ok = false;
170
+ switch (f.op) {
171
+ case 'eq':
172
+ ok = actual === operand;
173
+ break;
174
+ case 'ne':
175
+ ok = actual !== operand;
176
+ break;
177
+ case 'gt':
178
+ ok = actual > operand;
179
+ break;
180
+ case 'gte':
181
+ ok = actual >= operand;
182
+ break;
183
+ case 'lt':
184
+ ok = actual < operand;
185
+ break;
186
+ case 'lte':
187
+ ok = actual <= operand;
188
+ break;
189
+ }
190
+ if (ok)
191
+ out.add(row.runId);
192
+ }
193
+ return out;
194
+ }
195
+ async listRuns(query) {
196
+ let runs = [...this.runs.values()];
197
+ if (query.workflow)
198
+ runs = runs.filter((r) => r.workflow === query.workflow);
199
+ if (query.status)
200
+ runs = runs.filter((r) => r.status === query.status);
201
+ if (query.statuses)
202
+ runs = runs.filter((r) => query.statuses?.includes(r.status));
203
+ if (query.tag)
204
+ runs = runs.filter((r) => r.tags?.includes(query.tag));
205
+ if (query.attributes?.length) {
206
+ // Pushdown: intersect per-predicate candidate sets from the key-indexed side-table, so we only
207
+ // ever materialize the runs that already satisfy EVERY attribute filter (no full per-run scan).
208
+ let candidates = null;
209
+ for (const f of query.attributes) {
210
+ const next = this.candidatesForFilter(f);
211
+ if (candidates == null) {
212
+ candidates = next;
213
+ }
214
+ else {
215
+ const prev = candidates;
216
+ candidates = new Set([...prev].filter((id) => next.has(id)));
217
+ }
218
+ if (candidates.size === 0)
219
+ break;
220
+ }
221
+ const ids = candidates ?? new Set();
222
+ this.lastAttributeCandidates = ids.size;
223
+ runs = runs.filter((r) => ids.has(r.id));
224
+ }
225
+ // Newest first (matches the store adapters' `createdAt DESC`) — recent runs on top in the dashboard.
226
+ runs.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
227
+ const offset = query.offset ?? 0;
228
+ const limit = query.limit ?? runs.length;
229
+ return runs.slice(offset, offset + limit).map((r) => ({ ...r }));
230
+ }
231
+ async listCheckpoints(runId) {
232
+ const rows = [...this.checkpoints.values()]
233
+ .filter((cp) => cp.runId === runId)
234
+ .sort((a, b) => a.seq - b.seq)
235
+ .map((cp) => ({ ...cp }));
236
+ this.lastCheckpointRowsRead = rows.length;
237
+ return rows;
238
+ }
239
+ async getLatestCheckpointByName(runId, name) {
240
+ let latest;
241
+ for (const cp of this.checkpoints.values()) {
242
+ if (cp.runId !== runId || cp.name !== name)
243
+ continue;
244
+ if (!latest || cp.seq > latest.seq)
245
+ latest = cp;
246
+ }
247
+ this.lastCheckpointRowsRead = latest ? 1 : 0;
248
+ return latest ? { ...latest } : undefined;
249
+ }
250
+ async listCheckpointsByNamePrefix(runId, prefixes) {
251
+ const rows = [...this.checkpoints.values()]
252
+ .filter((cp) => cp.runId === runId && prefixes.some((p) => cp.name.startsWith(p)))
253
+ .sort((a, b) => a.seq - b.seq)
254
+ .map((cp) => ({ ...cp }));
255
+ this.lastCheckpointRowsRead = rows.length;
256
+ return rows;
257
+ }
258
+ }
259
+ //# sourceMappingURL=in-memory-state-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-memory-state-store.js","sourceRoot":"","sources":["../../../src/testing/in-memory-state-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import type { ControlMessage, ControlPlane, Heartbeat, RemoteTask, StepResult, Transport, WorkflowStepEvent } from '../interfaces.js';
2
+ import { type StepHandler } from '../protocol.js';
3
+ /**
4
+ * An in-process `Transport` (and `ControlPlane`) for tests and local development: registered
5
+ * handlers stand in for remote workers, so a whole cross-app workflow runs in a single process,
6
+ * and control messages broadcast locally. Pass the same instance as both `transport` and
7
+ * `controlPlane`.
8
+ */
9
+ export declare class InMemoryTransport implements Transport, ControlPlane {
10
+ private readonly handlers;
11
+ private resultHandler?;
12
+ private stepEventHandler?;
13
+ private readonly controlHandlers;
14
+ /** Register a fake worker handler for a step name. */
15
+ handle(name: string, fn: StepHandler): void;
16
+ dispatch(task: RemoteTask): Promise<void>;
17
+ onResult(handler: (result: StepResult) => Promise<void>): void;
18
+ onHeartbeat(_handler: (beat: Heartbeat) => Promise<void>): void;
19
+ /** Workflow step lifecycle: deliver to the engine's handler (async, mirroring a real broker). */
20
+ dispatchStepEvent(event: WorkflowStepEvent): Promise<void>;
21
+ onStepEvent(handler: (event: WorkflowStepEvent) => Promise<void>): void;
22
+ publishControl(msg: ControlMessage): Promise<void>;
23
+ onControl(handler: (msg: ControlMessage) => void): void;
24
+ }
25
+ //# sourceMappingURL=in-memory-transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-memory-transport.d.ts","sourceRoot":"","sources":["../../../src/testing/in-memory-transport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,YAAY,EACZ,SAAS,EACT,UAAU,EACV,UAAU,EACV,SAAS,EACT,iBAAiB,EAClB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,KAAK,WAAW,EAAkB,MAAM,gBAAgB,CAAC;AAElE;;;;;GAKG;AACH,qBAAa,iBAAkB,YAAW,SAAS,EAAE,YAAY;IAC/D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkC;IAC3D,OAAO,CAAC,aAAa,CAAC,CAAwC;IAC9D,OAAO,CAAC,gBAAgB,CAAC,CAA8C;IACvE,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA4C;IAE5E,sDAAsD;IACtD,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,WAAW,GAAG,IAAI;IAIrC,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAS/C,QAAQ,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAI9D,WAAW,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAI/D,iGAAiG;IAC3F,iBAAiB,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhE,WAAW,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAMjE,cAAc,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxD,SAAS,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,IAAI,GAAG,IAAI;CAGxD"}
@@ -0,0 +1,49 @@
1
+ import { runStepHandler } from '../protocol.js';
2
+ /**
3
+ * An in-process `Transport` (and `ControlPlane`) for tests and local development: registered
4
+ * handlers stand in for remote workers, so a whole cross-app workflow runs in a single process,
5
+ * and control messages broadcast locally. Pass the same instance as both `transport` and
6
+ * `controlPlane`.
7
+ */
8
+ export class InMemoryTransport {
9
+ handlers = new Map();
10
+ resultHandler;
11
+ stepEventHandler;
12
+ controlHandlers = new Set();
13
+ /** Register a fake worker handler for a step name. */
14
+ handle(name, fn) {
15
+ this.handlers.set(name, fn);
16
+ }
17
+ async dispatch(task) {
18
+ if (!this.resultHandler)
19
+ throw new Error('no result handler registered');
20
+ const result = await runStepHandler(task, this.handlers.get(task.name));
21
+ // Deliver the result ASYNCHRONOUSLY, not inline: a durable `ctx.call` suspends the run right
22
+ // after dispatch, so the result must land AFTER that unwinds (else the resume re-enters
23
+ // mid-suspend). Real brokers are async; this mirrors them.
24
+ setImmediate(() => void this.resultHandler?.(result));
25
+ }
26
+ onResult(handler) {
27
+ this.resultHandler = handler;
28
+ }
29
+ onHeartbeat(_handler) {
30
+ // In-process handlers run synchronously; there is no liveness to track.
31
+ }
32
+ /** Workflow step lifecycle: deliver to the engine's handler (async, mirroring a real broker). */
33
+ async dispatchStepEvent(event) {
34
+ await this.stepEventHandler?.(event);
35
+ }
36
+ onStepEvent(handler) {
37
+ this.stepEventHandler = handler;
38
+ }
39
+ // Control plane: broadcast to every registered handler (including the publisher's own — the
40
+ // engine dedupes by `from`), mirroring how a real broker echoes a publish to all subscribers.
41
+ async publishControl(msg) {
42
+ for (const handler of this.controlHandlers)
43
+ handler(msg);
44
+ }
45
+ onControl(handler) {
46
+ this.controlHandlers.add(handler);
47
+ }
48
+ }
49
+ //# sourceMappingURL=in-memory-transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-memory-transport.js","sourceRoot":"","sources":["../../../src/testing/in-memory-transport.ts"],"names":[],"mappings":"AASA,OAAO,EAAoB,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAElE;;;;;GAKG;AACH,MAAM,OAAO,iBAAiB;IACX,QAAQ,GAAG,IAAI,GAAG,EAAuB,CAAC;IACnD,aAAa,CAAyC;IACtD,gBAAgB,CAA+C;IACtD,eAAe,GAAG,IAAI,GAAG,EAAiC,CAAC;IAE5E,sDAAsD;IACtD,MAAM,CAAC,IAAY,EAAE,EAAe;QAClC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,IAAgB;QAC7B,IAAI,CAAC,IAAI,CAAC,aAAa;YAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;QACzE,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACxE,6FAA6F;QAC7F,wFAAwF;QACxF,2DAA2D;QAC3D,YAAY,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC,aAAa,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IACxD,CAAC;IAED,QAAQ,CAAC,OAA8C;QACrD,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC;IAC/B,CAAC;IAED,WAAW,CAAC,QAA4C;QACtD,wEAAwE;IAC1E,CAAC;IAED,iGAAiG;IACjG,KAAK,CAAC,iBAAiB,CAAC,KAAwB;QAC9C,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC,KAAK,CAAC,CAAC;IACvC,CAAC;IAED,WAAW,CAAC,OAAoD;QAC9D,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC;IAClC,CAAC;IAED,4FAA4F;IAC5F,8FAA8F;IAC9F,KAAK,CAAC,cAAc,CAAC,GAAmB;QACtC,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,eAAe;YAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3D,CAAC;IAED,SAAS,CAAC,OAAsC;QAC9C,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC;CACF"}
@@ -0,0 +1,18 @@
1
+ import type { AdmissionBackend } from '../index.js';
2
+ /**
3
+ * Builds an {@link AdmissionBackend} bound to the given test clock. Implementations that hold their
4
+ * own resources (e.g. a Redis connection) should register the instance for teardown out-of-band.
5
+ */
6
+ export type AdmissionBackendFactory = (clock: () => number) => AdmissionBackend;
7
+ /**
8
+ * The SHARED cross-backend behavioural contract for the flow-control admission gate. Both the
9
+ * in-process `InMemoryAdmissionBackend` and the Redis `RedisAdmissionBackend` run it, so their
10
+ * concurrency / rate-limit / ordering semantics can never silently drift apart — backend-specific
11
+ * concerns (leases, pub/sub, cross-pod globality) live in each adapter's own spec.
12
+ *
13
+ * The engine always passes a stable `waiterId`, so every gated call is order-tracked: ties with no
14
+ * priority/fairness fall back to arrival FIFO (or LIFO when configured). These cases assert exactly
15
+ * that, on ONE backend instance.
16
+ */
17
+ export declare function runAdmissionBackendContract(name: string, makeBackend: AdmissionBackendFactory): void;
18
+ //# sourceMappingURL=admission-backend-conformance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admission-backend-conformance.d.ts","sourceRoot":"","sources":["../../../src/testing-kit/admission-backend-conformance.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAe,MAAM,aAAa,CAAC;AAEjE;;;GAGG;AACH,MAAM,MAAM,uBAAuB,GAAG,CAAC,KAAK,EAAE,MAAM,MAAM,KAAK,gBAAgB,CAAC;AAEhF;;;;;;;;;GASG;AACH,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,uBAAuB,GACnC,IAAI,CA2EN"}
@@ -0,0 +1,81 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ /**
3
+ * The SHARED cross-backend behavioural contract for the flow-control admission gate. Both the
4
+ * in-process `InMemoryAdmissionBackend` and the Redis `RedisAdmissionBackend` run it, so their
5
+ * concurrency / rate-limit / ordering semantics can never silently drift apart — backend-specific
6
+ * concerns (leases, pub/sub, cross-pod globality) live in each adapter's own spec.
7
+ *
8
+ * The engine always passes a stable `waiterId`, so every gated call is order-tracked: ties with no
9
+ * priority/fairness fall back to arrival FIFO (or LIFO when configured). These cases assert exactly
10
+ * that, on ONE backend instance.
11
+ */
12
+ export function runAdmissionBackendContract(name, makeBackend) {
13
+ describe(`AdmissionBackend contract: ${name}`, () => {
14
+ let now = 1_000_000;
15
+ const make = (config) => {
16
+ now = 1_000_000;
17
+ const backend = makeBackend(() => now);
18
+ backend.register(config);
19
+ return backend;
20
+ };
21
+ it('caps concurrency: a second call blocks until the first releases', async () => {
22
+ const b = make({ name: 'q', concurrency: 1 });
23
+ expect((await b.tryAdmit('q', { waiterId: 'a' })).ok).toBe(true);
24
+ expect((await b.tryAdmit('q', { waiterId: 'b' })).ok).toBe(false);
25
+ await b.release('q', 'a');
26
+ expect((await b.tryAdmit('q', { waiterId: 'b' })).ok).toBe(true);
27
+ });
28
+ it('enforces a fixed-window rate limit', async () => {
29
+ const b = make({ name: 'q', rateLimit: { limit: 2, periodMs: 1000 } });
30
+ expect((await b.tryAdmit('q', { waiterId: '1' })).ok).toBe(true);
31
+ expect((await b.tryAdmit('q', { waiterId: '2' })).ok).toBe(true);
32
+ expect((await b.tryAdmit('q', { waiterId: '3' })).ok).toBe(false);
33
+ now += 1001;
34
+ expect((await b.tryAdmit('q', { waiterId: '4' })).ok).toBe(true);
35
+ });
36
+ it('admits the highest-priority waiter first when a slot frees', async () => {
37
+ const b = make({ name: 'q', concurrency: 1 });
38
+ expect((await b.tryAdmit('q', { waiterId: 'holder' })).ok).toBe(true);
39
+ expect((await b.tryAdmit('q', { waiterId: 'low', priority: 1 })).ok).toBe(false);
40
+ expect((await b.tryAdmit('q', { waiterId: 'high', priority: 9 })).ok).toBe(false);
41
+ await b.release('q', 'holder');
42
+ expect((await b.tryAdmit('q', { waiterId: 'low', priority: 1 })).ok).toBe(false);
43
+ expect((await b.tryAdmit('q', { waiterId: 'high', priority: 9 })).ok).toBe(true);
44
+ });
45
+ it('orders plain-concurrency waiters by arrival (FIFO) — no priority/fairness configured', async () => {
46
+ const b = make({ name: 'q', concurrency: 1 });
47
+ expect((await b.tryAdmit('q', { waiterId: 'holder' })).ok).toBe(true);
48
+ expect((await b.tryAdmit('q', { waiterId: 'first' })).ok).toBe(false);
49
+ expect((await b.tryAdmit('q', { waiterId: 'second' })).ok).toBe(false);
50
+ await b.release('q', 'holder');
51
+ // The earlier arrival wins the freed slot, on every backend.
52
+ expect((await b.tryAdmit('q', { waiterId: 'second' })).ok).toBe(false);
53
+ expect((await b.tryAdmit('q', { waiterId: 'first' })).ok).toBe(true);
54
+ });
55
+ it('admits the most-recent arrival first when order is LIFO', async () => {
56
+ const b = make({ name: 'q', concurrency: 1, order: 'lifo' });
57
+ expect((await b.tryAdmit('q', { waiterId: 'holder' })).ok).toBe(true);
58
+ expect((await b.tryAdmit('q', { waiterId: 'first' })).ok).toBe(false);
59
+ expect((await b.tryAdmit('q', { waiterId: 'second' })).ok).toBe(false);
60
+ await b.release('q', 'holder');
61
+ expect((await b.tryAdmit('q', { waiterId: 'first' })).ok).toBe(false);
62
+ expect((await b.tryAdmit('q', { waiterId: 'second' })).ok).toBe(true);
63
+ });
64
+ it('round-robins a contended slot across fairness keys', async () => {
65
+ const b = make({ name: 'q', concurrency: 1, fairness: 'key' });
66
+ expect((await b.tryAdmit('q', { waiterId: 'a0', key: 'A' })).ok).toBe(true);
67
+ expect((await b.tryAdmit('q', { waiterId: 'a1', key: 'A' })).ok).toBe(false);
68
+ expect((await b.tryAdmit('q', { waiterId: 'b0', key: 'B' })).ok).toBe(false);
69
+ await b.release('q', 'a0');
70
+ // B (never served) wins over A (just served), not arrival order.
71
+ expect((await b.tryAdmit('q', { waiterId: 'a1', key: 'A' })).ok).toBe(false);
72
+ expect((await b.tryAdmit('q', { waiterId: 'b0', key: 'B' })).ok).toBe(true);
73
+ });
74
+ it('leaves an unregistered queue ungated', async () => {
75
+ const b = make({ name: 'q', concurrency: 1 });
76
+ expect((await b.tryAdmit('other', { waiterId: 'x' })).ok).toBe(true);
77
+ expect((await b.tryAdmit('other', { waiterId: 'y' })).ok).toBe(true);
78
+ });
79
+ });
80
+ }
81
+ //# sourceMappingURL=admission-backend-conformance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admission-backend-conformance.js","sourceRoot":"","sources":["../../../src/testing-kit/admission-backend-conformance.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { RunStatus, StateStore } from '../index.js';
2
+ export declare function assertRunStatus(store: StateStore, runId: string, status: RunStatus): Promise<void>;
3
+ export declare function assertOutput(store: StateStore, runId: string, expected: unknown): Promise<void>;
4
+ /** The names of the steps that have run, in order. */
5
+ export declare function recordedSteps(store: StateStore, runId: string): Promise<string[]>;
6
+ /** Assert every named step ran (in any order). */
7
+ export declare function assertStepsRan(store: StateStore, runId: string, names: string[]): Promise<void>;
8
+ /** Assert a step ran exactly the given number of attempts (e.g. to verify retries). */
9
+ export declare function assertStepAttempts(store: StateStore, runId: string, name: string, attempts: number): Promise<void>;
10
+ //# sourceMappingURL=assertions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assertions.d.ts","sourceRoot":"","sources":["../../../src/testing-kit/assertions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAQzD,wBAAsB,eAAe,CACnC,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,SAAS,GAChB,OAAO,CAAC,IAAI,CAAC,CAKf;AAED,wBAAsB,YAAY,CAChC,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,OAAO,GAChB,OAAO,CAAC,IAAI,CAAC,CAOf;AAED,sDAAsD;AACtD,wBAAsB,aAAa,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAEvF;AAED,kDAAkD;AAClD,wBAAsB,cAAc,CAClC,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EAAE,GACd,OAAO,CAAC,IAAI,CAAC,CAOf;AAED,uFAAuF;AACvF,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAMf"}
@@ -0,0 +1,41 @@
1
+ async function requireRun(store, runId) {
2
+ const run = await store.getRun(runId);
3
+ if (!run)
4
+ throw new Error(`assertion failed: run ${runId} not found`);
5
+ return run;
6
+ }
7
+ export async function assertRunStatus(store, runId, status) {
8
+ const run = await requireRun(store, runId);
9
+ if (run.status !== status) {
10
+ throw new Error(`expected run ${runId} to be "${status}", but it was "${run.status}"`);
11
+ }
12
+ }
13
+ export async function assertOutput(store, runId, expected) {
14
+ const run = await requireRun(store, runId);
15
+ if (JSON.stringify(run.output) !== JSON.stringify(expected)) {
16
+ throw new Error(`expected run ${runId} output ${JSON.stringify(expected)}, got ${JSON.stringify(run.output)}`);
17
+ }
18
+ }
19
+ /** The names of the steps that have run, in order. */
20
+ export async function recordedSteps(store, runId) {
21
+ return (await store.listCheckpoints(runId)).map((cp) => cp.name);
22
+ }
23
+ /** Assert every named step ran (in any order). */
24
+ export async function assertStepsRan(store, runId, names) {
25
+ const ran = await recordedSteps(store, runId);
26
+ for (const name of names) {
27
+ if (!ran.includes(name)) {
28
+ throw new Error(`expected step "${name}" to have run; ran: [${ran.join(', ')}]`);
29
+ }
30
+ }
31
+ }
32
+ /** Assert a step ran exactly the given number of attempts (e.g. to verify retries). */
33
+ export async function assertStepAttempts(store, runId, name, attempts) {
34
+ const cp = (await store.listCheckpoints(runId)).find((c) => c.name === name);
35
+ if (!cp)
36
+ throw new Error(`expected step "${name}" to have run, but it did not`);
37
+ if (cp.attempts !== attempts) {
38
+ throw new Error(`expected step "${name}" to take ${attempts} attempt(s), took ${cp.attempts}`);
39
+ }
40
+ }
41
+ //# sourceMappingURL=assertions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assertions.js","sourceRoot":"","sources":["../../../src/testing-kit/assertions.ts"],"names":[],"mappings":"AAEA,KAAK,UAAU,UAAU,CAAC,KAAiB,EAAE,KAAa;IACxD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACtC,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,KAAK,YAAY,CAAC,CAAC;IACtE,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,KAAiB,EACjB,KAAa,EACb,MAAiB;IAEjB,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC3C,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,gBAAgB,KAAK,WAAW,MAAM,kBAAkB,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;IACzF,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,KAAiB,EACjB,KAAa,EACb,QAAiB;IAEjB,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC3C,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5D,MAAM,IAAI,KAAK,CACb,gBAAgB,KAAK,WAAW,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAC9F,CAAC;IACJ,CAAC;AACH,CAAC;AAED,sDAAsD;AACtD,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,KAAiB,EAAE,KAAa;IAClE,OAAO,CAAC,MAAM,KAAK,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;AACnE,CAAC;AAED,kDAAkD;AAClD,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,KAAiB,EACjB,KAAa,EACb,KAAe;IAEf,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC9C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,kBAAkB,IAAI,wBAAwB,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnF,CAAC;IACH,CAAC;AACH,CAAC;AAED,uFAAuF;AACvF,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,KAAiB,EACjB,KAAa,EACb,IAAY,EACZ,QAAgB;IAEhB,MAAM,EAAE,GAAG,CAAC,MAAM,KAAK,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IAC7E,IAAI,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,IAAI,+BAA+B,CAAC,CAAC;IAChF,IAAI,EAAE,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,kBAAkB,IAAI,aAAa,QAAQ,qBAAqB,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;IACjG,CAAC;AACH,CAAC"}