experimental-a2 0.18.0 → 0.18.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 (114) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/{actor-Bjce9_5U.d.ts → actor-C7b-1arn.d.ts} +3 -3
  3. package/dist/{actor-Bjce9_5U.d.ts.map → actor-C7b-1arn.d.ts.map} +1 -1
  4. package/dist/actor-client.d.ts +1 -1
  5. package/dist/actor-react.d.ts +1 -1
  6. package/dist/actor-react.js +1 -1
  7. package/dist/actor.d.ts +1 -1
  8. package/dist/actor.js +2 -2
  9. package/dist/{ai-DrUaMyRt.d.ts → ai-BMLlI2Ff.d.ts} +2 -2
  10. package/dist/{ai-DrUaMyRt.d.ts.map → ai-BMLlI2Ff.d.ts.map} +1 -1
  11. package/dist/{ai-BpOGm-zB.js → ai-D6mGlO8j.js} +2 -2
  12. package/dist/{ai-BpOGm-zB.js.map → ai-D6mGlO8j.js.map} +1 -1
  13. package/dist/ai-client.d.ts +1 -1
  14. package/dist/ai-client.js +2 -2
  15. package/dist/ai-fx.d.ts +1 -1
  16. package/dist/ai-fx.d.ts.map +1 -1
  17. package/dist/ai-fx.js +92 -34
  18. package/dist/ai-fx.js.map +1 -1
  19. package/dist/{ai-harness-DvsPeJeB.d.ts → ai-harness-B2suP2Qh.d.ts} +2 -2
  20. package/dist/{ai-harness-DvsPeJeB.d.ts.map → ai-harness-B2suP2Qh.d.ts.map} +1 -1
  21. package/dist/ai-pi.d.ts +1 -1
  22. package/dist/ai-pi.d.ts.map +1 -1
  23. package/dist/ai-pi.js +59 -13
  24. package/dist/ai-pi.js.map +1 -1
  25. package/dist/ai-react.d.ts +1 -1
  26. package/dist/ai-react.js +2 -2
  27. package/dist/ai-server.d.ts +3 -3
  28. package/dist/ai-server.d.ts.map +1 -1
  29. package/dist/ai-server.js +10 -6
  30. package/dist/ai-server.js.map +1 -1
  31. package/dist/ai-tool-input-DmSqMUQi.js +40 -0
  32. package/dist/ai-tool-input-DmSqMUQi.js.map +1 -0
  33. package/dist/ai.d.ts +1 -1
  34. package/dist/ai.js +1 -1
  35. package/dist/{client-BReKqwZC.js → client-BhHLoNKF.js} +3 -3
  36. package/dist/{client-BReKqwZC.js.map → client-BhHLoNKF.js.map} +1 -1
  37. package/dist/client.js +1 -1
  38. package/dist/index.d.ts +2 -2
  39. package/dist/{internal-B2T3U4Rq.js → internal-CscSY7K_.js} +4 -2
  40. package/dist/{internal-B2T3U4Rq.js.map → internal-CscSY7K_.js.map} +1 -1
  41. package/dist/react.js +1 -1
  42. package/dist/scheduler-qstash.d.ts +2 -2
  43. package/dist/scheduler-qstash.js +3 -3
  44. package/dist/scheduler-qstash.js.map +1 -1
  45. package/dist/scheduler-vercel.d.ts +7 -7
  46. package/dist/scheduler-vercel.d.ts.map +1 -1
  47. package/dist/scheduler-vercel.js +9 -10
  48. package/dist/scheduler-vercel.js.map +1 -1
  49. package/dist/{server-Dw_k_7kO.js → server-D-Y4pqwu.js} +37 -11
  50. package/dist/server-D-Y4pqwu.js.map +1 -0
  51. package/dist/{server-En7cbi3v.d.ts → server-DYAATFuT.d.ts} +11 -5
  52. package/dist/server-DYAATFuT.d.ts.map +1 -0
  53. package/dist/server.d.ts +2 -2
  54. package/dist/server.js +1 -1
  55. package/dist/{session-clear-Bo-XTFEy.d.ts → session-clear-C-QwTXV1.d.ts} +2 -2
  56. package/dist/session-clear-C-QwTXV1.d.ts.map +1 -0
  57. package/dist/{store-Djdv0bnZ.d.ts → store-CyLUy86v.d.ts} +23 -4
  58. package/dist/store-CyLUy86v.d.ts.map +1 -0
  59. package/dist/store-N8PXxDAS.js.map +1 -1
  60. package/dist/store-memory.d.ts +1 -1
  61. package/dist/store-memory.js +25 -6
  62. package/dist/store-memory.js.map +1 -1
  63. package/dist/{store-polling-B5FcwJfo.js → store-polling-7WJV0YWP.js} +2 -2
  64. package/dist/{store-polling-B5FcwJfo.js.map → store-polling-7WJV0YWP.js.map} +1 -1
  65. package/dist/store-postgres.d.ts +1 -1
  66. package/dist/store-postgres.d.ts.map +1 -1
  67. package/dist/store-postgres.js +55 -25
  68. package/dist/store-postgres.js.map +1 -1
  69. package/dist/{store-presence-polling-BAwS8RWn.js → store-presence-polling-B1ixeqIS.js} +3 -3
  70. package/dist/{store-presence-polling-BAwS8RWn.js.map → store-presence-polling-B1ixeqIS.js.map} +1 -1
  71. package/dist/store-redis-http.d.ts +1 -1
  72. package/dist/store-redis-http.js +3 -3
  73. package/dist/{store-redis-notify-BRITti_o.js → store-redis-notify-CM0AfLY0.js} +88 -37
  74. package/dist/store-redis-notify-CM0AfLY0.js.map +1 -0
  75. package/dist/store-redis.d.ts +1 -1
  76. package/dist/store-redis.js +1 -1
  77. package/dist/store-sqlite.d.ts +1 -1
  78. package/dist/store-sqlite.js +35 -20
  79. package/dist/store-sqlite.js.map +1 -1
  80. package/dist/{wire-rSUglYo8.js → wire-BKxH1vbP.js} +2 -2
  81. package/dist/{wire-rSUglYo8.js.map → wire-BKxH1vbP.js.map} +1 -1
  82. package/docs/agents/03-conversations.mdx +2 -2
  83. package/docs/index.mdx +3 -3
  84. package/docs/reference/02-server.mdx +12 -7
  85. package/docs/reference/04-ai.mdx +16 -7
  86. package/docs/reference/05-adapters.mdx +4 -4
  87. package/docs/server/01-handlers.mdx +1 -1
  88. package/docs/server/03-cancellation.mdx +3 -2
  89. package/docs/server/05-production.mdx +2 -1
  90. package/docs/server/06-guarantees.mdx +20 -11
  91. package/examples/playground/DEPLOY.md +2 -4
  92. package/examples/playground/app/a0/[appId]/page.tsx +2 -8
  93. package/examples/playground/app/a0/devtools.tsx +2 -8
  94. package/examples/playground/app/a0/server.ts +8 -19
  95. package/examples/playground/package.json +1 -1
  96. package/package.json +1 -1
  97. package/src/ai-agent.ts +10 -3
  98. package/src/ai-fx.ts +126 -47
  99. package/src/ai-pi.ts +74 -15
  100. package/src/ai-tool-input.ts +45 -0
  101. package/src/internal.ts +6 -0
  102. package/src/scheduler-qstash.ts +5 -5
  103. package/src/scheduler-vercel.ts +14 -15
  104. package/src/server.ts +58 -12
  105. package/src/store-memory.ts +50 -9
  106. package/src/store-postgres.ts +79 -28
  107. package/src/store-redis-core.ts +112 -31
  108. package/src/store-sqlite.ts +61 -28
  109. package/src/store.ts +22 -3
  110. package/dist/server-Dw_k_7kO.js.map +0 -1
  111. package/dist/server-En7cbi3v.d.ts.map +0 -1
  112. package/dist/session-clear-Bo-XTFEy.d.ts.map +0 -1
  113. package/dist/store-Djdv0bnZ.d.ts.map +0 -1
  114. package/dist/store-redis-notify-BRITti_o.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  import { c as ContractEvent, d as PresenceDefs, f as PresenceMap, g as WithPresence, m as PresenceSnapshot, o as AppendInput, p as PresencePatch, r as RegisteredReducer, s as Contract, t as Reducer, u as EventDefs } from "./reducer-CqA59Q6U.js";
2
- import { t as A2Store } from "./store-Djdv0bnZ.js";
3
- import { t as SessionCleared } from "./session-clear-Bo-XTFEy.js";
2
+ import { t as A2Store } from "./store-CyLUy86v.js";
3
+ import { t as SessionCleared } from "./session-clear-C-QwTXV1.js";
4
4
  import { i as A2Telemetry } from "./telemetry-Cyfqo6Qt.js";
5
5
  //#region src/session-socket.d.ts
6
6
  /**
@@ -180,9 +180,15 @@ type DeadLetter<D extends EventDefs> = ContractEvent<D> & {
180
180
  lane: string | null;
181
181
  /** Durable dispatch claims, including claims abandoned by hard kills. */
182
182
  attemptCount: number;
183
- /** Caught handler failures since the event was appended or last retried. */
183
+ /**
184
+ * Failed attempts since the event was appended or last retried: caught
185
+ * handler failures, and attempts that ended before they finished.
186
+ */
184
187
  failureCount: number;
185
- /** The last handler failure, stringified. */
188
+ /**
189
+ * The last error a handler threw, stringified; null when every failed
190
+ * attempt ended before it finished.
191
+ */
186
192
  lastError: string | null;
187
193
  failedAt: Date;
188
194
  };
@@ -377,4 +383,4 @@ type ServerOptions<D extends EventDefs, P extends PresenceDefs = Record<never, n
377
383
  declare function createServer<D extends EventDefs, P extends PresenceDefs = Record<never, never>, R extends RegisteredReducer<D, P> | undefined = RegisteredReducer<D, P> | undefined>(options: ServerOptions<D, P, R>): A2Server<D, P, R>;
378
384
  //#endregion
379
385
  export { ScheduledEvent as A, A2Socket as B, SessionRedriveResult as C, deliverSchedulerAppend as D, createServer as E, A2Operation as F, A2PushEvent as I, A2PushPresence as L, SchedulerClearTask as M, SchedulerDrainTask as N, deliverSchedulerClear as O, SchedulerTask as P, ServerFetchOptions as R, SessionRedriveOptions as S, StateOptions as T, SessionClearOptions as _, DrainableServer as a, SessionDispatch as b, HandlerContext as c, LaneContext as d, ScheduleDelay as f, SessionAppend as g, Session as h, DeadLetter as i, SchedulerAppendTask as j, handler as k, HandlerEntry as l, ServerOptions as m, A2Server as n, Handler as o, ScheduleTiming as p, AbortSpec as r, HandlerAppend as s, A2Scheduler as t, Lane as u, SessionClearResult as v, SessionSchedule as w, SessionPresence as x, SessionDeadLetters as y, UpgradeWebSocket as z };
380
- //# sourceMappingURL=server-En7cbi3v.d.ts.map
386
+ //# sourceMappingURL=server-DYAATFuT.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-DYAATFuT.d.ts","names":[],"sources":["../src/session-socket.ts","../src/server-fetch.ts","../src/scheduler-task.ts","../src/server.ts"],"mappings":"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"}
package/dist/server.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  import { c as ContractEvent, d as PresenceDefs, f as PresenceMap, m as PresenceSnapshot, o as AppendInput, p as PresencePatch, s as Contract, u as EventDefs } from "./reducer-CqA59Q6U.js";
2
- import { a as EventCause, c as PresenceRow, d as StoreStateRead, f as StoredEvent, i as Event, l as StoreAppendResult, n as AppendEvent, o as FailAttemptResult, r as Clock, s as IdSource, t as A2Store, u as StoreClaimAvailableResult } from "./store-Djdv0bnZ.js";
3
- import { A as ScheduledEvent, B as A2Socket, C as SessionRedriveResult, D as deliverSchedulerAppend, E as createServer, F as A2Operation, I as A2PushEvent, L as A2PushPresence, M as SchedulerClearTask, N as SchedulerDrainTask, O as deliverSchedulerClear, P as SchedulerTask, R as ServerFetchOptions, S as SessionRedriveOptions, T as StateOptions, _ as SessionClearOptions, a as DrainableServer, b as SessionDispatch, c as HandlerContext, d as LaneContext, f as ScheduleDelay, g as SessionAppend, h as Session, i as DeadLetter, j as SchedulerAppendTask, k as handler, l as HandlerEntry, m as ServerOptions, n as A2Server, o as Handler, p as ScheduleTiming, r as AbortSpec, s as HandlerAppend, t as A2Scheduler, u as Lane, v as SessionClearResult, w as SessionSchedule, x as SessionPresence, y as SessionDeadLetters, z as UpgradeWebSocket } from "./server-En7cbi3v.js";
2
+ import { a as EventCause, c as PresenceRow, d as StoreStateRead, f as StoredEvent, i as Event, l as StoreAppendResult, n as AppendEvent, o as FailAttemptResult, r as Clock, s as IdSource, t as A2Store, u as StoreClaimAvailableResult } from "./store-CyLUy86v.js";
3
+ import { A as ScheduledEvent, B as A2Socket, C as SessionRedriveResult, D as deliverSchedulerAppend, E as createServer, F as A2Operation, I as A2PushEvent, L as A2PushPresence, M as SchedulerClearTask, N as SchedulerDrainTask, O as deliverSchedulerClear, P as SchedulerTask, R as ServerFetchOptions, S as SessionRedriveOptions, T as StateOptions, _ as SessionClearOptions, a as DrainableServer, b as SessionDispatch, c as HandlerContext, d as LaneContext, f as ScheduleDelay, g as SessionAppend, h as Session, i as DeadLetter, j as SchedulerAppendTask, k as handler, l as HandlerEntry, m as ServerOptions, n as A2Server, o as Handler, p as ScheduleTiming, r as AbortSpec, s as HandlerAppend, t as A2Scheduler, u as Lane, v as SessionClearResult, w as SessionSchedule, x as SessionPresence, y as SessionDeadLetters, z as UpgradeWebSocket } from "./server-DYAATFuT.js";
4
4
  export { type A2Operation, type A2PushEvent, type A2PushPresence, A2Scheduler, A2Server, type A2Socket, type A2Store, AbortSpec, type AppendEvent, type AppendInput, type Clock, type Contract, type ContractEvent, DeadLetter, DrainableServer, type Event, type EventCause, type EventDefs, type FailAttemptResult, Handler, HandlerAppend, HandlerContext, HandlerEntry, type IdSource, Lane, LaneContext, type PresenceDefs, type PresenceMap, type PresencePatch, type PresenceRow, type PresenceSnapshot, ScheduleDelay, ScheduleTiming, type ScheduledEvent, type SchedulerAppendTask, type SchedulerClearTask, type SchedulerDrainTask, type SchedulerTask, type ServerFetchOptions, ServerOptions, Session, SessionAppend, SessionClearOptions, SessionClearResult, SessionDeadLetters, SessionDispatch, SessionPresence, SessionRedriveOptions, SessionRedriveResult, SessionSchedule, StateOptions, type StoreAppendResult, type StoreClaimAvailableResult, type StoreStateRead, type StoredEvent, type UpgradeWebSocket, createServer, deliverSchedulerAppend, deliverSchedulerClear, handler };
package/dist/server.js CHANGED
@@ -1,2 +1,2 @@
1
- import { i as handler, n as deliverSchedulerAppend, r as deliverSchedulerClear, t as createServer } from "./server-Dw_k_7kO.js";
1
+ import { i as handler, n as deliverSchedulerAppend, r as deliverSchedulerClear, t as createServer } from "./server-D-Y4pqwu.js";
2
2
  export { createServer, deliverSchedulerAppend, deliverSchedulerClear, handler };
@@ -1,4 +1,4 @@
1
- import { i as Event } from "./store-Djdv0bnZ.js";
1
+ import { i as Event } from "./store-CyLUy86v.js";
2
2
  //#region src/session-clear.d.ts
3
3
  /** Reserved type of the marker a clear appends. */
4
4
  declare const CLEAR_EVENT_TYPE = "a2.cleared";
@@ -9,4 +9,4 @@ type SessionCleared = Event & {
9
9
  };
10
10
  //#endregion
11
11
  export { SessionCleared as t };
12
- //# sourceMappingURL=session-clear-Bo-XTFEy.d.ts.map
12
+ //# sourceMappingURL=session-clear-C-QwTXV1.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-clear-C-QwTXV1.d.ts","names":[],"sources":["../src/session-clear.ts"],"mappings":";;;cAOa;;KAGD,iBAAiB;EAC3B,aAAa;EACb"}
@@ -41,9 +41,15 @@ type StoredEvent = Event & {
41
41
  attemptCount: number;
42
42
  /** Current dispatch holder; null when the event is not claimed. */
43
43
  claimHolder: string | null;
44
- /** Adapter clock expiry for the current dispatch claim. */
44
+ /**
45
+ * Adapter clock expiry for the current dispatch claim, or, with no holder,
46
+ * the end of a failed attempt's retry hold.
47
+ */
45
48
  claimExpiresAt: Date | null;
46
- /** Caught handler failures. This alone drives dead-lettering. */
49
+ /**
50
+ * Failed attempts: caught handler failures, and lapsed claims a later claim
51
+ * took over. This alone drives dead-lettering.
52
+ */
47
53
  failureCount: number;
48
54
  /** Adapter clock time recorded by the most recent caught handler failure. */
49
55
  lastFailedAt: Date | null;
@@ -271,6 +277,15 @@ interface A2Store {
271
277
  ttlMs: number;
272
278
  expiresAtMs?: number;
273
279
  excludeIndexes?: readonly number[];
280
+ /**
281
+ * Taking over a lapsed claim (one whose holder is still recorded, never
282
+ * completed or failed) adds one to `failureCount`. When that reaches
283
+ * `maxFailures`, the event dead-letters instead of being claimed: it
284
+ * comes back in `events` with `failedAt` set and no claim. Its
285
+ * `attemptCount` still advances, fencing the lapsed attempt, and its
286
+ * `lastFailedAttempt` is unchanged.
287
+ */
288
+ maxFailures?: number;
274
289
  }): Promise<StoreClaimAvailableResult>;
275
290
  /**
276
291
  * Renews the listed live claims still owned by `holder`. Each listed claim
@@ -305,7 +320,10 @@ interface A2Store {
305
320
  /**
306
321
  * Atomically records a caught failure for one claimed attempt. A stale
307
322
  * attempt cannot poison a processed event or a newer dispatch. Accepted
308
- * failures record the operation's clock time.
323
+ * failures record the operation's clock time. A failure that does not
324
+ * dead-letter releases the claim and, with `retryAfterMs`, keeps the event
325
+ * unclaimable for that long: its claim expiry is set with no holder, so
326
+ * `claimAvailable` reports it `busy` until then.
309
327
  */
310
328
  failAttempt(options: {
311
329
  sessionId: string;
@@ -313,6 +331,7 @@ interface A2Store {
313
331
  attempt: number;
314
332
  error: string;
315
333
  maxFailures: number;
334
+ retryAfterMs?: number;
316
335
  }): Promise<FailAttemptResult>;
317
336
  /**
318
337
  * Reads a reducer snapshot and its event tail as one consistent adapter
@@ -382,4 +401,4 @@ interface A2Store {
382
401
  }
383
402
  //#endregion
384
403
  export { EventCause as a, PresenceRow as c, StoreStateRead as d, StoredEvent as f, Event as i, StoreAppendResult as l, AppendEvent as n, FailAttemptResult as o, Clock as r, IdSource as s, A2Store as t, StoreClaimAvailableResult as u };
385
- //# sourceMappingURL=store-Djdv0bnZ.d.ts.map
404
+ //# sourceMappingURL=store-CyLUy86v.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store-CyLUy86v.d.ts","names":[],"sources":["../src/store.ts"],"mappings":";;;KAaY;EACV;EACA;EACA;;EAEA;EACA;EACA,WAAW;;;KAID;EACV;EACA;;EAEA;;;;;;;KAQU,cAAc;;EAExB,OAAO;;EAEP;;EAEA,aAAa;;EAEb;;EAEA;;EAEA,gBAAgB;;EAEhB,eAAe;;EAEf;;EAEA;;;;;EAKA,gBAAgB;;;;;EAKhB;;EAEA,cAAc;;EAEd;;EAEA;;EAEA,UAAU;;EAEV;;;;;;;;;KAUU;EACV;EACA;EACA;EACA;EACA,IAAI;EACJ,WAAW;;;KAID;;EAEV;;EAEA;IAAY;IAAe;;;EAE3B,QAAQ;;EAER;;KAGU;EACV;EACA;;EAEA;;KAGU;EACV;EACA;EACA;;;KAGU;EACN;EAAoB,QAAQ;;EAC5B;EAAiB,SAAS;;EAC1B;;;KAGM;EACR;EAAsB,QAAQ;;EAAoB;;;KAG1C;;EAEV;;EAEA;;;KAIU;EACV;EACA;;;KAIU;EACV;EACA;;EAEA;;EAEA,QAAQ;;EAER;;EAEA;;;KAIU,gBAAgB;EAAgB;;;KAGhC;EACV,QAAQ;;EAER;;KAGU;EACV;EACA;;EAEA,QAAQ;;KAGE;EACV;;EAEA;;EAEA;;KAGU;EAAuB;EAAiB;;KAExC;EACV;EACA;;EAEA;;KAGU;;EAEV;;EAEA;;;;;;;KAQU;EACV,OAAO;;;KAIG;UAQK;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4Bf,OACE,mBACA,QAAQ,eACR;IAAY;MACX,QAAQ;;;;;;;EAQX,OAAO,SAAS,oBAAoB,QAAQ;;;;;;EAO5C,SAAS,oBAAoB,QAAQ;;;;;EAMrC,aAAa,oBAAoB,QAAQ;;;;;;;;;;;;EAazC,SAAS,SAAS,sBAAsB,QAAQ;;EAGhD,KACE,mBACA;IAAS;IAAqB;MAC7B,QAAQ;;EAGX,aACE,mBACA;IAAS;IAAqB;MAC7B,QAAQ;;;;;;;;EASX,eAAe;IACb;IACA;IACA;IACA;IACA;;;;;;;;;IASA;MACE,QAAQ;;;;;;;;;;EAWZ,YAAY;IACV;IACA;IACA;MAAmB;MAAe;;IAClC;IACA;MACE,QAAQ;;;;;;EAOZ,gBAAgB;IACd;IACA;IACA;IACA,QAAQ;MACN,QAAQ;;;;;;;;;EAUZ,YAAY;IACV;IACA;IACA;IACA;IACA;IACA;MACE,QAAQ;;;;;;;;EASZ,UACE,mBACA,qBACA;IAAY;IAAuB;MAClC,QAAQ;;;;;;;;EASX,YACE,mBAAmB,yBACnB,sBACC,QAAQ;;;;;;;EAQX,aACE,mBACA,qBACA,oBAAoB,uBACnB;;;;;;;EAQH;;;;;;;;;IASE,IACE,YACA,qBACA,QAAQ,gCACR;MAAQ;MAAc,IAAI;MAAM;QAC/B;;IAGH,KAAK,aAAa,QAAQ;;;;;;IAO1B,WAAW,YAAY,UAAU,OAAO;;;;;;;;;EAU1C,OACE,mBACA;IAAS;MACR,cAAc"}
@@ -1 +1 @@
1
- {"version":3,"file":"store-N8PXxDAS.js","names":[],"sources":["../src/store.ts"],"sourcesContent":["/**\n * The A2Store interface — the storage contract every store backend\n * implements. See specs/a2-implementation.md §2–3.\n *\n * This is the whole storage contract: append, read, dispatch claims,\n * failure markers, snapshots, and the live stream. The scheduler\n * needs nothing extra — the armed queue message is its own state, and\n * the store is the only thing it consults.\n */\n\nimport type { PresencePatch } from './contract.ts'\n\n/** A stored event, as the public API exposes it. */\nexport type Event = {\n id: string\n type: string\n payload: unknown\n /** Position in the session's event log, from 1. */\n index: number\n sessionId: string\n createdAt: Date\n}\n\n/** The handler dispatch whose append first persisted a child event. */\nexport type EventCause = {\n index: number\n attempt: number\n /** Size of one named handler append, used to reject truncated retries. */\n batchSize?: number\n}\n\n/**\n * What the store persists: immutable event history, including its causal edge,\n * plus derived dispatch and failure bookkeeping. The bookkeeping is disposable;\n * the event and its cause are not.\n */\nexport type StoredEvent = Event & {\n /** Same-session handler dispatch that appended this event; null means root. */\n cause: EventCause | null\n /** Session-scoped serial execution key resolved when the event is appended. */\n lane: string | null\n /** Adapter clock time recorded by append settlement, completion, or manual skip; null while pending. */\n processedAt: Date | null\n /** Dispatch attempt that completed this event; null without dispatch or while pending. */\n processedByAttempt: number | null\n /** Exact ordered child ids atomically returned by the completing attempt. */\n returnedEventIds: string[] | null\n /** Adapter clock time recorded by the first durable dispatch claim. */\n firstClaimedAt: Date | null\n /** Adapter clock time recorded by the most recent durable dispatch claim. */\n lastClaimedAt: Date | null\n /** Durable dispatch claims, including claims abandoned by hard kills. */\n attemptCount: number\n /** Current dispatch holder; null when the event is not claimed. */\n claimHolder: string | null\n /** Adapter clock expiry for the current dispatch claim. */\n claimExpiresAt: Date | null\n /** Caught handler failures. This alone drives dead-lettering. */\n failureCount: number\n /** Adapter clock time recorded by the most recent caught handler failure. */\n lastFailedAt: Date | null\n /** Dispatch attempt that produced the most recent caught handler failure. */\n lastFailedAttempt: number | null\n /** The last handler failure, stringified. */\n lastError: string | null\n /** Adapter clock time recorded when dead-lettered; null otherwise. */\n failedAt: Date | null\n /** Latest clear marker, on claimed events of a cleared session. */\n clearIndex?: number\n}\n\n/**\n * One live presence value, as `A2Store.presence.read` returns it. The\n * row is the LWW unit — one participant's one field. `at` is the\n * sender's stamp, the LWW comparator. `expiresAt` is the storage's\n * own clock at the applied set plus its `ttlMs` — never derived from\n * the sender stamp; a row is live strictly before it.\n */\nexport type PresenceRow = {\n participant: string\n field: string\n value: unknown\n seen: number\n at: Date\n expiresAt: Date\n}\n\n/** One consistent cache-plus-tail read for a reducer fold. */\nexport type StoreStateRead = {\n /** The current head checkpoint, even when an older historical snapshot is selected. */\n headIndex: number | null\n /** The greatest cached fold at or before the requested snapshot frontier. */\n snapshot: { index: number; state: unknown } | null\n /** Immutable events strictly after `snapshot.index`, or the full log on a miss. */\n events: Event[]\n /** Latest clear marker; omitted when the session was never cleared. */\n clearIndex?: number\n}\n\nexport type StoreSnapshotWrite = {\n index: number\n state: unknown\n /** Unfinished trigger events that durably retain this exact checkpoint. */\n pinEventIndexes?: readonly number[]\n}\n\nexport type StoreStateReadRequest = {\n sessionId: string\n throughIndex?: number\n snapshotThroughIndex?: number\n}\n/** The result of atomically claiming every currently eligible event. */\nexport type StoreClaimAvailableResult =\n | { outcome: 'claimed'; events: StoredEvent[] }\n | { outcome: 'busy'; retryAt: Date }\n | { outcome: 'settled' }\n\n/** A completion may lose to a newer claim or an earlier completion. */\nexport type CompleteAttemptResult =\n { outcome: 'completed'; events: StoredEvent[] } | { outcome: 'superseded' }\n\n/** The result of one claim-renewal heartbeat, both lists in append order. */\nexport type RenewClaimsResult = {\n /** Listed claims that remain owned by the holder. */\n renewed: number[]\n /** Listed claims whose event a newer attempt has durably taken. */\n superseded: number[]\n}\n\n/** The result of atomically recording a caught handler failure. */\nexport type FailAttemptResult = {\n outcome: 'failed' | 'dead_lettered' | 'superseded'\n failureCount: number\n}\n\n/** Input to `A2Store.append` — already validated by the machine. */\nexport type AppendEvent = {\n type: string\n payload: unknown\n /** Caller-supplied idempotency key; generated when absent. */\n id?: string\n /** Internal causal edge supplied atomically by handler `session.append`. */\n cause?: EventCause\n /** Session-scoped serial execution key resolved before persistence. */\n lane?: string\n /** Internal hint: settle this event in the append transaction; no handler is registered. */\n settled?: true\n}\n\n/** A handler-returned event with the deterministic id retries require. */\nexport type ReturnedEvent = AppendEvent & { id: string }\n\n/** The rows written by an append and the session's pending state. */\nexport type StoreAppendResult = {\n events: StoredEvent[]\n /** Whether the session contains an event without a completion marker. */\n hasPending: boolean\n}\n\nexport type StoreClearOptions = {\n sessionId: string\n ifLastIndex?: number\n /** The clearing handler's dispatch, fenced like a handler append. */\n cause?: EventCause\n}\n\nexport type StoreClearResult = {\n cleared: boolean\n /** The head after the operation. */\n index: number\n /** The latest clear marker after the operation, or 0. */\n clearIndex: number\n}\n\nexport type StoreReclaimResult = { deleted: number; done: boolean }\n\nexport type StoreRedriveOptions = {\n sessionId: string\n index: number\n /** `retry` clears the dead letter; `skip` settles it without a handler. */\n action: 'retry' | 'skip'\n}\n\nexport type StoreRedriveResult = {\n /** Whether the event was dead-lettered and this operation resolved it. */\n redriven: boolean\n /** Whether the session contains an event without a completion marker. */\n hasPending: boolean\n}\n\n/**\n * An injectable clock. Adapters take one so tests can drive claim\n * expiry, failure timestamps, and (later) stuck-session detection\n * deterministically — against real storage, no mocking.\n */\nexport type Clock = {\n now(): Date\n}\n\n/** An injectable id source for generated event ids. */\nexport type IdSource = () => string\n\nexport const SYSTEM_CLOCK: Clock = {\n now: () => new Date(),\n}\n\nexport const RANDOM_IDS: IdSource = () => crypto.randomUUID()\n\nexport interface A2Store {\n /**\n * Accepts a batch; the batch is atomic — one transaction, consecutive\n * `index`es, all-or-nothing. The idempotency key covers the whole\n * operation, not each item: if *every* event's `id` already exists in\n * this session, this is a retry of a committed batch whose ack was\n * lost — return the existing rows as success. If only *some* ids\n * exist, the caller mixed an already-sent batch with fresh events —\n * always a caller bug — so throw `A2Error('PARTIAL_DUPLICATE_BATCH')`.\n * Events carrying `settled: true` get `processedAt` in this same atomic\n * operation, with no dispatch claim or `processedByAttempt`. The result's\n * `hasPending` reflects the whole session in the same atomic operation,\n * including older events and idempotent retries.\n *\n * An event carrying `cause` is a handler append, fenced by attempt\n * currency: accept it only while `cause.attempt` is still the parent\n * event's latest attempt and the parent is not dead-lettered; otherwise\n * throw `A2Error('SUPERSEDED_ATTEMPT')` and write nothing. The check is\n * part of this atomic operation and must serialize against a concurrent\n * `claimAvailable` — an unlocked read of the parent admits write skew.\n * The idempotent-replay path runs first, so a batch whose ids all exist\n * replays regardless of the current attempt.\n *\n * Clearing stores (a2-implementation.md §17.2) fence one level earlier:\n * a `cause` at or below the latest clear marker throws\n * `SUPERSEDED_ATTEMPT`, an `originIndex` there throws `SESSION_CLEARED`,\n * and ids whose rows lie below the marker are free to reuse.\n */\n append(\n sessionId: string,\n events: AppendEvent[],\n options?: { originIndex?: number },\n ): Promise<StoreAppendResult>\n\n /**\n * Optional with `reclaim`. Serialized with `append`: checks\n * `ifLastIndex` against the head and the latest marker, then appends a\n * settled clear marker at the next index without touching existing\n * rows. Afterwards every event at or below the marker is superseded.\n */\n clear?(options: StoreClearOptions): Promise<StoreClearResult>\n\n /**\n * Deletes one bounded batch of rows below the latest clear marker, with\n * their bookkeeping, id records, and cached folds. `done` once nothing\n * remains below it. Never waits on a lock that other operations hold.\n */\n reclaim?(sessionId: string): Promise<StoreReclaimResult>\n\n /**\n * Optional with `redrive`. The session's dead-lettered events above the\n * latest clear marker, oldest first.\n */\n deadLetters?(sessionId: string): Promise<StoredEvent[]>\n\n /**\n * Optional with `deadLetters`. Atomically resolves one dead-lettered event\n * above the latest clear marker; any other event is untouched and reports\n * `redriven: false`. `retry` clears `failedAt` and `failureCount`, so the\n * event is claimable again with a fresh failure budget, keeping its claim\n * history and last failure. `skip` records `processedAt` with no\n * `processedByAttempt` or `returnedEventIds` and exposes the next event in\n * its lane. Both serialize with `claimAvailable` and the handler-append\n * parent fence; `skip` also serializes with lane promotion in `append` and\n * `completeAttempt`. `hasPending` is read in the same step.\n */\n redrive?(options: StoreRedriveOptions): Promise<StoreRedriveResult>\n\n /** Events for one session, oldest first. Bounds form `(afterIndex, throughIndex]`. */\n read(\n sessionId: string,\n opts?: { afterIndex?: number; throughIndex?: number },\n ): Promise<StoredEvent[]>\n\n /** Public history without dispatch metadata; core falls back to read when absent. */\n readHistory?(\n sessionId: string,\n opts?: { afterIndex?: number; throughIndex?: number },\n ): Promise<Event[]>\n\n /**\n * Atomically claims every eligible pending event. Unlaned events are all\n * independently eligible. Within a lane, only the lowest-index unfinished\n * event is eligible. A live claim produces `busy` only when it is the sole\n * remaining obstacle to actionable work. Claimed events are returned in event-log\n * order. Excluded rows remain lane barriers.\n */\n claimAvailable(options: {\n sessionId: string\n holder: string\n ttlMs: number\n expiresAtMs?: number\n excludeIndexes?: readonly number[]\n }): Promise<StoreClaimAvailableResult>\n\n /**\n * Renews the listed live claims still owned by `holder`. Each listed claim\n * carries the attempt ordinal the holder owns. `renewed` lists the claims\n * that remain owned after the operation; `superseded` lists the claims\n * whose event's `attemptCount` has durably passed the listed attempt. An\n * expired claim no successor has taken appears in neither list — its\n * attempt may still complete (`completeAttempt` is the fence), so it is\n * not reported as lost. Renewal never revives an expired claim.\n */\n renewClaims(options: {\n sessionId: string\n holder: string\n claims: readonly { index: number; attempt: number }[]\n ttlMs: number\n expiresAtMs?: number\n }): Promise<RenewClaimsResult>\n\n /**\n * Atomically completes one current attempt and appends its returned events.\n * Retrying a committed completion with the same attempt and deterministic\n * child ids returns the existing children. A stale attempt never appends.\n */\n completeAttempt(options: {\n sessionId: string\n index: number\n attempt: number\n events: ReturnedEvent[]\n }): Promise<CompleteAttemptResult>\n\n /**\n * Atomically records a caught failure for one claimed attempt. A stale\n * attempt cannot poison a processed event or a newer dispatch. Accepted\n * failures record the operation's clock time.\n */\n failAttempt(options: {\n sessionId: string\n index: number\n attempt: number\n error: string\n maxFailures: number\n }): Promise<FailAttemptResult>\n\n /**\n * Reads a reducer snapshot and its event tail as one consistent adapter\n * operation. On a cache miss, `snapshot` is null and `events` is the full\n * log. The snapshot is untrusted; core may reject it and issue a full\n * `read()` when its state schema no longer accepts the cached value.\n * Operational failures propagate without falling back to a full-log read.\n */\n readState(\n sessionId: string,\n reducerName: string,\n options?: { throughIndex?: number; snapshotThroughIndex?: number },\n ): Promise<StoreStateRead>\n\n /**\n * Optional batched `readState` — one consistent snapshot-plus-tail read\n * per session id, aligned positionally with the input (duplicates\n * allowed). Each element has its own frontier; the batch makes no\n * cross-session consistency claim. Core falls back to parallel\n * `readState` calls when absent.\n */\n readStates?(\n requests: readonly StoreStateReadRequest[],\n reducerName: string,\n ): Promise<StoreStateRead[]>\n\n /**\n * Atomically writes disposable reducer checkpoints. The greatest index\n * advances the head cache. Older checkpoints survive only when at least one\n * listed trigger event is still unfinished; completion and dead-lettering\n * release that event's pins and collect unreferenced historical checkpoints.\n */\n putSnapshots(\n sessionId: string,\n reducerName: string,\n snapshots: readonly StoreSnapshotWrite[],\n ): Promise<void>\n\n /**\n * Optional ephemeral-plane capability (specs/a2-implementation.md\n * §15.1) — optional like snapshots are. Values arrive already\n * validated by core; adapters store them opaquely. Presence never\n * touches the event log: no index, no history row, no recovery arm.\n */\n presence?: {\n /**\n * Field-wise last-writer-wins merge of one participant's values:\n * a field whose existing row has a strictly newer `at` (the\n * sender's stamp) is left untouched; `null` deletes the row. Every\n * applied write refreshes that field's expiry to the storage's own\n * clock plus `ttlMs` — the sender stamp orders writes but never\n * anchors their lifetime.\n */\n set(\n ns: string,\n participant: string,\n values: Record<string, unknown | null>,\n meta: { seen: number; at: Date; ttlMs: number },\n ): Promise<void>\n\n /** The current map, pruned of rows at or past their `expiresAt`. */\n read(ns: string): Promise<PresenceRow[]>\n\n /**\n * Adapter-managed patch delivery. Without it, live feeds re-read\n * presence on their poll cadence. HTTP Redis uses adaptive polling\n * here when its endpoint does not support subscriptions.\n */\n subscribe?(ns: string, onPatch: (patch: PresencePatch) => void): () => void\n }\n\n /**\n * A live feed of one session's events, starting after `startAfter`\n * (exclusive). Transport is the backend's choice — in-process pub/sub,\n * polling, LISTEN/NOTIFY — callers never branch on which. The iterable\n * ends when the consumer calls `return()` (e.g. a disconnecting SSE\n * client) and must deliver events appended after subscription.\n */\n stream(\n sessionId: string,\n opts?: { startAfter?: number },\n ): AsyncIterable<Event>\n}\n"],"mappings":";AA0MA,MAAa,eAAsB,EACjC,2BAAW,IAAI,KAAK,EACtB;AAEA,MAAa,mBAA6B,OAAO,WAAW"}
1
+ {"version":3,"file":"store-N8PXxDAS.js","names":[],"sources":["../src/store.ts"],"sourcesContent":["/**\n * The A2Store interface — the storage contract every store backend\n * implements. See specs/a2-implementation.md §2–3.\n *\n * This is the whole storage contract: append, read, dispatch claims,\n * failure markers, snapshots, and the live stream. The scheduler\n * needs nothing extra — the armed queue message is its own state, and\n * the store is the only thing it consults.\n */\n\nimport type { PresencePatch } from './contract.ts'\n\n/** A stored event, as the public API exposes it. */\nexport type Event = {\n id: string\n type: string\n payload: unknown\n /** Position in the session's event log, from 1. */\n index: number\n sessionId: string\n createdAt: Date\n}\n\n/** The handler dispatch whose append first persisted a child event. */\nexport type EventCause = {\n index: number\n attempt: number\n /** Size of one named handler append, used to reject truncated retries. */\n batchSize?: number\n}\n\n/**\n * What the store persists: immutable event history, including its causal edge,\n * plus derived dispatch and failure bookkeeping. The bookkeeping is disposable;\n * the event and its cause are not.\n */\nexport type StoredEvent = Event & {\n /** Same-session handler dispatch that appended this event; null means root. */\n cause: EventCause | null\n /** Session-scoped serial execution key resolved when the event is appended. */\n lane: string | null\n /** Adapter clock time recorded by append settlement, completion, or manual skip; null while pending. */\n processedAt: Date | null\n /** Dispatch attempt that completed this event; null without dispatch or while pending. */\n processedByAttempt: number | null\n /** Exact ordered child ids atomically returned by the completing attempt. */\n returnedEventIds: string[] | null\n /** Adapter clock time recorded by the first durable dispatch claim. */\n firstClaimedAt: Date | null\n /** Adapter clock time recorded by the most recent durable dispatch claim. */\n lastClaimedAt: Date | null\n /** Durable dispatch claims, including claims abandoned by hard kills. */\n attemptCount: number\n /** Current dispatch holder; null when the event is not claimed. */\n claimHolder: string | null\n /**\n * Adapter clock expiry for the current dispatch claim, or, with no holder,\n * the end of a failed attempt's retry hold.\n */\n claimExpiresAt: Date | null\n /**\n * Failed attempts: caught handler failures, and lapsed claims a later claim\n * took over. This alone drives dead-lettering.\n */\n failureCount: number\n /** Adapter clock time recorded by the most recent caught handler failure. */\n lastFailedAt: Date | null\n /** Dispatch attempt that produced the most recent caught handler failure. */\n lastFailedAttempt: number | null\n /** The last handler failure, stringified. */\n lastError: string | null\n /** Adapter clock time recorded when dead-lettered; null otherwise. */\n failedAt: Date | null\n /** Latest clear marker, on claimed events of a cleared session. */\n clearIndex?: number\n}\n\n/**\n * One live presence value, as `A2Store.presence.read` returns it. The\n * row is the LWW unit — one participant's one field. `at` is the\n * sender's stamp, the LWW comparator. `expiresAt` is the storage's\n * own clock at the applied set plus its `ttlMs` — never derived from\n * the sender stamp; a row is live strictly before it.\n */\nexport type PresenceRow = {\n participant: string\n field: string\n value: unknown\n seen: number\n at: Date\n expiresAt: Date\n}\n\n/** One consistent cache-plus-tail read for a reducer fold. */\nexport type StoreStateRead = {\n /** The current head checkpoint, even when an older historical snapshot is selected. */\n headIndex: number | null\n /** The greatest cached fold at or before the requested snapshot frontier. */\n snapshot: { index: number; state: unknown } | null\n /** Immutable events strictly after `snapshot.index`, or the full log on a miss. */\n events: Event[]\n /** Latest clear marker; omitted when the session was never cleared. */\n clearIndex?: number\n}\n\nexport type StoreSnapshotWrite = {\n index: number\n state: unknown\n /** Unfinished trigger events that durably retain this exact checkpoint. */\n pinEventIndexes?: readonly number[]\n}\n\nexport type StoreStateReadRequest = {\n sessionId: string\n throughIndex?: number\n snapshotThroughIndex?: number\n}\n/** The result of atomically claiming every currently eligible event. */\nexport type StoreClaimAvailableResult =\n | { outcome: 'claimed'; events: StoredEvent[] }\n | { outcome: 'busy'; retryAt: Date }\n | { outcome: 'settled' }\n\n/** A completion may lose to a newer claim or an earlier completion. */\nexport type CompleteAttemptResult =\n { outcome: 'completed'; events: StoredEvent[] } | { outcome: 'superseded' }\n\n/** The result of one claim-renewal heartbeat, both lists in append order. */\nexport type RenewClaimsResult = {\n /** Listed claims that remain owned by the holder. */\n renewed: number[]\n /** Listed claims whose event a newer attempt has durably taken. */\n superseded: number[]\n}\n\n/** The result of atomically recording a caught handler failure. */\nexport type FailAttemptResult = {\n outcome: 'failed' | 'dead_lettered' | 'superseded'\n failureCount: number\n}\n\n/** Input to `A2Store.append` — already validated by the machine. */\nexport type AppendEvent = {\n type: string\n payload: unknown\n /** Caller-supplied idempotency key; generated when absent. */\n id?: string\n /** Internal causal edge supplied atomically by handler `session.append`. */\n cause?: EventCause\n /** Session-scoped serial execution key resolved before persistence. */\n lane?: string\n /** Internal hint: settle this event in the append transaction; no handler is registered. */\n settled?: true\n}\n\n/** A handler-returned event with the deterministic id retries require. */\nexport type ReturnedEvent = AppendEvent & { id: string }\n\n/** The rows written by an append and the session's pending state. */\nexport type StoreAppendResult = {\n events: StoredEvent[]\n /** Whether the session contains an event without a completion marker. */\n hasPending: boolean\n}\n\nexport type StoreClearOptions = {\n sessionId: string\n ifLastIndex?: number\n /** The clearing handler's dispatch, fenced like a handler append. */\n cause?: EventCause\n}\n\nexport type StoreClearResult = {\n cleared: boolean\n /** The head after the operation. */\n index: number\n /** The latest clear marker after the operation, or 0. */\n clearIndex: number\n}\n\nexport type StoreReclaimResult = { deleted: number; done: boolean }\n\nexport type StoreRedriveOptions = {\n sessionId: string\n index: number\n /** `retry` clears the dead letter; `skip` settles it without a handler. */\n action: 'retry' | 'skip'\n}\n\nexport type StoreRedriveResult = {\n /** Whether the event was dead-lettered and this operation resolved it. */\n redriven: boolean\n /** Whether the session contains an event without a completion marker. */\n hasPending: boolean\n}\n\n/**\n * An injectable clock. Adapters take one so tests can drive claim\n * expiry, failure timestamps, and (later) stuck-session detection\n * deterministically — against real storage, no mocking.\n */\nexport type Clock = {\n now(): Date\n}\n\n/** An injectable id source for generated event ids. */\nexport type IdSource = () => string\n\nexport const SYSTEM_CLOCK: Clock = {\n now: () => new Date(),\n}\n\nexport const RANDOM_IDS: IdSource = () => crypto.randomUUID()\n\nexport interface A2Store {\n /**\n * Accepts a batch; the batch is atomic — one transaction, consecutive\n * `index`es, all-or-nothing. The idempotency key covers the whole\n * operation, not each item: if *every* event's `id` already exists in\n * this session, this is a retry of a committed batch whose ack was\n * lost — return the existing rows as success. If only *some* ids\n * exist, the caller mixed an already-sent batch with fresh events —\n * always a caller bug — so throw `A2Error('PARTIAL_DUPLICATE_BATCH')`.\n * Events carrying `settled: true` get `processedAt` in this same atomic\n * operation, with no dispatch claim or `processedByAttempt`. The result's\n * `hasPending` reflects the whole session in the same atomic operation,\n * including older events and idempotent retries.\n *\n * An event carrying `cause` is a handler append, fenced by attempt\n * currency: accept it only while `cause.attempt` is still the parent\n * event's latest attempt and the parent is not dead-lettered; otherwise\n * throw `A2Error('SUPERSEDED_ATTEMPT')` and write nothing. The check is\n * part of this atomic operation and must serialize against a concurrent\n * `claimAvailable` — an unlocked read of the parent admits write skew.\n * The idempotent-replay path runs first, so a batch whose ids all exist\n * replays regardless of the current attempt.\n *\n * Clearing stores (a2-implementation.md §17.2) fence one level earlier:\n * a `cause` at or below the latest clear marker throws\n * `SUPERSEDED_ATTEMPT`, an `originIndex` there throws `SESSION_CLEARED`,\n * and ids whose rows lie below the marker are free to reuse.\n */\n append(\n sessionId: string,\n events: AppendEvent[],\n options?: { originIndex?: number },\n ): Promise<StoreAppendResult>\n\n /**\n * Optional with `reclaim`. Serialized with `append`: checks\n * `ifLastIndex` against the head and the latest marker, then appends a\n * settled clear marker at the next index without touching existing\n * rows. Afterwards every event at or below the marker is superseded.\n */\n clear?(options: StoreClearOptions): Promise<StoreClearResult>\n\n /**\n * Deletes one bounded batch of rows below the latest clear marker, with\n * their bookkeeping, id records, and cached folds. `done` once nothing\n * remains below it. Never waits on a lock that other operations hold.\n */\n reclaim?(sessionId: string): Promise<StoreReclaimResult>\n\n /**\n * Optional with `redrive`. The session's dead-lettered events above the\n * latest clear marker, oldest first.\n */\n deadLetters?(sessionId: string): Promise<StoredEvent[]>\n\n /**\n * Optional with `deadLetters`. Atomically resolves one dead-lettered event\n * above the latest clear marker; any other event is untouched and reports\n * `redriven: false`. `retry` clears `failedAt` and `failureCount`, so the\n * event is claimable again with a fresh failure budget, keeping its claim\n * history and last failure. `skip` records `processedAt` with no\n * `processedByAttempt` or `returnedEventIds` and exposes the next event in\n * its lane. Both serialize with `claimAvailable` and the handler-append\n * parent fence; `skip` also serializes with lane promotion in `append` and\n * `completeAttempt`. `hasPending` is read in the same step.\n */\n redrive?(options: StoreRedriveOptions): Promise<StoreRedriveResult>\n\n /** Events for one session, oldest first. Bounds form `(afterIndex, throughIndex]`. */\n read(\n sessionId: string,\n opts?: { afterIndex?: number; throughIndex?: number },\n ): Promise<StoredEvent[]>\n\n /** Public history without dispatch metadata; core falls back to read when absent. */\n readHistory?(\n sessionId: string,\n opts?: { afterIndex?: number; throughIndex?: number },\n ): Promise<Event[]>\n\n /**\n * Atomically claims every eligible pending event. Unlaned events are all\n * independently eligible. Within a lane, only the lowest-index unfinished\n * event is eligible. A live claim produces `busy` only when it is the sole\n * remaining obstacle to actionable work. Claimed events are returned in event-log\n * order. Excluded rows remain lane barriers.\n */\n claimAvailable(options: {\n sessionId: string\n holder: string\n ttlMs: number\n expiresAtMs?: number\n excludeIndexes?: readonly number[]\n /**\n * Taking over a lapsed claim (one whose holder is still recorded, never\n * completed or failed) adds one to `failureCount`. When that reaches\n * `maxFailures`, the event dead-letters instead of being claimed: it\n * comes back in `events` with `failedAt` set and no claim. Its\n * `attemptCount` still advances, fencing the lapsed attempt, and its\n * `lastFailedAttempt` is unchanged.\n */\n maxFailures?: number\n }): Promise<StoreClaimAvailableResult>\n\n /**\n * Renews the listed live claims still owned by `holder`. Each listed claim\n * carries the attempt ordinal the holder owns. `renewed` lists the claims\n * that remain owned after the operation; `superseded` lists the claims\n * whose event's `attemptCount` has durably passed the listed attempt. An\n * expired claim no successor has taken appears in neither list — its\n * attempt may still complete (`completeAttempt` is the fence), so it is\n * not reported as lost. Renewal never revives an expired claim.\n */\n renewClaims(options: {\n sessionId: string\n holder: string\n claims: readonly { index: number; attempt: number }[]\n ttlMs: number\n expiresAtMs?: number\n }): Promise<RenewClaimsResult>\n\n /**\n * Atomically completes one current attempt and appends its returned events.\n * Retrying a committed completion with the same attempt and deterministic\n * child ids returns the existing children. A stale attempt never appends.\n */\n completeAttempt(options: {\n sessionId: string\n index: number\n attempt: number\n events: ReturnedEvent[]\n }): Promise<CompleteAttemptResult>\n\n /**\n * Atomically records a caught failure for one claimed attempt. A stale\n * attempt cannot poison a processed event or a newer dispatch. Accepted\n * failures record the operation's clock time. A failure that does not\n * dead-letter releases the claim and, with `retryAfterMs`, keeps the event\n * unclaimable for that long: its claim expiry is set with no holder, so\n * `claimAvailable` reports it `busy` until then.\n */\n failAttempt(options: {\n sessionId: string\n index: number\n attempt: number\n error: string\n maxFailures: number\n retryAfterMs?: number\n }): Promise<FailAttemptResult>\n\n /**\n * Reads a reducer snapshot and its event tail as one consistent adapter\n * operation. On a cache miss, `snapshot` is null and `events` is the full\n * log. The snapshot is untrusted; core may reject it and issue a full\n * `read()` when its state schema no longer accepts the cached value.\n * Operational failures propagate without falling back to a full-log read.\n */\n readState(\n sessionId: string,\n reducerName: string,\n options?: { throughIndex?: number; snapshotThroughIndex?: number },\n ): Promise<StoreStateRead>\n\n /**\n * Optional batched `readState` — one consistent snapshot-plus-tail read\n * per session id, aligned positionally with the input (duplicates\n * allowed). Each element has its own frontier; the batch makes no\n * cross-session consistency claim. Core falls back to parallel\n * `readState` calls when absent.\n */\n readStates?(\n requests: readonly StoreStateReadRequest[],\n reducerName: string,\n ): Promise<StoreStateRead[]>\n\n /**\n * Atomically writes disposable reducer checkpoints. The greatest index\n * advances the head cache. Older checkpoints survive only when at least one\n * listed trigger event is still unfinished; completion and dead-lettering\n * release that event's pins and collect unreferenced historical checkpoints.\n */\n putSnapshots(\n sessionId: string,\n reducerName: string,\n snapshots: readonly StoreSnapshotWrite[],\n ): Promise<void>\n\n /**\n * Optional ephemeral-plane capability (specs/a2-implementation.md\n * §15.1) — optional like snapshots are. Values arrive already\n * validated by core; adapters store them opaquely. Presence never\n * touches the event log: no index, no history row, no recovery arm.\n */\n presence?: {\n /**\n * Field-wise last-writer-wins merge of one participant's values:\n * a field whose existing row has a strictly newer `at` (the\n * sender's stamp) is left untouched; `null` deletes the row. Every\n * applied write refreshes that field's expiry to the storage's own\n * clock plus `ttlMs` — the sender stamp orders writes but never\n * anchors their lifetime.\n */\n set(\n ns: string,\n participant: string,\n values: Record<string, unknown | null>,\n meta: { seen: number; at: Date; ttlMs: number },\n ): Promise<void>\n\n /** The current map, pruned of rows at or past their `expiresAt`. */\n read(ns: string): Promise<PresenceRow[]>\n\n /**\n * Adapter-managed patch delivery. Without it, live feeds re-read\n * presence on their poll cadence. HTTP Redis uses adaptive polling\n * here when its endpoint does not support subscriptions.\n */\n subscribe?(ns: string, onPatch: (patch: PresencePatch) => void): () => void\n }\n\n /**\n * A live feed of one session's events, starting after `startAfter`\n * (exclusive). Transport is the backend's choice — in-process pub/sub,\n * polling, LISTEN/NOTIFY — callers never branch on which. The iterable\n * ends when the consumer calls `return()` (e.g. a disconnecting SSE\n * client) and must deliver events appended after subscription.\n */\n stream(\n sessionId: string,\n opts?: { startAfter?: number },\n ): AsyncIterable<Event>\n}\n"],"mappings":";AAgNA,MAAa,eAAsB,EACjC,2BAAW,IAAI,KAAK,EACtB;AAEA,MAAa,mBAA6B,OAAO,WAAW"}
@@ -1,4 +1,4 @@
1
- import { r as Clock, s as IdSource, t as A2Store } from "./store-Djdv0bnZ.js";
1
+ import { r as Clock, s as IdSource, t as A2Store } from "./store-CyLUy86v.js";
2
2
  //#region src/store-memory.d.ts
3
3
  type MemoryStoreOptions = {
4
4
  /** Injectable clock — every stored timestamp comes from here. */
@@ -1,5 +1,5 @@
1
1
  import { i as A2Error, r as sessionClearedError, s as supersededAttemptError, t as CLEAR_EVENT_TYPE } from "./session-clear-DGI4jTQ5.js";
2
- import { _ as nullProtoRecord } from "./internal-B2T3U4Rq.js";
2
+ import { _ as nullProtoRecord } from "./internal-CscSY7K_.js";
3
3
  import { t as idempotentReplay } from "./idempotent-replay-JdgMQRRm.js";
4
4
  import { n as SYSTEM_CLOCK, t as RANDOM_IDS } from "./store-N8PXxDAS.js";
5
5
  //#region src/store-memory.ts
@@ -157,7 +157,19 @@ function memory(options = {}) {
157
157
  const parent = find(sessionId, cause.index);
158
158
  if (parent.attemptCount !== cause.attempt || parent.failedAt !== null) throw supersededAttemptError(sessionId, cause);
159
159
  };
160
- const claim = (row, holder, now, expiresAt) => {
160
+ const claim = ({ sessionId, row, holder, now, expiresAt, maxFailures }) => {
161
+ if (row.claimHolder !== null) {
162
+ row.failureCount += 1;
163
+ if (maxFailures !== void 0 && row.failureCount >= maxFailures) {
164
+ row.attemptCount += 1;
165
+ row.failedAt = new Date(now);
166
+ row.claimHolder = null;
167
+ row.claimExpiresAt = null;
168
+ dispatchOf(sessionId).ready.delete(row.index);
169
+ releaseSnapshotPins(sessionId, row.index);
170
+ return toStored(row);
171
+ }
172
+ }
161
173
  row.attemptCount += 1;
162
174
  row.firstClaimedAt ??= new Date(now);
163
175
  row.lastClaimedAt = new Date(now);
@@ -322,7 +334,7 @@ function memory(options = {}) {
322
334
  if (through <= after) return [];
323
335
  return log.rows.slice(after - log.offset, through - log.offset).map(toStored);
324
336
  },
325
- async claimAvailable({ sessionId, holder, ttlMs, expiresAtMs, excludeIndexes }) {
337
+ async claimAvailable({ sessionId, holder, ttlMs, expiresAtMs, excludeIndexes, maxFailures }) {
326
338
  const claimedAt = clock.now();
327
339
  const now = claimedAt.getTime();
328
340
  const expiresAt = new Date(expiresAtMs ?? now + ttlMs);
@@ -346,7 +358,14 @@ function memory(options = {}) {
346
358
  return {
347
359
  outcome: "claimed",
348
360
  events: eligible.map((row) => {
349
- const claimed = claim(row, holder, claimedAt, expiresAt);
361
+ const claimed = claim({
362
+ sessionId,
363
+ row,
364
+ holder,
365
+ now: claimedAt,
366
+ expiresAt,
367
+ maxFailures
368
+ });
350
369
  if (clearIndex > 0) claimed.clearIndex = clearIndex;
351
370
  return claimed;
352
371
  })
@@ -414,7 +433,7 @@ function memory(options = {}) {
414
433
  events: inserted.map(toStored)
415
434
  };
416
435
  },
417
- async failAttempt({ sessionId, index, attempt, error, maxFailures }) {
436
+ async failAttempt({ sessionId, index, attempt, error, maxFailures, retryAfterMs }) {
418
437
  if (index <= clearIndexOf(sessionId)) return {
419
438
  outcome: "superseded",
420
439
  failureCount: 0
@@ -438,7 +457,7 @@ function memory(options = {}) {
438
457
  row.lastFailedAt = new Date(failedAt);
439
458
  row.lastFailedAttempt = attempt;
440
459
  row.claimHolder = null;
441
- row.claimExpiresAt = null;
460
+ row.claimExpiresAt = retryAfterMs === void 0 || row.failureCount >= maxFailures ? null : new Date(failedAt.getTime() + retryAfterMs);
442
461
  if (row.failureCount >= maxFailures) {
443
462
  row.failedAt = new Date(failedAt);
444
463
  dispatchOf(sessionId).ready.delete(row.index);
@@ -1 +1 @@
1
- {"version":3,"file":"store-memory.js","names":[],"sources":["../src/store-memory.ts"],"sourcesContent":["/**\n * experimental-a2/store-memory — in-memory store backend (the test default).\n *\n * Implements the A2Store interface with zero dependencies. See\n * specs/a2-implementation.md §3 for the contract; the conformance suite\n * in test/conformance is the executable version of it.\n */\n\nimport type { PresencePatch } from './contract.ts'\nimport { A2Error, supersededAttemptError } from './errors.ts'\nimport { idempotentReplay } from './idempotent-replay.ts'\nimport { nullProtoRecord } from './internal.ts'\nimport { CLEAR_EVENT_TYPE, sessionClearedError } from './session-clear.ts'\nimport {\n RANDOM_IDS,\n SYSTEM_CLOCK,\n type A2Store,\n type AppendEvent,\n type Clock,\n type Event,\n type EventCause,\n type IdSource,\n type PresenceRow,\n type StoredEvent,\n type StoreStateRead,\n} from './store.ts'\n\nexport type MemoryStoreOptions = {\n /** Injectable clock — every stored timestamp comes from here. */\n clock?: Clock\n /** Injectable id source for generated event ids. */\n ids?: IdSource\n}\n\ntype Row = {\n id: string\n type: string\n payload: unknown\n index: number\n sessionId: string\n createdAt: Date\n cause: EventCause | null\n lane: string | null\n processedAt: Date | null\n processedByAttempt: number | null\n returnedEventIds: string[] | null\n firstClaimedAt: Date | null\n lastClaimedAt: Date | null\n attemptCount: number\n claimHolder: string | null\n claimExpiresAt: Date | null\n failureCount: number\n lastFailedAt: Date | null\n lastFailedAttempt: number | null\n lastError: string | null\n failedAt: Date | null\n}\n\ntype PresenceEntry = {\n value: unknown\n seen: number\n at: Date\n expiresAt: Date\n}\n\ntype LaneQueue = { rows: Row[]; head: number }\ntype SessionDispatch = {\n ready: Map<number, Row>\n lanes: Map<string, LaneQueue>\n}\n\n/** Contiguous rows; `reclaim` removes from the front below `clearIndex`. */\ntype SessionLog = {\n rows: Row[]\n /** Index of the event before `rows[0]`. */\n offset: number\n /** Latest clear marker, or 0. */\n clearIndex: number\n}\n\nconst RECLAIM_BATCH = 256\n\nconst headOf = (log: SessionLog | undefined): number =>\n log ? log.offset + log.rows.length : 0\n\nconst toStored = (row: Row): StoredEvent => ({\n id: row.id,\n type: row.type,\n payload: structuredClone(row.payload),\n index: row.index,\n sessionId: row.sessionId,\n createdAt: new Date(row.createdAt),\n cause: row.cause ? { ...row.cause } : null,\n lane: row.lane,\n processedAt: row.processedAt ? new Date(row.processedAt) : null,\n processedByAttempt: row.processedByAttempt,\n returnedEventIds: row.returnedEventIds ? [...row.returnedEventIds] : null,\n firstClaimedAt: row.firstClaimedAt ? new Date(row.firstClaimedAt) : null,\n lastClaimedAt: row.lastClaimedAt ? new Date(row.lastClaimedAt) : null,\n attemptCount: row.attemptCount,\n claimHolder: row.claimHolder,\n claimExpiresAt: row.claimExpiresAt ? new Date(row.claimExpiresAt) : null,\n failureCount: row.failureCount,\n lastFailedAt: row.lastFailedAt ? new Date(row.lastFailedAt) : null,\n lastFailedAttempt: row.lastFailedAttempt,\n lastError: row.lastError,\n failedAt: row.failedAt ? new Date(row.failedAt) : null,\n})\n\nconst toEvent = (row: Row): Event => ({\n id: row.id,\n type: row.type,\n payload: structuredClone(row.payload),\n index: row.index,\n sessionId: row.sessionId,\n createdAt: new Date(row.createdAt),\n})\n\nconst snapshotKey = (sessionId: string, reducerName: string): string =>\n `${sessionId}\\u0000${reducerName}`\n\nconst eventPinKey = (sessionId: string, index: number): string =>\n `${sessionId}\\u0000${index}`\n\nexport function memory(options: MemoryStoreOptions = {}): A2Store {\n const clock = options.clock ?? SYSTEM_CLOCK\n const generateId = options.ids ?? RANDOM_IDS\n\n const sessions = new Map<string, SessionLog>()\n const dispatch = new Map<string, SessionDispatch>()\n /** Global unique index on event ids, like the SQL schema's. */\n const byEventId = new Map<string, Row>()\n /** Keyed by `${sessionId}\\u0000${reducerName}` — a pure cache. */\n const snapshots = new Map<\n string,\n { index: number; state: unknown; updatedAt: Date }\n >()\n const historicalSnapshots = new Map<\n string,\n { index: number; state: unknown; updatedAt: Date }\n >()\n const snapshotPins = new Map<string, Set<string>>()\n const snapshotPinCounts = new Map<string, number>()\n const streamSubscribers = new Map<string, Set<(row: Row) => void>>()\n /** ns → participant → field → latest surviving write. */\n const presenceRows = new Map<\n string,\n Map<string, Map<string, PresenceEntry>>\n >()\n const presenceSubscribers = new Map<\n string,\n Set<(patch: PresencePatch) => void>\n >()\n\n const notifyStreams = (sessionId: string, rows: Row[]): void => {\n const subs = streamSubscribers.get(sessionId)\n if (!subs) return\n for (const listener of subs) {\n for (const row of rows) listener(row)\n }\n }\n\n const logOf = (sessionId: string): SessionLog => {\n let log = sessions.get(sessionId)\n if (!log) {\n log = { rows: [], offset: 0, clearIndex: 0 }\n sessions.set(sessionId, log)\n }\n return log\n }\n\n const rowAt = (sessionId: string, index: number): Row | undefined => {\n const log = sessions.get(sessionId)\n return log && index > log.offset\n ? log.rows[index - log.offset - 1]\n : undefined\n }\n\n const clearIndexOf = (sessionId: string): number =>\n sessions.get(sessionId)?.clearIndex ?? 0\n\n /** The row owning `id`, ignoring this session's rows below its clear. */\n const ownerOf = (sessionId: string, id: string): Row | undefined => {\n const row = byEventId.get(id)\n return row?.sessionId === sessionId && row.index < clearIndexOf(sessionId)\n ? undefined\n : row\n }\n\n const checkpointKey = (\n sessionId: string,\n reducerName: string,\n index: number,\n ): string => `${snapshotKey(sessionId, reducerName)}\\u0000${index}`\n\n const releaseSnapshotPins = (sessionId: string, eventIndex: number): void => {\n const pinKey = eventPinKey(sessionId, eventIndex)\n const checkpoints = snapshotPins.get(pinKey)\n if (!checkpoints) return\n for (const key of checkpoints) {\n const next = (snapshotPinCounts.get(key) ?? 1) - 1\n if (next === 0) {\n snapshotPinCounts.delete(key)\n historicalSnapshots.delete(key)\n } else {\n snapshotPinCounts.set(key, next)\n }\n }\n snapshotPins.delete(pinKey)\n }\n\n const dispatchOf = (sessionId: string): SessionDispatch => {\n let state = dispatch.get(sessionId)\n if (!state) {\n state = { ready: new Map(), lanes: new Map() }\n dispatch.set(sessionId, state)\n }\n return state\n }\n\n const enqueue = (sessionId: string, row: Row): void => {\n if (row.processedAt !== null) return\n const state = dispatchOf(sessionId)\n if (row.lane === null) {\n state.ready.set(row.index, row)\n return\n }\n let queue = state.lanes.get(row.lane)\n if (!queue) {\n queue = { rows: [], head: 0 }\n state.lanes.set(row.lane, queue)\n }\n queue.rows.push(row)\n if (queue.rows.length === 1) state.ready.set(row.index, row)\n }\n\n const settle = (sessionId: string, row: Row): void => {\n const state = dispatchOf(sessionId)\n state.ready.delete(row.index)\n if (row.lane === null) return\n const queue = state.lanes.get(row.lane)!\n if (queue.rows[queue.head] !== row) return\n queue.head += 1\n if (queue.head === queue.rows.length) {\n state.lanes.delete(row.lane)\n return\n }\n const next = queue.rows[queue.head]!\n if (next.failedAt === null) state.ready.set(next.index, next)\n }\n\n const find = (sessionId: string, index: number): Row => {\n const row = rowAt(sessionId, index)\n if (!row) {\n throw new TypeError(\n `no event at index ${index} in session '${sessionId}'`,\n )\n }\n return row\n }\n\n const hasPending = (sessionId: string): boolean => {\n const log = sessions.get(sessionId)\n return (log?.rows ?? []).some(\n (row) => row.index > log!.clearIndex && row.processedAt === null,\n )\n }\n\n const appendResult = (sessionId: string, events: StoredEvent[]) => ({\n events,\n hasPending: hasPending(sessionId),\n })\n\n /** The attempt-currency fence shared by handler appends and clears. */\n const assertCurrentCause = (sessionId: string, cause: EventCause): void => {\n if (cause.index <= clearIndexOf(sessionId)) {\n throw supersededAttemptError(sessionId, cause)\n }\n const parent = find(sessionId, cause.index)\n if (parent.attemptCount !== cause.attempt || parent.failedAt !== null) {\n throw supersededAttemptError(sessionId, cause)\n }\n }\n\n const claim = (\n row: Row,\n holder: string,\n now: Date,\n expiresAt: Date,\n ): StoredEvent => {\n row.attemptCount += 1\n row.firstClaimedAt ??= new Date(now)\n row.lastClaimedAt = new Date(now)\n row.claimHolder = holder\n row.claimExpiresAt = new Date(expiresAt)\n return toStored(row)\n }\n\n const checkBatchIds = (\n sessionId: string,\n events: readonly (AppendEvent & { id?: string })[],\n ): Row[] => {\n const supplied = events.filter(\n (candidate): candidate is AppendEvent & { id: string } =>\n candidate.id !== undefined,\n )\n const suppliedIds = new Set(supplied.map((candidate) => candidate.id))\n if (suppliedIds.size !== supplied.length) {\n throw new A2Error(\n 'PARTIAL_DUPLICATE_BATCH',\n 'batch contains the same event id more than once',\n )\n }\n const existing = supplied\n .map((candidate) => ownerOf(sessionId, candidate.id))\n .filter((row): row is Row => row !== undefined)\n const foreign = existing.find((row) => row.sessionId !== sessionId)\n if (foreign) {\n throw new A2Error(\n 'PARTIAL_DUPLICATE_BATCH',\n `event id '${foreign.id}' already exists in another session`,\n )\n }\n return existing\n }\n\n const insert = (\n sessionId: string,\n events: readonly AppendEvent[],\n now: Date,\n cause?: EventCause,\n ): Row[] => {\n const log = logOf(sessionId)\n const base = headOf(log)\n const inserted = events.map((candidate, offset): Row => ({\n id: candidate.id ?? generateId(),\n type: candidate.type,\n payload: structuredClone(candidate.payload),\n index: base + 1 + offset,\n sessionId,\n createdAt: new Date(now),\n cause: cause\n ? { ...cause }\n : candidate.cause\n ? { ...candidate.cause }\n : null,\n lane: candidate.lane ?? null,\n processedAt: candidate.settled ? new Date(now) : null,\n processedByAttempt: null,\n returnedEventIds: null,\n firstClaimedAt: null,\n lastClaimedAt: null,\n attemptCount: 0,\n claimHolder: null,\n claimExpiresAt: null,\n failureCount: 0,\n lastFailedAt: null,\n lastFailedAttempt: null,\n lastError: null,\n failedAt: null,\n }))\n for (const row of inserted) {\n if (ownerOf(sessionId, row.id)) {\n throw new A2Error(\n 'PARTIAL_DUPLICATE_BATCH',\n `event id '${row.id}' already exists`,\n )\n }\n }\n for (const row of inserted) {\n log.rows.push(row)\n byEventId.set(row.id, row)\n enqueue(sessionId, row)\n }\n return inserted\n }\n\n /** Every cached fold of this session below its clear, head or historical. */\n const dropCheckpointsBelow = (\n sessionId: string,\n clearIndex: number,\n ): void => {\n const prefix = `${sessionId}\\u0000`\n for (const [key, snapshot] of snapshots) {\n if (!key.startsWith(prefix) || snapshot.index >= clearIndex) continue\n snapshots.delete(key)\n snapshotPinCounts.delete(`${key}\\u0000${snapshot.index}`)\n }\n for (const [key, snapshot] of historicalSnapshots) {\n if (!key.startsWith(prefix) || snapshot.index >= clearIndex) continue\n historicalSnapshots.delete(key)\n snapshotPinCounts.delete(key)\n }\n }\n\n const readStateOf = (\n sessionId: string,\n reducerName: string,\n throughIndex?: number,\n snapshotThroughIndex?: number,\n ): StoreStateRead => {\n const key = snapshotKey(sessionId, reducerName)\n const clearIndex = clearIndexOf(sessionId)\n const snapshotFrontier = snapshotThroughIndex ?? throughIndex\n const stored = snapshots.get(key)\n const head = stored && stored.index >= clearIndex ? stored : undefined\n let candidate =\n head && (snapshotFrontier === undefined || head.index <= snapshotFrontier)\n ? head\n : null\n if (snapshotFrontier !== undefined) {\n const prefix = `${key}\\u0000`\n for (const [historicalKey, snapshot] of historicalSnapshots) {\n if (\n historicalKey.startsWith(prefix) &&\n snapshot.index >= clearIndex &&\n snapshot.index <= snapshotFrontier &&\n (!candidate || snapshot.index > candidate.index)\n ) {\n candidate = snapshot\n }\n }\n }\n const snapshot = candidate\n ? { index: candidate.index, state: structuredClone(candidate.state) }\n : null\n const afterIndex = Math.max(snapshot?.index ?? 0, clearIndex - 1)\n return {\n headIndex: head?.index ?? null,\n snapshot,\n events: (sessions.get(sessionId)?.rows ?? [])\n .filter(\n (row) =>\n row.index > afterIndex &&\n (throughIndex === undefined || row.index <= throughIndex),\n )\n .map(toEvent),\n ...(clearIndex > 0 ? { clearIndex } : {}),\n }\n }\n\n return {\n async append(sessionId, events, appendOptions) {\n if (events.length === 0) return appendResult(sessionId, [])\n\n // Batch-scoped idempotency (a2-implementation.md §3): all ids\n // already present → lost-ack retry, return the original rows;\n // some present → the caller mixed sent and fresh events.\n const existing = checkBatchIds(sessionId, events)\n if (existing.length > 0) {\n if (existing.length === events.length) {\n return appendResult(\n sessionId,\n idempotentReplay(events, existing.map(toStored)),\n )\n }\n throw new A2Error(\n 'PARTIAL_DUPLICATE_BATCH',\n `batch mixes ${existing.length} already-appended and ${events.length - existing.length} fresh events`,\n )\n }\n\n const originIndex = appendOptions?.originIndex\n if (originIndex !== undefined && originIndex <= clearIndexOf(sessionId)) {\n throw sessionClearedError(\n `scheduled work from event ${originIndex} was cleared in session '${sessionId}'`,\n )\n }\n // Attempt-currency fence: a fresh handler append commits only while\n // its causal attempt is still the parent's latest (store.ts `append`).\n for (const event of events) {\n if (event.cause) assertCurrentCause(sessionId, event.cause)\n }\n\n const now = clock.now()\n const inserted = insert(sessionId, events, now)\n notifyStreams(sessionId, inserted)\n return appendResult(sessionId, inserted.map(toStored))\n },\n\n async clear({ sessionId, ifLastIndex, cause }) {\n if (cause) assertCurrentCause(sessionId, cause)\n const log = sessions.get(sessionId)\n const head = headOf(log)\n const clearIndex = log?.clearIndex ?? 0\n if (ifLastIndex !== undefined && clearIndex === ifLastIndex + 1) {\n return { cleared: true, index: head, clearIndex }\n }\n if (ifLastIndex !== undefined && ifLastIndex !== head) {\n return { cleared: false, index: head, clearIndex }\n }\n if (head === 0 || clearIndex === head) {\n return { cleared: true, index: head, clearIndex }\n }\n const [marker] = insert(\n sessionId,\n [{ type: CLEAR_EVENT_TYPE, payload: null, settled: true }],\n clock.now(),\n )\n logOf(sessionId).clearIndex = marker!.index\n // Every row is at or below the marker, so no dispatch state survives.\n dispatch.delete(sessionId)\n notifyStreams(sessionId, [marker!])\n return { cleared: true, index: marker!.index, clearIndex: marker!.index }\n },\n\n async reclaim(sessionId) {\n const log = sessions.get(sessionId)\n if (!log || log.offset >= log.clearIndex - 1) {\n return { deleted: 0, done: true }\n }\n const removed = log.rows.splice(\n 0,\n Math.min(RECLAIM_BATCH, log.clearIndex - 1 - log.offset),\n )\n log.offset += removed.length\n for (const row of removed) {\n // A reused id belongs to its new row now.\n if (byEventId.get(row.id) === row) byEventId.delete(row.id)\n releaseSnapshotPins(sessionId, row.index)\n }\n const done = log.offset === log.clearIndex - 1\n // Writes below the marker are dropped, so one sweep at the end suffices.\n if (done) dropCheckpointsBelow(sessionId, log.clearIndex)\n return { deleted: removed.length, done }\n },\n\n async read(sessionId, opts) {\n const log = sessions.get(sessionId)\n if (!log) return []\n const head = headOf(log)\n const after = Math.max(\n opts?.afterIndex ?? 0,\n log.clearIndex - 1,\n log.offset,\n )\n const through = Math.min(opts?.throughIndex ?? head, head)\n if (through <= after) return []\n return log.rows\n .slice(after - log.offset, through - log.offset)\n .map(toStored)\n },\n\n async claimAvailable({\n sessionId,\n holder,\n ttlMs,\n expiresAtMs,\n excludeIndexes,\n }) {\n const claimedAt = clock.now()\n const now = claimedAt.getTime()\n const expiresAt = new Date(expiresAtMs ?? now + ttlMs)\n const excluded = new Set(excludeIndexes ?? [])\n const eligible: Row[] = []\n let retryAt: Date | null = null\n\n for (const row of dispatchOf(sessionId).ready.values()) {\n if (row.failedAt !== null || excluded.has(row.index)) continue\n if (row.claimExpiresAt && row.claimExpiresAt.getTime() > now) {\n if (!retryAt || row.claimExpiresAt < retryAt) {\n retryAt = new Date(row.claimExpiresAt)\n }\n continue\n }\n eligible.push(row)\n }\n\n if (eligible.length === 0) {\n return retryAt ? { outcome: 'busy', retryAt } : { outcome: 'settled' }\n }\n eligible.sort((a, b) => a.index - b.index)\n const clearIndex = clearIndexOf(sessionId)\n return {\n outcome: 'claimed',\n events: eligible.map((row) => {\n const claimed = claim(row, holder, claimedAt, expiresAt)\n if (clearIndex > 0) claimed.clearIndex = clearIndex\n return claimed\n }),\n }\n },\n\n async renewClaims({ sessionId, holder, claims, ttlMs, expiresAtMs }) {\n const now = clock.now()\n const expiresAt = new Date(expiresAtMs ?? now.getTime() + ttlMs)\n const clearIndex = clearIndexOf(sessionId)\n const renewed: number[] = []\n const superseded: number[] = []\n for (const { index, attempt } of claims.toSorted(\n (a, b) => a.index - b.index,\n )) {\n if (index <= clearIndex) {\n superseded.push(index)\n continue\n }\n const row = rowAt(sessionId, index)\n if (!row) continue\n if (row.attemptCount > attempt) {\n superseded.push(row.index)\n continue\n }\n if (\n row.processedAt === null &&\n row.failedAt === null &&\n row.claimHolder === holder &&\n row.claimExpiresAt !== null &&\n row.claimExpiresAt > now\n ) {\n row.claimExpiresAt = new Date(expiresAt)\n renewed.push(row.index)\n }\n }\n return { renewed, superseded }\n },\n\n async completeAttempt({ sessionId, index, attempt, events }) {\n if (index <= clearIndexOf(sessionId)) return { outcome: 'superseded' }\n const parent = find(sessionId, index)\n const cause = { index, attempt }\n if (parent.processedAt !== null) {\n if (parent.processedByAttempt !== attempt) {\n return { outcome: 'superseded' }\n }\n const requestedIds = events.map((event) => event.id)\n if (\n parent.returnedEventIds === null ||\n parent.returnedEventIds.length !== requestedIds.length ||\n parent.returnedEventIds.some(\n (id, offset) => id !== requestedIds[offset],\n )\n ) {\n throw new A2Error(\n 'PARTIAL_DUPLICATE_BATCH',\n 'completed attempt does not match the returned event batch',\n )\n }\n const existing = checkBatchIds(sessionId, events)\n if (\n existing.length !== events.length ||\n existing.some(\n (row) =>\n row.cause?.index !== index || row.cause.attempt !== attempt,\n )\n ) {\n throw new A2Error(\n 'PARTIAL_DUPLICATE_BATCH',\n 'completed attempt does not match the returned event batch',\n )\n }\n return {\n outcome: 'completed',\n events: idempotentReplay(events, existing.map(toStored)),\n }\n }\n if (\n parent.attemptCount !== attempt ||\n parent.failedAt !== null ||\n parent.claimHolder === null\n ) {\n return { outcome: 'superseded' }\n }\n\n const existing = checkBatchIds(sessionId, events)\n if (existing.length > 0) {\n throw new A2Error(\n 'PARTIAL_DUPLICATE_BATCH',\n 'returned event batch contains already-appended ids',\n )\n }\n const now = clock.now()\n const inserted = insert(sessionId, events, now, cause)\n parent.processedAt = new Date(now)\n parent.processedByAttempt = attempt\n parent.returnedEventIds = events.map((event) => event.id)\n parent.claimHolder = null\n parent.claimExpiresAt = null\n settle(sessionId, parent)\n releaseSnapshotPins(sessionId, index)\n notifyStreams(sessionId, inserted)\n return { outcome: 'completed', events: inserted.map(toStored) }\n },\n\n async failAttempt({ sessionId, index, attempt, error, maxFailures }) {\n if (index <= clearIndexOf(sessionId)) {\n return { outcome: 'superseded', failureCount: 0 }\n }\n const row = find(sessionId, index)\n if (\n row.processedAt ||\n row.attemptCount !== attempt ||\n (row.claimHolder === null && row.lastFailedAttempt !== attempt)\n ) {\n return { outcome: 'superseded', failureCount: row.failureCount }\n }\n if (row.lastFailedAttempt === attempt && row.claimHolder === null) {\n return {\n outcome: row.failedAt ? 'dead_lettered' : 'failed',\n failureCount: row.failureCount,\n }\n }\n if (row.failedAt) {\n return { outcome: 'dead_lettered', failureCount: row.failureCount }\n }\n row.failureCount += 1\n row.lastError = error\n const failedAt = clock.now()\n row.lastFailedAt = new Date(failedAt)\n row.lastFailedAttempt = attempt\n row.claimHolder = null\n row.claimExpiresAt = null\n if (row.failureCount >= maxFailures) {\n row.failedAt = new Date(failedAt)\n dispatchOf(sessionId).ready.delete(row.index)\n releaseSnapshotPins(sessionId, index)\n return {\n outcome: 'dead_lettered',\n failureCount: row.failureCount,\n }\n }\n return { outcome: 'failed', failureCount: row.failureCount }\n },\n\n async deadLetters(sessionId) {\n const log = sessions.get(sessionId)\n return (log?.rows ?? [])\n .filter(\n (row) =>\n row.index > log!.clearIndex &&\n row.processedAt === null &&\n row.failedAt !== null,\n )\n .map(toStored)\n },\n\n async redrive({ sessionId, index, action }) {\n const row =\n index > clearIndexOf(sessionId) ? rowAt(sessionId, index) : undefined\n if (!row || row.processedAt !== null || row.failedAt === null) {\n return { redriven: false, hasPending: hasPending(sessionId) }\n }\n if (action === 'skip') {\n row.processedAt = clock.now()\n settle(sessionId, row)\n } else {\n row.failedAt = null\n row.failureCount = 0\n const state = dispatchOf(sessionId)\n const queue = row.lane === null ? undefined : state.lanes.get(row.lane)\n if (row.lane === null || queue?.rows[queue.head] === row) {\n state.ready.set(row.index, row)\n }\n }\n return { redriven: true, hasPending: hasPending(sessionId) }\n },\n\n async readState(sessionId, reducerName, stateOptions) {\n return readStateOf(\n sessionId,\n reducerName,\n stateOptions?.throughIndex,\n stateOptions?.snapshotThroughIndex,\n )\n },\n\n async readStates(requests, reducerName) {\n return requests.map((request) =>\n readStateOf(\n request.sessionId,\n reducerName,\n request.throughIndex,\n request.snapshotThroughIndex,\n ),\n )\n },\n\n async putSnapshots(sessionId, reducerName, writes) {\n const key = snapshotKey(sessionId, reducerName)\n const clearIndex = clearIndexOf(sessionId)\n for (const write of writes.toSorted((a, b) => a.index - b.index)) {\n if (write.index < clearIndex) continue\n const checkpoint = checkpointKey(sessionId, reducerName, write.index)\n for (const eventIndex of write.pinEventIndexes ?? []) {\n const event = rowAt(sessionId, eventIndex)\n if (\n !event ||\n event.index <= clearIndex ||\n event.processedAt !== null ||\n event.failedAt !== null\n ) {\n continue\n }\n const pinKey = eventPinKey(sessionId, eventIndex)\n let pinned = snapshotPins.get(pinKey)\n if (!pinned) {\n pinned = new Set()\n snapshotPins.set(pinKey, pinned)\n }\n if (!pinned.has(checkpoint)) {\n pinned.add(checkpoint)\n snapshotPinCounts.set(\n checkpoint,\n (snapshotPinCounts.get(checkpoint) ?? 0) + 1,\n )\n }\n }\n\n const current = snapshots.get(key)\n if (!current || write.index >= current.index) {\n if (\n current &&\n write.index > current.index &&\n current.index >= clearIndex\n ) {\n const currentCheckpoint = checkpointKey(\n sessionId,\n reducerName,\n current.index,\n )\n if ((snapshotPinCounts.get(currentCheckpoint) ?? 0) > 0) {\n historicalSnapshots.set(currentCheckpoint, {\n index: current.index,\n state: structuredClone(current.state),\n updatedAt: new Date(current.updatedAt),\n })\n }\n }\n snapshots.set(key, {\n index: write.index,\n state: structuredClone(write.state),\n updatedAt: clock.now(),\n })\n historicalSnapshots.delete(checkpoint)\n } else if (\n write.index < current.index &&\n (snapshotPinCounts.get(checkpoint) ?? 0) > 0\n ) {\n historicalSnapshots.set(checkpoint, {\n index: write.index,\n state: structuredClone(write.state),\n updatedAt: clock.now(),\n })\n }\n }\n },\n\n presence: {\n async set(ns, participant, values, meta) {\n let participants = presenceRows.get(ns)\n if (!participants) {\n participants = new Map()\n presenceRows.set(ns, participants)\n }\n let fields = participants.get(participant)\n if (!fields) {\n fields = new Map()\n participants.set(participant, fields)\n }\n\n // Expiry anchors on the storage's own clock — the sender's\n // `at` orders writes but never extends or shortens a lifetime.\n const expiresAtMs = clock.now().getTime() + meta.ttlMs\n // Field-keyed and caller-named — null-prototype, like every\n // presence map (see `nullProtoRecord`).\n const applied: Record<string, unknown> = nullProtoRecord()\n let appliedCount = 0\n for (const [field, value] of Object.entries(values)) {\n // Field-wise LWW by `at`; ties go to the incoming write, so\n // same-stamp sets keep set-then-read intuition.\n const existing = fields.get(field)\n if (existing && existing.at > meta.at) continue\n if (value === null) {\n fields.delete(field)\n } else {\n fields.set(field, {\n value: structuredClone(value),\n seen: meta.seen,\n at: new Date(meta.at),\n expiresAt: new Date(expiresAtMs),\n })\n }\n applied[field] = structuredClone(value)\n appliedCount += 1\n }\n if (fields.size === 0) participants.delete(participant)\n if (participants.size === 0) presenceRows.delete(ns)\n\n // Only applied fields broadcast — a losing write repaints nothing,\n // so subscribers stay consistent with what read() returns.\n if (appliedCount === 0) return\n const subs = presenceSubscribers.get(ns)\n if (!subs) return\n const patch: PresencePatch = {\n participant,\n values: applied,\n seen: meta.seen,\n at: new Date(meta.at),\n }\n for (const listener of subs) listener(patch)\n },\n\n async read(ns) {\n const participants = presenceRows.get(ns)\n if (!participants) return []\n const now = clock.now()\n const rows: PresenceRow[] = []\n for (const [participant, fields] of participants) {\n for (const [field, entry] of fields) {\n // Expiry is enforced lazily on read — no timers; a silent\n // participant's rows vanish the next time anyone looks.\n if (entry.expiresAt <= now) {\n fields.delete(field)\n continue\n }\n rows.push({\n participant,\n field,\n value: structuredClone(entry.value),\n seen: entry.seen,\n at: new Date(entry.at),\n expiresAt: new Date(entry.expiresAt),\n })\n }\n if (fields.size === 0) participants.delete(participant)\n }\n if (participants.size === 0) presenceRows.delete(ns)\n return rows\n },\n\n subscribe(ns, onPatch) {\n let subs = presenceSubscribers.get(ns)\n if (!subs) {\n subs = new Set()\n presenceSubscribers.set(ns, subs)\n }\n subs.add(onPatch)\n return () => {\n subs.delete(onPatch)\n if (subs.size === 0) presenceSubscribers.delete(ns)\n }\n },\n },\n\n stream(sessionId, opts) {\n const startAfter = opts?.startAfter ?? 0\n return {\n [Symbol.asyncIterator](): AsyncIterator<Event> {\n let last = Math.max(startAfter, clearIndexOf(sessionId) - 1)\n let wake: (() => void) | null = null\n let closed = false\n\n const onRow = (): void => {\n wake?.()\n }\n let subs = streamSubscribers.get(sessionId)\n if (!subs) {\n subs = new Set()\n streamSubscribers.set(sessionId, subs)\n }\n subs.add(onRow)\n const stop = (): void => {\n if (closed) return\n closed = true\n subs.delete(onRow)\n if (subs.size === 0) streamSubscribers.delete(sessionId)\n wake?.()\n }\n\n return {\n async next(): Promise<IteratorResult<Event>> {\n try {\n for (;;) {\n if (closed) return { value: undefined, done: true }\n const log = sessions.get(sessionId)\n // Rows reclaimed behind a running stream are skipped.\n const row = log?.rows[Math.max(0, last - log.offset)]\n if (row) {\n const value = toStored(row)\n last = row.index\n return { value, done: false }\n }\n // oxlint-disable-next-line no-await-in-loop -- wait-for-wake\n await new Promise<void>((resolve) => {\n wake = resolve\n })\n wake = null\n }\n } catch (error) {\n stop()\n throw error\n }\n },\n async return(): Promise<IteratorResult<Event>> {\n stop()\n return { value: undefined, done: true }\n },\n }\n },\n }\n },\n }\n}\n"],"mappings":";;;;;AAgFA,MAAM,gBAAgB;AAEtB,MAAM,UAAU,QACd,MAAM,IAAI,SAAS,IAAI,KAAK,SAAS;AAEvC,MAAM,YAAY,SAA2B;CAC3C,IAAI,IAAI;CACR,MAAM,IAAI;CACV,SAAS,gBAAgB,IAAI,OAAO;CACpC,OAAO,IAAI;CACX,WAAW,IAAI;CACf,WAAW,IAAI,KAAK,IAAI,SAAS;CACjC,OAAO,IAAI,QAAQ,EAAE,GAAG,IAAI,MAAM,IAAI;CACtC,MAAM,IAAI;CACV,aAAa,IAAI,cAAc,IAAI,KAAK,IAAI,WAAW,IAAI;CAC3D,oBAAoB,IAAI;CACxB,kBAAkB,IAAI,mBAAmB,CAAC,GAAG,IAAI,gBAAgB,IAAI;CACrE,gBAAgB,IAAI,iBAAiB,IAAI,KAAK,IAAI,cAAc,IAAI;CACpE,eAAe,IAAI,gBAAgB,IAAI,KAAK,IAAI,aAAa,IAAI;CACjE,cAAc,IAAI;CAClB,aAAa,IAAI;CACjB,gBAAgB,IAAI,iBAAiB,IAAI,KAAK,IAAI,cAAc,IAAI;CACpE,cAAc,IAAI;CAClB,cAAc,IAAI,eAAe,IAAI,KAAK,IAAI,YAAY,IAAI;CAC9D,mBAAmB,IAAI;CACvB,WAAW,IAAI;CACf,UAAU,IAAI,WAAW,IAAI,KAAK,IAAI,QAAQ,IAAI;AACpD;AAEA,MAAM,WAAW,SAAqB;CACpC,IAAI,IAAI;CACR,MAAM,IAAI;CACV,SAAS,gBAAgB,IAAI,OAAO;CACpC,OAAO,IAAI;CACX,WAAW,IAAI;CACf,WAAW,IAAI,KAAK,IAAI,SAAS;AACnC;AAEA,MAAM,eAAe,WAAmB,gBACtC,GAAG,UAAU,QAAQ;AAEvB,MAAM,eAAe,WAAmB,UACtC,GAAG,UAAU,QAAQ;AAEvB,SAAgB,OAAO,UAA8B,CAAC,GAAY;CAChE,MAAM,QAAQ,QAAQ,SAAS;CAC/B,MAAM,aAAa,QAAQ,OAAO;CAElC,MAAM,2BAAW,IAAI,IAAwB;CAC7C,MAAM,2BAAW,IAAI,IAA6B;;CAElD,MAAM,4BAAY,IAAI,IAAiB;;CAEvC,MAAM,4BAAY,IAAI,IAGpB;CACF,MAAM,sCAAsB,IAAI,IAG9B;CACF,MAAM,+BAAe,IAAI,IAAyB;CAClD,MAAM,oCAAoB,IAAI,IAAoB;CAClD,MAAM,oCAAoB,IAAI,IAAqC;;CAEnE,MAAM,+BAAe,IAAI,IAGvB;CACF,MAAM,sCAAsB,IAAI,IAG9B;CAEF,MAAM,iBAAiB,WAAmB,SAAsB;EAC9D,MAAM,OAAO,kBAAkB,IAAI,SAAS;EAC5C,IAAI,CAAC,MAAM;EACX,KAAK,MAAM,YAAY,MACrB,KAAK,MAAM,OAAO,MAAM,SAAS,GAAG;CAExC;CAEA,MAAM,SAAS,cAAkC;EAC/C,IAAI,MAAM,SAAS,IAAI,SAAS;EAChC,IAAI,CAAC,KAAK;GACR,MAAM;IAAE,MAAM,CAAC;IAAG,QAAQ;IAAG,YAAY;GAAE;GAC3C,SAAS,IAAI,WAAW,GAAG;EAC7B;EACA,OAAO;CACT;CAEA,MAAM,SAAS,WAAmB,UAAmC;EACnE,MAAM,MAAM,SAAS,IAAI,SAAS;EAClC,OAAO,OAAO,QAAQ,IAAI,SACtB,IAAI,KAAK,QAAQ,IAAI,SAAS,KAC9B,KAAA;CACN;CAEA,MAAM,gBAAgB,cACpB,SAAS,IAAI,SAAS,CAAC,EAAE,cAAc;;CAGzC,MAAM,WAAW,WAAmB,OAAgC;EAClE,MAAM,MAAM,UAAU,IAAI,EAAE;EAC5B,OAAO,KAAK,cAAc,aAAa,IAAI,QAAQ,aAAa,SAAS,IACrE,KAAA,IACA;CACN;CAEA,MAAM,iBACJ,WACA,aACA,UACW,GAAG,YAAY,WAAW,WAAW,EAAE,QAAQ;CAE5D,MAAM,uBAAuB,WAAmB,eAA6B;EAC3E,MAAM,SAAS,YAAY,WAAW,UAAU;EAChD,MAAM,cAAc,aAAa,IAAI,MAAM;EAC3C,IAAI,CAAC,aAAa;EAClB,KAAK,MAAM,OAAO,aAAa;GAC7B,MAAM,QAAQ,kBAAkB,IAAI,GAAG,KAAK,KAAK;GACjD,IAAI,SAAS,GAAG;IACd,kBAAkB,OAAO,GAAG;IAC5B,oBAAoB,OAAO,GAAG;GAChC,OACE,kBAAkB,IAAI,KAAK,IAAI;EAEnC;EACA,aAAa,OAAO,MAAM;CAC5B;CAEA,MAAM,cAAc,cAAuC;EACzD,IAAI,QAAQ,SAAS,IAAI,SAAS;EAClC,IAAI,CAAC,OAAO;GACV,QAAQ;IAAE,uBAAO,IAAI,IAAI;IAAG,uBAAO,IAAI,IAAI;GAAE;GAC7C,SAAS,IAAI,WAAW,KAAK;EAC/B;EACA,OAAO;CACT;CAEA,MAAM,WAAW,WAAmB,QAAmB;EACrD,IAAI,IAAI,gBAAgB,MAAM;EAC9B,MAAM,QAAQ,WAAW,SAAS;EAClC,IAAI,IAAI,SAAS,MAAM;GACrB,MAAM,MAAM,IAAI,IAAI,OAAO,GAAG;GAC9B;EACF;EACA,IAAI,QAAQ,MAAM,MAAM,IAAI,IAAI,IAAI;EACpC,IAAI,CAAC,OAAO;GACV,QAAQ;IAAE,MAAM,CAAC;IAAG,MAAM;GAAE;GAC5B,MAAM,MAAM,IAAI,IAAI,MAAM,KAAK;EACjC;EACA,MAAM,KAAK,KAAK,GAAG;EACnB,IAAI,MAAM,KAAK,WAAW,GAAG,MAAM,MAAM,IAAI,IAAI,OAAO,GAAG;CAC7D;CAEA,MAAM,UAAU,WAAmB,QAAmB;EACpD,MAAM,QAAQ,WAAW,SAAS;EAClC,MAAM,MAAM,OAAO,IAAI,KAAK;EAC5B,IAAI,IAAI,SAAS,MAAM;EACvB,MAAM,QAAQ,MAAM,MAAM,IAAI,IAAI,IAAI;EACtC,IAAI,MAAM,KAAK,MAAM,UAAU,KAAK;EACpC,MAAM,QAAQ;EACd,IAAI,MAAM,SAAS,MAAM,KAAK,QAAQ;GACpC,MAAM,MAAM,OAAO,IAAI,IAAI;GAC3B;EACF;EACA,MAAM,OAAO,MAAM,KAAK,MAAM;EAC9B,IAAI,KAAK,aAAa,MAAM,MAAM,MAAM,IAAI,KAAK,OAAO,IAAI;CAC9D;CAEA,MAAM,QAAQ,WAAmB,UAAuB;EACtD,MAAM,MAAM,MAAM,WAAW,KAAK;EAClC,IAAI,CAAC,KACH,MAAM,IAAI,UACR,qBAAqB,MAAM,eAAe,UAAU,EACtD;EAEF,OAAO;CACT;CAEA,MAAM,cAAc,cAA+B;EACjD,MAAM,MAAM,SAAS,IAAI,SAAS;EAClC,QAAQ,KAAK,QAAQ,CAAC,EAAA,CAAG,MACtB,QAAQ,IAAI,QAAQ,IAAK,cAAc,IAAI,gBAAgB,IAC9D;CACF;CAEA,MAAM,gBAAgB,WAAmB,YAA2B;EAClE;EACA,YAAY,WAAW,SAAS;CAClC;;CAGA,MAAM,sBAAsB,WAAmB,UAA4B;EACzE,IAAI,MAAM,SAAS,aAAa,SAAS,GACvC,MAAM,uBAAuB,WAAW,KAAK;EAE/C,MAAM,SAAS,KAAK,WAAW,MAAM,KAAK;EAC1C,IAAI,OAAO,iBAAiB,MAAM,WAAW,OAAO,aAAa,MAC/D,MAAM,uBAAuB,WAAW,KAAK;CAEjD;CAEA,MAAM,SACJ,KACA,QACA,KACA,cACgB;EAChB,IAAI,gBAAgB;EACpB,IAAI,mBAAmB,IAAI,KAAK,GAAG;EACnC,IAAI,gBAAgB,IAAI,KAAK,GAAG;EAChC,IAAI,cAAc;EAClB,IAAI,iBAAiB,IAAI,KAAK,SAAS;EACvC,OAAO,SAAS,GAAG;CACrB;CAEA,MAAM,iBACJ,WACA,WACU;EACV,MAAM,WAAW,OAAO,QACrB,cACC,UAAU,OAAO,KAAA,CACrB;EAEA,IAAI,IADoB,IAAI,SAAS,KAAK,cAAc,UAAU,EAAE,CACtD,CAAC,CAAC,SAAS,SAAS,QAChC,MAAM,IAAI,QACR,2BACA,iDACF;EAEF,MAAM,WAAW,SACd,KAAK,cAAc,QAAQ,WAAW,UAAU,EAAE,CAAC,CAAC,CACpD,QAAQ,QAAoB,QAAQ,KAAA,CAAS;EAChD,MAAM,UAAU,SAAS,MAAM,QAAQ,IAAI,cAAc,SAAS;EAClE,IAAI,SACF,MAAM,IAAI,QACR,2BACA,aAAa,QAAQ,GAAG,oCAC1B;EAEF,OAAO;CACT;CAEA,MAAM,UACJ,WACA,QACA,KACA,UACU;EACV,MAAM,MAAM,MAAM,SAAS;EAC3B,MAAM,OAAO,OAAO,GAAG;EACvB,MAAM,WAAW,OAAO,KAAK,WAAW,YAAiB;GACvD,IAAI,UAAU,MAAM,WAAW;GAC/B,MAAM,UAAU;GAChB,SAAS,gBAAgB,UAAU,OAAO;GAC1C,OAAO,OAAO,IAAI;GAClB;GACA,WAAW,IAAI,KAAK,GAAG;GACvB,OAAO,QACH,EAAE,GAAG,MAAM,IACX,UAAU,QACR,EAAE,GAAG,UAAU,MAAM,IACrB;GACN,MAAM,UAAU,QAAQ;GACxB,aAAa,UAAU,UAAU,IAAI,KAAK,GAAG,IAAI;GACjD,oBAAoB;GACpB,kBAAkB;GAClB,gBAAgB;GAChB,eAAe;GACf,cAAc;GACd,aAAa;GACb,gBAAgB;GAChB,cAAc;GACd,cAAc;GACd,mBAAmB;GACnB,WAAW;GACX,UAAU;EACZ,EAAE;EACF,KAAK,MAAM,OAAO,UAChB,IAAI,QAAQ,WAAW,IAAI,EAAE,GAC3B,MAAM,IAAI,QACR,2BACA,aAAa,IAAI,GAAG,iBACtB;EAGJ,KAAK,MAAM,OAAO,UAAU;GAC1B,IAAI,KAAK,KAAK,GAAG;GACjB,UAAU,IAAI,IAAI,IAAI,GAAG;GACzB,QAAQ,WAAW,GAAG;EACxB;EACA,OAAO;CACT;;CAGA,MAAM,wBACJ,WACA,eACS;EACT,MAAM,SAAS,GAAG,UAAU;EAC5B,KAAK,MAAM,CAAC,KAAK,aAAa,WAAW;GACvC,IAAI,CAAC,IAAI,WAAW,MAAM,KAAK,SAAS,SAAS,YAAY;GAC7D,UAAU,OAAO,GAAG;GACpB,kBAAkB,OAAO,GAAG,IAAI,QAAQ,SAAS,OAAO;EAC1D;EACA,KAAK,MAAM,CAAC,KAAK,aAAa,qBAAqB;GACjD,IAAI,CAAC,IAAI,WAAW,MAAM,KAAK,SAAS,SAAS,YAAY;GAC7D,oBAAoB,OAAO,GAAG;GAC9B,kBAAkB,OAAO,GAAG;EAC9B;CACF;CAEA,MAAM,eACJ,WACA,aACA,cACA,yBACmB;EACnB,MAAM,MAAM,YAAY,WAAW,WAAW;EAC9C,MAAM,aAAa,aAAa,SAAS;EACzC,MAAM,mBAAmB,wBAAwB;EACjD,MAAM,SAAS,UAAU,IAAI,GAAG;EAChC,MAAM,OAAO,UAAU,OAAO,SAAS,aAAa,SAAS,KAAA;EAC7D,IAAI,YACF,SAAS,qBAAqB,KAAA,KAAa,KAAK,SAAS,oBACrD,OACA;EACN,IAAI,qBAAqB,KAAA,GAAW;GAClC,MAAM,SAAS,GAAG,IAAI;GACtB,KAAK,MAAM,CAAC,eAAe,aAAa,qBACtC,IACE,cAAc,WAAW,MAAM,KAC/B,SAAS,SAAS,cAClB,SAAS,SAAS,qBACjB,CAAC,aAAa,SAAS,QAAQ,UAAU,QAE1C,YAAY;EAGlB;EACA,MAAM,WAAW,YACb;GAAE,OAAO,UAAU;GAAO,OAAO,gBAAgB,UAAU,KAAK;EAAE,IAClE;EACJ,MAAM,aAAa,KAAK,IAAI,UAAU,SAAS,GAAG,aAAa,CAAC;EAChE,OAAO;GACL,WAAW,MAAM,SAAS;GAC1B;GACA,SAAS,SAAS,IAAI,SAAS,CAAC,EAAE,QAAQ,CAAC,EAAA,CACxC,QACE,QACC,IAAI,QAAQ,eACX,iBAAiB,KAAA,KAAa,IAAI,SAAS,aAChD,CAAC,CACA,IAAI,OAAO;GACd,GAAI,aAAa,IAAI,EAAE,WAAW,IAAI,CAAC;EACzC;CACF;CAEA,OAAO;EACL,MAAM,OAAO,WAAW,QAAQ,eAAe;GAC7C,IAAI,OAAO,WAAW,GAAG,OAAO,aAAa,WAAW,CAAC,CAAC;GAK1D,MAAM,WAAW,cAAc,WAAW,MAAM;GAChD,IAAI,SAAS,SAAS,GAAG;IACvB,IAAI,SAAS,WAAW,OAAO,QAC7B,OAAO,aACL,WACA,iBAAiB,QAAQ,SAAS,IAAI,QAAQ,CAAC,CACjD;IAEF,MAAM,IAAI,QACR,2BACA,eAAe,SAAS,OAAO,wBAAwB,OAAO,SAAS,SAAS,OAAO,cACzF;GACF;GAEA,MAAM,cAAc,eAAe;GACnC,IAAI,gBAAgB,KAAA,KAAa,eAAe,aAAa,SAAS,GACpE,MAAM,oBACJ,6BAA6B,YAAY,2BAA2B,UAAU,EAChF;GAIF,KAAK,MAAM,SAAS,QAClB,IAAI,MAAM,OAAO,mBAAmB,WAAW,MAAM,KAAK;GAG5D,MAAM,MAAM,MAAM,IAAI;GACtB,MAAM,WAAW,OAAO,WAAW,QAAQ,GAAG;GAC9C,cAAc,WAAW,QAAQ;GACjC,OAAO,aAAa,WAAW,SAAS,IAAI,QAAQ,CAAC;EACvD;EAEA,MAAM,MAAM,EAAE,WAAW,aAAa,SAAS;GAC7C,IAAI,OAAO,mBAAmB,WAAW,KAAK;GAC9C,MAAM,MAAM,SAAS,IAAI,SAAS;GAClC,MAAM,OAAO,OAAO,GAAG;GACvB,MAAM,aAAa,KAAK,cAAc;GACtC,IAAI,gBAAgB,KAAA,KAAa,eAAe,cAAc,GAC5D,OAAO;IAAE,SAAS;IAAM,OAAO;IAAM;GAAW;GAElD,IAAI,gBAAgB,KAAA,KAAa,gBAAgB,MAC/C,OAAO;IAAE,SAAS;IAAO,OAAO;IAAM;GAAW;GAEnD,IAAI,SAAS,KAAK,eAAe,MAC/B,OAAO;IAAE,SAAS;IAAM,OAAO;IAAM;GAAW;GAElD,MAAM,CAAC,UAAU,OACf,WACA,CAAC;IAAE,MAAM;IAAkB,SAAS;IAAM,SAAS;GAAK,CAAC,GACzD,MAAM,IAAI,CACZ;GACA,MAAM,SAAS,CAAC,CAAC,aAAa,OAAQ;GAEtC,SAAS,OAAO,SAAS;GACzB,cAAc,WAAW,CAAC,MAAO,CAAC;GAClC,OAAO;IAAE,SAAS;IAAM,OAAO,OAAQ;IAAO,YAAY,OAAQ;GAAM;EAC1E;EAEA,MAAM,QAAQ,WAAW;GACvB,MAAM,MAAM,SAAS,IAAI,SAAS;GAClC,IAAI,CAAC,OAAO,IAAI,UAAU,IAAI,aAAa,GACzC,OAAO;IAAE,SAAS;IAAG,MAAM;GAAK;GAElC,MAAM,UAAU,IAAI,KAAK,OACvB,GACA,KAAK,IAAI,eAAe,IAAI,aAAa,IAAI,IAAI,MAAM,CACzD;GACA,IAAI,UAAU,QAAQ;GACtB,KAAK,MAAM,OAAO,SAAS;IAEzB,IAAI,UAAU,IAAI,IAAI,EAAE,MAAM,KAAK,UAAU,OAAO,IAAI,EAAE;IAC1D,oBAAoB,WAAW,IAAI,KAAK;GAC1C;GACA,MAAM,OAAO,IAAI,WAAW,IAAI,aAAa;GAE7C,IAAI,MAAM,qBAAqB,WAAW,IAAI,UAAU;GACxD,OAAO;IAAE,SAAS,QAAQ;IAAQ;GAAK;EACzC;EAEA,MAAM,KAAK,WAAW,MAAM;GAC1B,MAAM,MAAM,SAAS,IAAI,SAAS;GAClC,IAAI,CAAC,KAAK,OAAO,CAAC;GAClB,MAAM,OAAO,OAAO,GAAG;GACvB,MAAM,QAAQ,KAAK,IACjB,MAAM,cAAc,GACpB,IAAI,aAAa,GACjB,IAAI,MACN;GACA,MAAM,UAAU,KAAK,IAAI,MAAM,gBAAgB,MAAM,IAAI;GACzD,IAAI,WAAW,OAAO,OAAO,CAAC;GAC9B,OAAO,IAAI,KACR,MAAM,QAAQ,IAAI,QAAQ,UAAU,IAAI,MAAM,CAAC,CAC/C,IAAI,QAAQ;EACjB;EAEA,MAAM,eAAe,EACnB,WACA,QACA,OACA,aACA,kBACC;GACD,MAAM,YAAY,MAAM,IAAI;GAC5B,MAAM,MAAM,UAAU,QAAQ;GAC9B,MAAM,YAAY,IAAI,KAAK,eAAe,MAAM,KAAK;GACrD,MAAM,WAAW,IAAI,IAAI,kBAAkB,CAAC,CAAC;GAC7C,MAAM,WAAkB,CAAC;GACzB,IAAI,UAAuB;GAE3B,KAAK,MAAM,OAAO,WAAW,SAAS,CAAC,CAAC,MAAM,OAAO,GAAG;IACtD,IAAI,IAAI,aAAa,QAAQ,SAAS,IAAI,IAAI,KAAK,GAAG;IACtD,IAAI,IAAI,kBAAkB,IAAI,eAAe,QAAQ,IAAI,KAAK;KAC5D,IAAI,CAAC,WAAW,IAAI,iBAAiB,SACnC,UAAU,IAAI,KAAK,IAAI,cAAc;KAEvC;IACF;IACA,SAAS,KAAK,GAAG;GACnB;GAEA,IAAI,SAAS,WAAW,GACtB,OAAO,UAAU;IAAE,SAAS;IAAQ;GAAQ,IAAI,EAAE,SAAS,UAAU;GAEvE,SAAS,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;GACzC,MAAM,aAAa,aAAa,SAAS;GACzC,OAAO;IACL,SAAS;IACT,QAAQ,SAAS,KAAK,QAAQ;KAC5B,MAAM,UAAU,MAAM,KAAK,QAAQ,WAAW,SAAS;KACvD,IAAI,aAAa,GAAG,QAAQ,aAAa;KACzC,OAAO;IACT,CAAC;GACH;EACF;EAEA,MAAM,YAAY,EAAE,WAAW,QAAQ,QAAQ,OAAO,eAAe;GACnE,MAAM,MAAM,MAAM,IAAI;GACtB,MAAM,YAAY,IAAI,KAAK,eAAe,IAAI,QAAQ,IAAI,KAAK;GAC/D,MAAM,aAAa,aAAa,SAAS;GACzC,MAAM,UAAoB,CAAC;GAC3B,MAAM,aAAuB,CAAC;GAC9B,KAAK,MAAM,EAAE,OAAO,aAAa,OAAO,UACrC,GAAG,MAAM,EAAE,QAAQ,EAAE,KACxB,GAAG;IACD,IAAI,SAAS,YAAY;KACvB,WAAW,KAAK,KAAK;KACrB;IACF;IACA,MAAM,MAAM,MAAM,WAAW,KAAK;IAClC,IAAI,CAAC,KAAK;IACV,IAAI,IAAI,eAAe,SAAS;KAC9B,WAAW,KAAK,IAAI,KAAK;KACzB;IACF;IACA,IACE,IAAI,gBAAgB,QACpB,IAAI,aAAa,QACjB,IAAI,gBAAgB,UACpB,IAAI,mBAAmB,QACvB,IAAI,iBAAiB,KACrB;KACA,IAAI,iBAAiB,IAAI,KAAK,SAAS;KACvC,QAAQ,KAAK,IAAI,KAAK;IACxB;GACF;GACA,OAAO;IAAE;IAAS;GAAW;EAC/B;EAEA,MAAM,gBAAgB,EAAE,WAAW,OAAO,SAAS,UAAU;GAC3D,IAAI,SAAS,aAAa,SAAS,GAAG,OAAO,EAAE,SAAS,aAAa;GACrE,MAAM,SAAS,KAAK,WAAW,KAAK;GACpC,MAAM,QAAQ;IAAE;IAAO;GAAQ;GAC/B,IAAI,OAAO,gBAAgB,MAAM;IAC/B,IAAI,OAAO,uBAAuB,SAChC,OAAO,EAAE,SAAS,aAAa;IAEjC,MAAM,eAAe,OAAO,KAAK,UAAU,MAAM,EAAE;IACnD,IACE,OAAO,qBAAqB,QAC5B,OAAO,iBAAiB,WAAW,aAAa,UAChD,OAAO,iBAAiB,MACrB,IAAI,WAAW,OAAO,aAAa,OACtC,GAEA,MAAM,IAAI,QACR,2BACA,2DACF;IAEF,MAAM,WAAW,cAAc,WAAW,MAAM;IAChD,IACE,SAAS,WAAW,OAAO,UAC3B,SAAS,MACN,QACC,IAAI,OAAO,UAAU,SAAS,IAAI,MAAM,YAAY,OACxD,GAEA,MAAM,IAAI,QACR,2BACA,2DACF;IAEF,OAAO;KACL,SAAS;KACT,QAAQ,iBAAiB,QAAQ,SAAS,IAAI,QAAQ,CAAC;IACzD;GACF;GACA,IACE,OAAO,iBAAiB,WACxB,OAAO,aAAa,QACpB,OAAO,gBAAgB,MAEvB,OAAO,EAAE,SAAS,aAAa;GAIjC,IADiB,cAAc,WAAW,MAC/B,CAAC,CAAC,SAAS,GACpB,MAAM,IAAI,QACR,2BACA,oDACF;GAEF,MAAM,MAAM,MAAM,IAAI;GACtB,MAAM,WAAW,OAAO,WAAW,QAAQ,KAAK,KAAK;GACrD,OAAO,cAAc,IAAI,KAAK,GAAG;GACjC,OAAO,qBAAqB;GAC5B,OAAO,mBAAmB,OAAO,KAAK,UAAU,MAAM,EAAE;GACxD,OAAO,cAAc;GACrB,OAAO,iBAAiB;GACxB,OAAO,WAAW,MAAM;GACxB,oBAAoB,WAAW,KAAK;GACpC,cAAc,WAAW,QAAQ;GACjC,OAAO;IAAE,SAAS;IAAa,QAAQ,SAAS,IAAI,QAAQ;GAAE;EAChE;EAEA,MAAM,YAAY,EAAE,WAAW,OAAO,SAAS,OAAO,eAAe;GACnE,IAAI,SAAS,aAAa,SAAS,GACjC,OAAO;IAAE,SAAS;IAAc,cAAc;GAAE;GAElD,MAAM,MAAM,KAAK,WAAW,KAAK;GACjC,IACE,IAAI,eACJ,IAAI,iBAAiB,WACpB,IAAI,gBAAgB,QAAQ,IAAI,sBAAsB,SAEvD,OAAO;IAAE,SAAS;IAAc,cAAc,IAAI;GAAa;GAEjE,IAAI,IAAI,sBAAsB,WAAW,IAAI,gBAAgB,MAC3D,OAAO;IACL,SAAS,IAAI,WAAW,kBAAkB;IAC1C,cAAc,IAAI;GACpB;GAEF,IAAI,IAAI,UACN,OAAO;IAAE,SAAS;IAAiB,cAAc,IAAI;GAAa;GAEpE,IAAI,gBAAgB;GACpB,IAAI,YAAY;GAChB,MAAM,WAAW,MAAM,IAAI;GAC3B,IAAI,eAAe,IAAI,KAAK,QAAQ;GACpC,IAAI,oBAAoB;GACxB,IAAI,cAAc;GAClB,IAAI,iBAAiB;GACrB,IAAI,IAAI,gBAAgB,aAAa;IACnC,IAAI,WAAW,IAAI,KAAK,QAAQ;IAChC,WAAW,SAAS,CAAC,CAAC,MAAM,OAAO,IAAI,KAAK;IAC5C,oBAAoB,WAAW,KAAK;IACpC,OAAO;KACL,SAAS;KACT,cAAc,IAAI;IACpB;GACF;GACA,OAAO;IAAE,SAAS;IAAU,cAAc,IAAI;GAAa;EAC7D;EAEA,MAAM,YAAY,WAAW;GAC3B,MAAM,MAAM,SAAS,IAAI,SAAS;GAClC,QAAQ,KAAK,QAAQ,CAAC,EAAA,CACnB,QACE,QACC,IAAI,QAAQ,IAAK,cACjB,IAAI,gBAAgB,QACpB,IAAI,aAAa,IACrB,CAAC,CACA,IAAI,QAAQ;EACjB;EAEA,MAAM,QAAQ,EAAE,WAAW,OAAO,UAAU;GAC1C,MAAM,MACJ,QAAQ,aAAa,SAAS,IAAI,MAAM,WAAW,KAAK,IAAI,KAAA;GAC9D,IAAI,CAAC,OAAO,IAAI,gBAAgB,QAAQ,IAAI,aAAa,MACvD,OAAO;IAAE,UAAU;IAAO,YAAY,WAAW,SAAS;GAAE;GAE9D,IAAI,WAAW,QAAQ;IACrB,IAAI,cAAc,MAAM,IAAI;IAC5B,OAAO,WAAW,GAAG;GACvB,OAAO;IACL,IAAI,WAAW;IACf,IAAI,eAAe;IACnB,MAAM,QAAQ,WAAW,SAAS;IAClC,MAAM,QAAQ,IAAI,SAAS,OAAO,KAAA,IAAY,MAAM,MAAM,IAAI,IAAI,IAAI;IACtE,IAAI,IAAI,SAAS,QAAQ,OAAO,KAAK,MAAM,UAAU,KACnD,MAAM,MAAM,IAAI,IAAI,OAAO,GAAG;GAElC;GACA,OAAO;IAAE,UAAU;IAAM,YAAY,WAAW,SAAS;GAAE;EAC7D;EAEA,MAAM,UAAU,WAAW,aAAa,cAAc;GACpD,OAAO,YACL,WACA,aACA,cAAc,cACd,cAAc,oBAChB;EACF;EAEA,MAAM,WAAW,UAAU,aAAa;GACtC,OAAO,SAAS,KAAK,YACnB,YACE,QAAQ,WACR,aACA,QAAQ,cACR,QAAQ,oBACV,CACF;EACF;EAEA,MAAM,aAAa,WAAW,aAAa,QAAQ;GACjD,MAAM,MAAM,YAAY,WAAW,WAAW;GAC9C,MAAM,aAAa,aAAa,SAAS;GACzC,KAAK,MAAM,SAAS,OAAO,UAAU,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK,GAAG;IAChE,IAAI,MAAM,QAAQ,YAAY;IAC9B,MAAM,aAAa,cAAc,WAAW,aAAa,MAAM,KAAK;IACpE,KAAK,MAAM,cAAc,MAAM,mBAAmB,CAAC,GAAG;KACpD,MAAM,QAAQ,MAAM,WAAW,UAAU;KACzC,IACE,CAAC,SACD,MAAM,SAAS,cACf,MAAM,gBAAgB,QACtB,MAAM,aAAa,MAEnB;KAEF,MAAM,SAAS,YAAY,WAAW,UAAU;KAChD,IAAI,SAAS,aAAa,IAAI,MAAM;KACpC,IAAI,CAAC,QAAQ;MACX,yBAAS,IAAI,IAAI;MACjB,aAAa,IAAI,QAAQ,MAAM;KACjC;KACA,IAAI,CAAC,OAAO,IAAI,UAAU,GAAG;MAC3B,OAAO,IAAI,UAAU;MACrB,kBAAkB,IAChB,aACC,kBAAkB,IAAI,UAAU,KAAK,KAAK,CAC7C;KACF;IACF;IAEA,MAAM,UAAU,UAAU,IAAI,GAAG;IACjC,IAAI,CAAC,WAAW,MAAM,SAAS,QAAQ,OAAO;KAC5C,IACE,WACA,MAAM,QAAQ,QAAQ,SACtB,QAAQ,SAAS,YACjB;MACA,MAAM,oBAAoB,cACxB,WACA,aACA,QAAQ,KACV;MACA,KAAK,kBAAkB,IAAI,iBAAiB,KAAK,KAAK,GACpD,oBAAoB,IAAI,mBAAmB;OACzC,OAAO,QAAQ;OACf,OAAO,gBAAgB,QAAQ,KAAK;OACpC,WAAW,IAAI,KAAK,QAAQ,SAAS;MACvC,CAAC;KAEL;KACA,UAAU,IAAI,KAAK;MACjB,OAAO,MAAM;MACb,OAAO,gBAAgB,MAAM,KAAK;MAClC,WAAW,MAAM,IAAI;KACvB,CAAC;KACD,oBAAoB,OAAO,UAAU;IACvC,OAAO,IACL,MAAM,QAAQ,QAAQ,UACrB,kBAAkB,IAAI,UAAU,KAAK,KAAK,GAE3C,oBAAoB,IAAI,YAAY;KAClC,OAAO,MAAM;KACb,OAAO,gBAAgB,MAAM,KAAK;KAClC,WAAW,MAAM,IAAI;IACvB,CAAC;GAEL;EACF;EAEA,UAAU;GACR,MAAM,IAAI,IAAI,aAAa,QAAQ,MAAM;IACvC,IAAI,eAAe,aAAa,IAAI,EAAE;IACtC,IAAI,CAAC,cAAc;KACjB,+BAAe,IAAI,IAAI;KACvB,aAAa,IAAI,IAAI,YAAY;IACnC;IACA,IAAI,SAAS,aAAa,IAAI,WAAW;IACzC,IAAI,CAAC,QAAQ;KACX,yBAAS,IAAI,IAAI;KACjB,aAAa,IAAI,aAAa,MAAM;IACtC;IAIA,MAAM,cAAc,MAAM,IAAI,CAAC,CAAC,QAAQ,IAAI,KAAK;IAGjD,MAAM,UAAmC,gBAAgB;IACzD,IAAI,eAAe;IACnB,KAAK,MAAM,CAAC,OAAO,UAAU,OAAO,QAAQ,MAAM,GAAG;KAGnD,MAAM,WAAW,OAAO,IAAI,KAAK;KACjC,IAAI,YAAY,SAAS,KAAK,KAAK,IAAI;KACvC,IAAI,UAAU,MACZ,OAAO,OAAO,KAAK;UAEnB,OAAO,IAAI,OAAO;MAChB,OAAO,gBAAgB,KAAK;MAC5B,MAAM,KAAK;MACX,IAAI,IAAI,KAAK,KAAK,EAAE;MACpB,WAAW,IAAI,KAAK,WAAW;KACjC,CAAC;KAEH,QAAQ,SAAS,gBAAgB,KAAK;KACtC,gBAAgB;IAClB;IACA,IAAI,OAAO,SAAS,GAAG,aAAa,OAAO,WAAW;IACtD,IAAI,aAAa,SAAS,GAAG,aAAa,OAAO,EAAE;IAInD,IAAI,iBAAiB,GAAG;IACxB,MAAM,OAAO,oBAAoB,IAAI,EAAE;IACvC,IAAI,CAAC,MAAM;IACX,MAAM,QAAuB;KAC3B;KACA,QAAQ;KACR,MAAM,KAAK;KACX,IAAI,IAAI,KAAK,KAAK,EAAE;IACtB;IACA,KAAK,MAAM,YAAY,MAAM,SAAS,KAAK;GAC7C;GAEA,MAAM,KAAK,IAAI;IACb,MAAM,eAAe,aAAa,IAAI,EAAE;IACxC,IAAI,CAAC,cAAc,OAAO,CAAC;IAC3B,MAAM,MAAM,MAAM,IAAI;IACtB,MAAM,OAAsB,CAAC;IAC7B,KAAK,MAAM,CAAC,aAAa,WAAW,cAAc;KAChD,KAAK,MAAM,CAAC,OAAO,UAAU,QAAQ;MAGnC,IAAI,MAAM,aAAa,KAAK;OAC1B,OAAO,OAAO,KAAK;OACnB;MACF;MACA,KAAK,KAAK;OACR;OACA;OACA,OAAO,gBAAgB,MAAM,KAAK;OAClC,MAAM,MAAM;OACZ,IAAI,IAAI,KAAK,MAAM,EAAE;OACrB,WAAW,IAAI,KAAK,MAAM,SAAS;MACrC,CAAC;KACH;KACA,IAAI,OAAO,SAAS,GAAG,aAAa,OAAO,WAAW;IACxD;IACA,IAAI,aAAa,SAAS,GAAG,aAAa,OAAO,EAAE;IACnD,OAAO;GACT;GAEA,UAAU,IAAI,SAAS;IACrB,IAAI,OAAO,oBAAoB,IAAI,EAAE;IACrC,IAAI,CAAC,MAAM;KACT,uBAAO,IAAI,IAAI;KACf,oBAAoB,IAAI,IAAI,IAAI;IAClC;IACA,KAAK,IAAI,OAAO;IAChB,aAAa;KACX,KAAK,OAAO,OAAO;KACnB,IAAI,KAAK,SAAS,GAAG,oBAAoB,OAAO,EAAE;IACpD;GACF;EACF;EAEA,OAAO,WAAW,MAAM;GACtB,MAAM,aAAa,MAAM,cAAc;GACvC,OAAO,EACL,CAAC,OAAO,iBAAuC;IAC7C,IAAI,OAAO,KAAK,IAAI,YAAY,aAAa,SAAS,IAAI,CAAC;IAC3D,IAAI,OAA4B;IAChC,IAAI,SAAS;IAEb,MAAM,cAAoB;KACxB,OAAO;IACT;IACA,IAAI,OAAO,kBAAkB,IAAI,SAAS;IAC1C,IAAI,CAAC,MAAM;KACT,uBAAO,IAAI,IAAI;KACf,kBAAkB,IAAI,WAAW,IAAI;IACvC;IACA,KAAK,IAAI,KAAK;IACd,MAAM,aAAmB;KACvB,IAAI,QAAQ;KACZ,SAAS;KACT,KAAK,OAAO,KAAK;KACjB,IAAI,KAAK,SAAS,GAAG,kBAAkB,OAAO,SAAS;KACvD,OAAO;IACT;IAEA,OAAO;KACL,MAAM,OAAuC;MAC3C,IAAI;OACF,SAAS;QACP,IAAI,QAAQ,OAAO;SAAE,OAAO,KAAA;SAAW,MAAM;QAAK;QAClD,MAAM,MAAM,SAAS,IAAI,SAAS;QAElC,MAAM,MAAM,KAAK,KAAK,KAAK,IAAI,GAAG,OAAO,IAAI,MAAM;QACnD,IAAI,KAAK;SACP,MAAM,QAAQ,SAAS,GAAG;SAC1B,OAAO,IAAI;SACX,OAAO;UAAE;UAAO,MAAM;SAAM;QAC9B;QAEA,MAAM,IAAI,SAAe,YAAY;SACnC,OAAO;QACT,CAAC;QACD,OAAO;OACT;MACF,SAAS,OAAO;OACd,KAAK;OACL,MAAM;MACR;KACF;KACA,MAAM,SAAyC;MAC7C,KAAK;MACL,OAAO;OAAE,OAAO,KAAA;OAAW,MAAM;MAAK;KACxC;IACF;GACF,EACF;EACF;CACF;AACF"}
1
+ {"version":3,"file":"store-memory.js","names":[],"sources":["../src/store-memory.ts"],"sourcesContent":["/**\n * experimental-a2/store-memory — in-memory store backend (the test default).\n *\n * Implements the A2Store interface with zero dependencies. See\n * specs/a2-implementation.md §3 for the contract; the conformance suite\n * in test/conformance is the executable version of it.\n */\n\nimport type { PresencePatch } from './contract.ts'\nimport { A2Error, supersededAttemptError } from './errors.ts'\nimport { idempotentReplay } from './idempotent-replay.ts'\nimport { nullProtoRecord } from './internal.ts'\nimport { CLEAR_EVENT_TYPE, sessionClearedError } from './session-clear.ts'\nimport {\n RANDOM_IDS,\n SYSTEM_CLOCK,\n type A2Store,\n type AppendEvent,\n type Clock,\n type Event,\n type EventCause,\n type IdSource,\n type PresenceRow,\n type StoredEvent,\n type StoreStateRead,\n} from './store.ts'\n\nexport type MemoryStoreOptions = {\n /** Injectable clock — every stored timestamp comes from here. */\n clock?: Clock\n /** Injectable id source for generated event ids. */\n ids?: IdSource\n}\n\ntype Row = {\n id: string\n type: string\n payload: unknown\n index: number\n sessionId: string\n createdAt: Date\n cause: EventCause | null\n lane: string | null\n processedAt: Date | null\n processedByAttempt: number | null\n returnedEventIds: string[] | null\n firstClaimedAt: Date | null\n lastClaimedAt: Date | null\n attemptCount: number\n claimHolder: string | null\n claimExpiresAt: Date | null\n failureCount: number\n lastFailedAt: Date | null\n lastFailedAttempt: number | null\n lastError: string | null\n failedAt: Date | null\n}\n\ntype PresenceEntry = {\n value: unknown\n seen: number\n at: Date\n expiresAt: Date\n}\n\ntype LaneQueue = { rows: Row[]; head: number }\ntype SessionDispatch = {\n ready: Map<number, Row>\n lanes: Map<string, LaneQueue>\n}\n\n/** Contiguous rows; `reclaim` removes from the front below `clearIndex`. */\ntype SessionLog = {\n rows: Row[]\n /** Index of the event before `rows[0]`. */\n offset: number\n /** Latest clear marker, or 0. */\n clearIndex: number\n}\n\nconst RECLAIM_BATCH = 256\n\nconst headOf = (log: SessionLog | undefined): number =>\n log ? log.offset + log.rows.length : 0\n\nconst toStored = (row: Row): StoredEvent => ({\n id: row.id,\n type: row.type,\n payload: structuredClone(row.payload),\n index: row.index,\n sessionId: row.sessionId,\n createdAt: new Date(row.createdAt),\n cause: row.cause ? { ...row.cause } : null,\n lane: row.lane,\n processedAt: row.processedAt ? new Date(row.processedAt) : null,\n processedByAttempt: row.processedByAttempt,\n returnedEventIds: row.returnedEventIds ? [...row.returnedEventIds] : null,\n firstClaimedAt: row.firstClaimedAt ? new Date(row.firstClaimedAt) : null,\n lastClaimedAt: row.lastClaimedAt ? new Date(row.lastClaimedAt) : null,\n attemptCount: row.attemptCount,\n claimHolder: row.claimHolder,\n claimExpiresAt: row.claimExpiresAt ? new Date(row.claimExpiresAt) : null,\n failureCount: row.failureCount,\n lastFailedAt: row.lastFailedAt ? new Date(row.lastFailedAt) : null,\n lastFailedAttempt: row.lastFailedAttempt,\n lastError: row.lastError,\n failedAt: row.failedAt ? new Date(row.failedAt) : null,\n})\n\nconst toEvent = (row: Row): Event => ({\n id: row.id,\n type: row.type,\n payload: structuredClone(row.payload),\n index: row.index,\n sessionId: row.sessionId,\n createdAt: new Date(row.createdAt),\n})\n\nconst snapshotKey = (sessionId: string, reducerName: string): string =>\n `${sessionId}\\u0000${reducerName}`\n\nconst eventPinKey = (sessionId: string, index: number): string =>\n `${sessionId}\\u0000${index}`\n\nexport function memory(options: MemoryStoreOptions = {}): A2Store {\n const clock = options.clock ?? SYSTEM_CLOCK\n const generateId = options.ids ?? RANDOM_IDS\n\n const sessions = new Map<string, SessionLog>()\n const dispatch = new Map<string, SessionDispatch>()\n /** Global unique index on event ids, like the SQL schema's. */\n const byEventId = new Map<string, Row>()\n /** Keyed by `${sessionId}\\u0000${reducerName}` — a pure cache. */\n const snapshots = new Map<\n string,\n { index: number; state: unknown; updatedAt: Date }\n >()\n const historicalSnapshots = new Map<\n string,\n { index: number; state: unknown; updatedAt: Date }\n >()\n const snapshotPins = new Map<string, Set<string>>()\n const snapshotPinCounts = new Map<string, number>()\n const streamSubscribers = new Map<string, Set<(row: Row) => void>>()\n /** ns → participant → field → latest surviving write. */\n const presenceRows = new Map<\n string,\n Map<string, Map<string, PresenceEntry>>\n >()\n const presenceSubscribers = new Map<\n string,\n Set<(patch: PresencePatch) => void>\n >()\n\n const notifyStreams = (sessionId: string, rows: Row[]): void => {\n const subs = streamSubscribers.get(sessionId)\n if (!subs) return\n for (const listener of subs) {\n for (const row of rows) listener(row)\n }\n }\n\n const logOf = (sessionId: string): SessionLog => {\n let log = sessions.get(sessionId)\n if (!log) {\n log = { rows: [], offset: 0, clearIndex: 0 }\n sessions.set(sessionId, log)\n }\n return log\n }\n\n const rowAt = (sessionId: string, index: number): Row | undefined => {\n const log = sessions.get(sessionId)\n return log && index > log.offset\n ? log.rows[index - log.offset - 1]\n : undefined\n }\n\n const clearIndexOf = (sessionId: string): number =>\n sessions.get(sessionId)?.clearIndex ?? 0\n\n /** The row owning `id`, ignoring this session's rows below its clear. */\n const ownerOf = (sessionId: string, id: string): Row | undefined => {\n const row = byEventId.get(id)\n return row?.sessionId === sessionId && row.index < clearIndexOf(sessionId)\n ? undefined\n : row\n }\n\n const checkpointKey = (\n sessionId: string,\n reducerName: string,\n index: number,\n ): string => `${snapshotKey(sessionId, reducerName)}\\u0000${index}`\n\n const releaseSnapshotPins = (sessionId: string, eventIndex: number): void => {\n const pinKey = eventPinKey(sessionId, eventIndex)\n const checkpoints = snapshotPins.get(pinKey)\n if (!checkpoints) return\n for (const key of checkpoints) {\n const next = (snapshotPinCounts.get(key) ?? 1) - 1\n if (next === 0) {\n snapshotPinCounts.delete(key)\n historicalSnapshots.delete(key)\n } else {\n snapshotPinCounts.set(key, next)\n }\n }\n snapshotPins.delete(pinKey)\n }\n\n const dispatchOf = (sessionId: string): SessionDispatch => {\n let state = dispatch.get(sessionId)\n if (!state) {\n state = { ready: new Map(), lanes: new Map() }\n dispatch.set(sessionId, state)\n }\n return state\n }\n\n const enqueue = (sessionId: string, row: Row): void => {\n if (row.processedAt !== null) return\n const state = dispatchOf(sessionId)\n if (row.lane === null) {\n state.ready.set(row.index, row)\n return\n }\n let queue = state.lanes.get(row.lane)\n if (!queue) {\n queue = { rows: [], head: 0 }\n state.lanes.set(row.lane, queue)\n }\n queue.rows.push(row)\n if (queue.rows.length === 1) state.ready.set(row.index, row)\n }\n\n const settle = (sessionId: string, row: Row): void => {\n const state = dispatchOf(sessionId)\n state.ready.delete(row.index)\n if (row.lane === null) return\n const queue = state.lanes.get(row.lane)!\n if (queue.rows[queue.head] !== row) return\n queue.head += 1\n if (queue.head === queue.rows.length) {\n state.lanes.delete(row.lane)\n return\n }\n const next = queue.rows[queue.head]!\n if (next.failedAt === null) state.ready.set(next.index, next)\n }\n\n const find = (sessionId: string, index: number): Row => {\n const row = rowAt(sessionId, index)\n if (!row) {\n throw new TypeError(\n `no event at index ${index} in session '${sessionId}'`,\n )\n }\n return row\n }\n\n const hasPending = (sessionId: string): boolean => {\n const log = sessions.get(sessionId)\n return (log?.rows ?? []).some(\n (row) => row.index > log!.clearIndex && row.processedAt === null,\n )\n }\n\n const appendResult = (sessionId: string, events: StoredEvent[]) => ({\n events,\n hasPending: hasPending(sessionId),\n })\n\n /** The attempt-currency fence shared by handler appends and clears. */\n const assertCurrentCause = (sessionId: string, cause: EventCause): void => {\n if (cause.index <= clearIndexOf(sessionId)) {\n throw supersededAttemptError(sessionId, cause)\n }\n const parent = find(sessionId, cause.index)\n if (parent.attemptCount !== cause.attempt || parent.failedAt !== null) {\n throw supersededAttemptError(sessionId, cause)\n }\n }\n\n const claim = ({\n sessionId,\n row,\n holder,\n now,\n expiresAt,\n maxFailures,\n }: {\n sessionId: string\n row: Row\n holder: string\n now: Date\n expiresAt: Date\n maxFailures: number | undefined\n }): StoredEvent => {\n // A claim still held here lapsed: its attempt never finished.\n if (row.claimHolder !== null) {\n row.failureCount += 1\n if (maxFailures !== undefined && row.failureCount >= maxFailures) {\n // Advancing the attempt fences the lapsed one; nothing runs.\n row.attemptCount += 1\n row.failedAt = new Date(now)\n row.claimHolder = null\n row.claimExpiresAt = null\n dispatchOf(sessionId).ready.delete(row.index)\n releaseSnapshotPins(sessionId, row.index)\n return toStored(row)\n }\n }\n row.attemptCount += 1\n row.firstClaimedAt ??= new Date(now)\n row.lastClaimedAt = new Date(now)\n row.claimHolder = holder\n row.claimExpiresAt = new Date(expiresAt)\n return toStored(row)\n }\n\n const checkBatchIds = (\n sessionId: string,\n events: readonly (AppendEvent & { id?: string })[],\n ): Row[] => {\n const supplied = events.filter(\n (candidate): candidate is AppendEvent & { id: string } =>\n candidate.id !== undefined,\n )\n const suppliedIds = new Set(supplied.map((candidate) => candidate.id))\n if (suppliedIds.size !== supplied.length) {\n throw new A2Error(\n 'PARTIAL_DUPLICATE_BATCH',\n 'batch contains the same event id more than once',\n )\n }\n const existing = supplied\n .map((candidate) => ownerOf(sessionId, candidate.id))\n .filter((row): row is Row => row !== undefined)\n const foreign = existing.find((row) => row.sessionId !== sessionId)\n if (foreign) {\n throw new A2Error(\n 'PARTIAL_DUPLICATE_BATCH',\n `event id '${foreign.id}' already exists in another session`,\n )\n }\n return existing\n }\n\n const insert = (\n sessionId: string,\n events: readonly AppendEvent[],\n now: Date,\n cause?: EventCause,\n ): Row[] => {\n const log = logOf(sessionId)\n const base = headOf(log)\n const inserted = events.map((candidate, offset): Row => ({\n id: candidate.id ?? generateId(),\n type: candidate.type,\n payload: structuredClone(candidate.payload),\n index: base + 1 + offset,\n sessionId,\n createdAt: new Date(now),\n cause: cause\n ? { ...cause }\n : candidate.cause\n ? { ...candidate.cause }\n : null,\n lane: candidate.lane ?? null,\n processedAt: candidate.settled ? new Date(now) : null,\n processedByAttempt: null,\n returnedEventIds: null,\n firstClaimedAt: null,\n lastClaimedAt: null,\n attemptCount: 0,\n claimHolder: null,\n claimExpiresAt: null,\n failureCount: 0,\n lastFailedAt: null,\n lastFailedAttempt: null,\n lastError: null,\n failedAt: null,\n }))\n for (const row of inserted) {\n if (ownerOf(sessionId, row.id)) {\n throw new A2Error(\n 'PARTIAL_DUPLICATE_BATCH',\n `event id '${row.id}' already exists`,\n )\n }\n }\n for (const row of inserted) {\n log.rows.push(row)\n byEventId.set(row.id, row)\n enqueue(sessionId, row)\n }\n return inserted\n }\n\n /** Every cached fold of this session below its clear, head or historical. */\n const dropCheckpointsBelow = (\n sessionId: string,\n clearIndex: number,\n ): void => {\n const prefix = `${sessionId}\\u0000`\n for (const [key, snapshot] of snapshots) {\n if (!key.startsWith(prefix) || snapshot.index >= clearIndex) continue\n snapshots.delete(key)\n snapshotPinCounts.delete(`${key}\\u0000${snapshot.index}`)\n }\n for (const [key, snapshot] of historicalSnapshots) {\n if (!key.startsWith(prefix) || snapshot.index >= clearIndex) continue\n historicalSnapshots.delete(key)\n snapshotPinCounts.delete(key)\n }\n }\n\n const readStateOf = (\n sessionId: string,\n reducerName: string,\n throughIndex?: number,\n snapshotThroughIndex?: number,\n ): StoreStateRead => {\n const key = snapshotKey(sessionId, reducerName)\n const clearIndex = clearIndexOf(sessionId)\n const snapshotFrontier = snapshotThroughIndex ?? throughIndex\n const stored = snapshots.get(key)\n const head = stored && stored.index >= clearIndex ? stored : undefined\n let candidate =\n head && (snapshotFrontier === undefined || head.index <= snapshotFrontier)\n ? head\n : null\n if (snapshotFrontier !== undefined) {\n const prefix = `${key}\\u0000`\n for (const [historicalKey, snapshot] of historicalSnapshots) {\n if (\n historicalKey.startsWith(prefix) &&\n snapshot.index >= clearIndex &&\n snapshot.index <= snapshotFrontier &&\n (!candidate || snapshot.index > candidate.index)\n ) {\n candidate = snapshot\n }\n }\n }\n const snapshot = candidate\n ? { index: candidate.index, state: structuredClone(candidate.state) }\n : null\n const afterIndex = Math.max(snapshot?.index ?? 0, clearIndex - 1)\n return {\n headIndex: head?.index ?? null,\n snapshot,\n events: (sessions.get(sessionId)?.rows ?? [])\n .filter(\n (row) =>\n row.index > afterIndex &&\n (throughIndex === undefined || row.index <= throughIndex),\n )\n .map(toEvent),\n ...(clearIndex > 0 ? { clearIndex } : {}),\n }\n }\n\n return {\n async append(sessionId, events, appendOptions) {\n if (events.length === 0) return appendResult(sessionId, [])\n\n // Batch-scoped idempotency (a2-implementation.md §3): all ids\n // already present → lost-ack retry, return the original rows;\n // some present → the caller mixed sent and fresh events.\n const existing = checkBatchIds(sessionId, events)\n if (existing.length > 0) {\n if (existing.length === events.length) {\n return appendResult(\n sessionId,\n idempotentReplay(events, existing.map(toStored)),\n )\n }\n throw new A2Error(\n 'PARTIAL_DUPLICATE_BATCH',\n `batch mixes ${existing.length} already-appended and ${events.length - existing.length} fresh events`,\n )\n }\n\n const originIndex = appendOptions?.originIndex\n if (originIndex !== undefined && originIndex <= clearIndexOf(sessionId)) {\n throw sessionClearedError(\n `scheduled work from event ${originIndex} was cleared in session '${sessionId}'`,\n )\n }\n // Attempt-currency fence: a fresh handler append commits only while\n // its causal attempt is still the parent's latest (store.ts `append`).\n for (const event of events) {\n if (event.cause) assertCurrentCause(sessionId, event.cause)\n }\n\n const now = clock.now()\n const inserted = insert(sessionId, events, now)\n notifyStreams(sessionId, inserted)\n return appendResult(sessionId, inserted.map(toStored))\n },\n\n async clear({ sessionId, ifLastIndex, cause }) {\n if (cause) assertCurrentCause(sessionId, cause)\n const log = sessions.get(sessionId)\n const head = headOf(log)\n const clearIndex = log?.clearIndex ?? 0\n if (ifLastIndex !== undefined && clearIndex === ifLastIndex + 1) {\n return { cleared: true, index: head, clearIndex }\n }\n if (ifLastIndex !== undefined && ifLastIndex !== head) {\n return { cleared: false, index: head, clearIndex }\n }\n if (head === 0 || clearIndex === head) {\n return { cleared: true, index: head, clearIndex }\n }\n const [marker] = insert(\n sessionId,\n [{ type: CLEAR_EVENT_TYPE, payload: null, settled: true }],\n clock.now(),\n )\n logOf(sessionId).clearIndex = marker!.index\n // Every row is at or below the marker, so no dispatch state survives.\n dispatch.delete(sessionId)\n notifyStreams(sessionId, [marker!])\n return { cleared: true, index: marker!.index, clearIndex: marker!.index }\n },\n\n async reclaim(sessionId) {\n const log = sessions.get(sessionId)\n if (!log || log.offset >= log.clearIndex - 1) {\n return { deleted: 0, done: true }\n }\n const removed = log.rows.splice(\n 0,\n Math.min(RECLAIM_BATCH, log.clearIndex - 1 - log.offset),\n )\n log.offset += removed.length\n for (const row of removed) {\n // A reused id belongs to its new row now.\n if (byEventId.get(row.id) === row) byEventId.delete(row.id)\n releaseSnapshotPins(sessionId, row.index)\n }\n const done = log.offset === log.clearIndex - 1\n // Writes below the marker are dropped, so one sweep at the end suffices.\n if (done) dropCheckpointsBelow(sessionId, log.clearIndex)\n return { deleted: removed.length, done }\n },\n\n async read(sessionId, opts) {\n const log = sessions.get(sessionId)\n if (!log) return []\n const head = headOf(log)\n const after = Math.max(\n opts?.afterIndex ?? 0,\n log.clearIndex - 1,\n log.offset,\n )\n const through = Math.min(opts?.throughIndex ?? head, head)\n if (through <= after) return []\n return log.rows\n .slice(after - log.offset, through - log.offset)\n .map(toStored)\n },\n\n async claimAvailable({\n sessionId,\n holder,\n ttlMs,\n expiresAtMs,\n excludeIndexes,\n maxFailures,\n }) {\n const claimedAt = clock.now()\n const now = claimedAt.getTime()\n const expiresAt = new Date(expiresAtMs ?? now + ttlMs)\n const excluded = new Set(excludeIndexes ?? [])\n const eligible: Row[] = []\n let retryAt: Date | null = null\n\n for (const row of dispatchOf(sessionId).ready.values()) {\n if (row.failedAt !== null || excluded.has(row.index)) continue\n if (row.claimExpiresAt && row.claimExpiresAt.getTime() > now) {\n if (!retryAt || row.claimExpiresAt < retryAt) {\n retryAt = new Date(row.claimExpiresAt)\n }\n continue\n }\n eligible.push(row)\n }\n\n if (eligible.length === 0) {\n return retryAt ? { outcome: 'busy', retryAt } : { outcome: 'settled' }\n }\n eligible.sort((a, b) => a.index - b.index)\n const clearIndex = clearIndexOf(sessionId)\n return {\n outcome: 'claimed',\n events: eligible.map((row) => {\n const claimed = claim({\n sessionId,\n row,\n holder,\n now: claimedAt,\n expiresAt,\n maxFailures,\n })\n if (clearIndex > 0) claimed.clearIndex = clearIndex\n return claimed\n }),\n }\n },\n\n async renewClaims({ sessionId, holder, claims, ttlMs, expiresAtMs }) {\n const now = clock.now()\n const expiresAt = new Date(expiresAtMs ?? now.getTime() + ttlMs)\n const clearIndex = clearIndexOf(sessionId)\n const renewed: number[] = []\n const superseded: number[] = []\n for (const { index, attempt } of claims.toSorted(\n (a, b) => a.index - b.index,\n )) {\n if (index <= clearIndex) {\n superseded.push(index)\n continue\n }\n const row = rowAt(sessionId, index)\n if (!row) continue\n if (row.attemptCount > attempt) {\n superseded.push(row.index)\n continue\n }\n if (\n row.processedAt === null &&\n row.failedAt === null &&\n row.claimHolder === holder &&\n row.claimExpiresAt !== null &&\n row.claimExpiresAt > now\n ) {\n row.claimExpiresAt = new Date(expiresAt)\n renewed.push(row.index)\n }\n }\n return { renewed, superseded }\n },\n\n async completeAttempt({ sessionId, index, attempt, events }) {\n if (index <= clearIndexOf(sessionId)) return { outcome: 'superseded' }\n const parent = find(sessionId, index)\n const cause = { index, attempt }\n if (parent.processedAt !== null) {\n if (parent.processedByAttempt !== attempt) {\n return { outcome: 'superseded' }\n }\n const requestedIds = events.map((event) => event.id)\n if (\n parent.returnedEventIds === null ||\n parent.returnedEventIds.length !== requestedIds.length ||\n parent.returnedEventIds.some(\n (id, offset) => id !== requestedIds[offset],\n )\n ) {\n throw new A2Error(\n 'PARTIAL_DUPLICATE_BATCH',\n 'completed attempt does not match the returned event batch',\n )\n }\n const existing = checkBatchIds(sessionId, events)\n if (\n existing.length !== events.length ||\n existing.some(\n (row) =>\n row.cause?.index !== index || row.cause.attempt !== attempt,\n )\n ) {\n throw new A2Error(\n 'PARTIAL_DUPLICATE_BATCH',\n 'completed attempt does not match the returned event batch',\n )\n }\n return {\n outcome: 'completed',\n events: idempotentReplay(events, existing.map(toStored)),\n }\n }\n if (\n parent.attemptCount !== attempt ||\n parent.failedAt !== null ||\n parent.claimHolder === null\n ) {\n return { outcome: 'superseded' }\n }\n\n const existing = checkBatchIds(sessionId, events)\n if (existing.length > 0) {\n throw new A2Error(\n 'PARTIAL_DUPLICATE_BATCH',\n 'returned event batch contains already-appended ids',\n )\n }\n const now = clock.now()\n const inserted = insert(sessionId, events, now, cause)\n parent.processedAt = new Date(now)\n parent.processedByAttempt = attempt\n parent.returnedEventIds = events.map((event) => event.id)\n parent.claimHolder = null\n parent.claimExpiresAt = null\n settle(sessionId, parent)\n releaseSnapshotPins(sessionId, index)\n notifyStreams(sessionId, inserted)\n return { outcome: 'completed', events: inserted.map(toStored) }\n },\n\n async failAttempt({\n sessionId,\n index,\n attempt,\n error,\n maxFailures,\n retryAfterMs,\n }) {\n if (index <= clearIndexOf(sessionId)) {\n return { outcome: 'superseded', failureCount: 0 }\n }\n const row = find(sessionId, index)\n if (\n row.processedAt ||\n row.attemptCount !== attempt ||\n (row.claimHolder === null && row.lastFailedAttempt !== attempt)\n ) {\n return { outcome: 'superseded', failureCount: row.failureCount }\n }\n if (row.lastFailedAttempt === attempt && row.claimHolder === null) {\n return {\n outcome: row.failedAt ? 'dead_lettered' : 'failed',\n failureCount: row.failureCount,\n }\n }\n if (row.failedAt) {\n return { outcome: 'dead_lettered', failureCount: row.failureCount }\n }\n row.failureCount += 1\n row.lastError = error\n const failedAt = clock.now()\n row.lastFailedAt = new Date(failedAt)\n row.lastFailedAttempt = attempt\n row.claimHolder = null\n row.claimExpiresAt =\n retryAfterMs === undefined || row.failureCount >= maxFailures\n ? null\n : new Date(failedAt.getTime() + retryAfterMs)\n if (row.failureCount >= maxFailures) {\n row.failedAt = new Date(failedAt)\n dispatchOf(sessionId).ready.delete(row.index)\n releaseSnapshotPins(sessionId, index)\n return {\n outcome: 'dead_lettered',\n failureCount: row.failureCount,\n }\n }\n return { outcome: 'failed', failureCount: row.failureCount }\n },\n\n async deadLetters(sessionId) {\n const log = sessions.get(sessionId)\n return (log?.rows ?? [])\n .filter(\n (row) =>\n row.index > log!.clearIndex &&\n row.processedAt === null &&\n row.failedAt !== null,\n )\n .map(toStored)\n },\n\n async redrive({ sessionId, index, action }) {\n const row =\n index > clearIndexOf(sessionId) ? rowAt(sessionId, index) : undefined\n if (!row || row.processedAt !== null || row.failedAt === null) {\n return { redriven: false, hasPending: hasPending(sessionId) }\n }\n if (action === 'skip') {\n row.processedAt = clock.now()\n settle(sessionId, row)\n } else {\n row.failedAt = null\n row.failureCount = 0\n const state = dispatchOf(sessionId)\n const queue = row.lane === null ? undefined : state.lanes.get(row.lane)\n if (row.lane === null || queue?.rows[queue.head] === row) {\n state.ready.set(row.index, row)\n }\n }\n return { redriven: true, hasPending: hasPending(sessionId) }\n },\n\n async readState(sessionId, reducerName, stateOptions) {\n return readStateOf(\n sessionId,\n reducerName,\n stateOptions?.throughIndex,\n stateOptions?.snapshotThroughIndex,\n )\n },\n\n async readStates(requests, reducerName) {\n return requests.map((request) =>\n readStateOf(\n request.sessionId,\n reducerName,\n request.throughIndex,\n request.snapshotThroughIndex,\n ),\n )\n },\n\n async putSnapshots(sessionId, reducerName, writes) {\n const key = snapshotKey(sessionId, reducerName)\n const clearIndex = clearIndexOf(sessionId)\n for (const write of writes.toSorted((a, b) => a.index - b.index)) {\n if (write.index < clearIndex) continue\n const checkpoint = checkpointKey(sessionId, reducerName, write.index)\n for (const eventIndex of write.pinEventIndexes ?? []) {\n const event = rowAt(sessionId, eventIndex)\n if (\n !event ||\n event.index <= clearIndex ||\n event.processedAt !== null ||\n event.failedAt !== null\n ) {\n continue\n }\n const pinKey = eventPinKey(sessionId, eventIndex)\n let pinned = snapshotPins.get(pinKey)\n if (!pinned) {\n pinned = new Set()\n snapshotPins.set(pinKey, pinned)\n }\n if (!pinned.has(checkpoint)) {\n pinned.add(checkpoint)\n snapshotPinCounts.set(\n checkpoint,\n (snapshotPinCounts.get(checkpoint) ?? 0) + 1,\n )\n }\n }\n\n const current = snapshots.get(key)\n if (!current || write.index >= current.index) {\n if (\n current &&\n write.index > current.index &&\n current.index >= clearIndex\n ) {\n const currentCheckpoint = checkpointKey(\n sessionId,\n reducerName,\n current.index,\n )\n if ((snapshotPinCounts.get(currentCheckpoint) ?? 0) > 0) {\n historicalSnapshots.set(currentCheckpoint, {\n index: current.index,\n state: structuredClone(current.state),\n updatedAt: new Date(current.updatedAt),\n })\n }\n }\n snapshots.set(key, {\n index: write.index,\n state: structuredClone(write.state),\n updatedAt: clock.now(),\n })\n historicalSnapshots.delete(checkpoint)\n } else if (\n write.index < current.index &&\n (snapshotPinCounts.get(checkpoint) ?? 0) > 0\n ) {\n historicalSnapshots.set(checkpoint, {\n index: write.index,\n state: structuredClone(write.state),\n updatedAt: clock.now(),\n })\n }\n }\n },\n\n presence: {\n async set(ns, participant, values, meta) {\n let participants = presenceRows.get(ns)\n if (!participants) {\n participants = new Map()\n presenceRows.set(ns, participants)\n }\n let fields = participants.get(participant)\n if (!fields) {\n fields = new Map()\n participants.set(participant, fields)\n }\n\n // Expiry anchors on the storage's own clock — the sender's\n // `at` orders writes but never extends or shortens a lifetime.\n const expiresAtMs = clock.now().getTime() + meta.ttlMs\n // Field-keyed and caller-named — null-prototype, like every\n // presence map (see `nullProtoRecord`).\n const applied: Record<string, unknown> = nullProtoRecord()\n let appliedCount = 0\n for (const [field, value] of Object.entries(values)) {\n // Field-wise LWW by `at`; ties go to the incoming write, so\n // same-stamp sets keep set-then-read intuition.\n const existing = fields.get(field)\n if (existing && existing.at > meta.at) continue\n if (value === null) {\n fields.delete(field)\n } else {\n fields.set(field, {\n value: structuredClone(value),\n seen: meta.seen,\n at: new Date(meta.at),\n expiresAt: new Date(expiresAtMs),\n })\n }\n applied[field] = structuredClone(value)\n appliedCount += 1\n }\n if (fields.size === 0) participants.delete(participant)\n if (participants.size === 0) presenceRows.delete(ns)\n\n // Only applied fields broadcast — a losing write repaints nothing,\n // so subscribers stay consistent with what read() returns.\n if (appliedCount === 0) return\n const subs = presenceSubscribers.get(ns)\n if (!subs) return\n const patch: PresencePatch = {\n participant,\n values: applied,\n seen: meta.seen,\n at: new Date(meta.at),\n }\n for (const listener of subs) listener(patch)\n },\n\n async read(ns) {\n const participants = presenceRows.get(ns)\n if (!participants) return []\n const now = clock.now()\n const rows: PresenceRow[] = []\n for (const [participant, fields] of participants) {\n for (const [field, entry] of fields) {\n // Expiry is enforced lazily on read — no timers; a silent\n // participant's rows vanish the next time anyone looks.\n if (entry.expiresAt <= now) {\n fields.delete(field)\n continue\n }\n rows.push({\n participant,\n field,\n value: structuredClone(entry.value),\n seen: entry.seen,\n at: new Date(entry.at),\n expiresAt: new Date(entry.expiresAt),\n })\n }\n if (fields.size === 0) participants.delete(participant)\n }\n if (participants.size === 0) presenceRows.delete(ns)\n return rows\n },\n\n subscribe(ns, onPatch) {\n let subs = presenceSubscribers.get(ns)\n if (!subs) {\n subs = new Set()\n presenceSubscribers.set(ns, subs)\n }\n subs.add(onPatch)\n return () => {\n subs.delete(onPatch)\n if (subs.size === 0) presenceSubscribers.delete(ns)\n }\n },\n },\n\n stream(sessionId, opts) {\n const startAfter = opts?.startAfter ?? 0\n return {\n [Symbol.asyncIterator](): AsyncIterator<Event> {\n let last = Math.max(startAfter, clearIndexOf(sessionId) - 1)\n let wake: (() => void) | null = null\n let closed = false\n\n const onRow = (): void => {\n wake?.()\n }\n let subs = streamSubscribers.get(sessionId)\n if (!subs) {\n subs = new Set()\n streamSubscribers.set(sessionId, subs)\n }\n subs.add(onRow)\n const stop = (): void => {\n if (closed) return\n closed = true\n subs.delete(onRow)\n if (subs.size === 0) streamSubscribers.delete(sessionId)\n wake?.()\n }\n\n return {\n async next(): Promise<IteratorResult<Event>> {\n try {\n for (;;) {\n if (closed) return { value: undefined, done: true }\n const log = sessions.get(sessionId)\n // Rows reclaimed behind a running stream are skipped.\n const row = log?.rows[Math.max(0, last - log.offset)]\n if (row) {\n const value = toStored(row)\n last = row.index\n return { value, done: false }\n }\n // oxlint-disable-next-line no-await-in-loop -- wait-for-wake\n await new Promise<void>((resolve) => {\n wake = resolve\n })\n wake = null\n }\n } catch (error) {\n stop()\n throw error\n }\n },\n async return(): Promise<IteratorResult<Event>> {\n stop()\n return { value: undefined, done: true }\n },\n }\n },\n }\n },\n }\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { i as POLL_TIMINGS } from "./internal-B2T3U4Rq.js";
1
+ import { i as POLL_TIMINGS } from "./internal-CscSY7K_.js";
2
2
  //#region src/stream-activity.ts
3
3
  const streamActivities = /* @__PURE__ */ new WeakMap();
4
4
  function createStreamActivity(wake) {
@@ -149,4 +149,4 @@ function pollingStream(readAfter, options) {
149
149
  //#endregion
150
150
  export { streamActivities as i, pollingStream as n, createStreamActivity as r, defaultSleep as t };
151
151
 
152
- //# sourceMappingURL=store-polling-B5FcwJfo.js.map
152
+ //# sourceMappingURL=store-polling-7WJV0YWP.js.map