@effect-agent/storage-memory 0.1.0-beta.8 → 0.1.0-beta.80

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 (34) hide show
  1. package/dist/MemoryMessageDeliveryStore.d.mts +15 -0
  2. package/dist/MemoryMessageDeliveryStore.mjs +144 -0
  3. package/dist/MemoryMessageDeliveryStore.mjs.map +1 -0
  4. package/dist/MemoryScheduleStore.d.mts +10 -0
  5. package/dist/MemoryScheduleStore.mjs +169 -0
  6. package/dist/MemoryScheduleStore.mjs.map +1 -0
  7. package/dist/MemorySemanticIndex.d.mts +21 -0
  8. package/dist/MemorySemanticIndex.mjs +222 -0
  9. package/dist/MemorySemanticIndex.mjs.map +1 -0
  10. package/dist/MemorySubmissionLedger.d.mts +24 -0
  11. package/dist/MemorySubmissionLedger.mjs +1058 -0
  12. package/dist/MemorySubmissionLedger.mjs.map +1 -0
  13. package/dist/MemorySubscriptionStore.d.mts +9 -0
  14. package/dist/MemorySubscriptionStore.mjs +849 -0
  15. package/dist/MemorySubscriptionStore.mjs.map +1 -0
  16. package/dist/MemoryThreadStore.d.mts +17 -0
  17. package/dist/MemoryThreadStore.mjs +377 -0
  18. package/dist/MemoryThreadStore.mjs.map +1 -0
  19. package/dist/index.d.mts +7 -30
  20. package/dist/index.mjs +7 -1298
  21. package/dist/rolldown-runtime-D7D4PA-g.mjs +13 -0
  22. package/package.json +1 -45
  23. package/src/MemoryMessageDeliveryStore.ts +285 -0
  24. package/src/MemoryScheduleStore.ts +328 -0
  25. package/src/MemorySemanticIndex.ts +357 -0
  26. package/src/{memory-ledger.ts → MemorySubmissionLedger.ts} +478 -86
  27. package/src/MemorySubscriptionStore.ts +1549 -0
  28. package/src/MemoryThreadStore.ts +766 -0
  29. package/src/index.ts +6 -2
  30. package/dist/index.mjs.map +0 -1
  31. package/dist/testing.d.mts +0 -2
  32. package/dist/testing.mjs +0 -2
  33. package/src/memory-storage.ts +0 -614
  34. package/src/testing.ts +0 -10
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MemorySubscriptionStore.mjs","names":[],"sources":["../src/MemorySubscriptionStore.ts"],"sourcesContent":["import { Digest } from \"@effect-agent/thread/Records\";\nimport { compareScheduleNames } from \"@effect-agent/thread/ScheduleTransition\";\nimport {\n AcceptedEvent,\n DeliveryChange,\n SubscriptionChange,\n SourcePartition,\n SubscriptionDelivery,\n SubscriptionDeliveryKey,\n SubscriptionError,\n SubscriptionFailpoint,\n SubscriptionKey,\n SubscriptionLimits,\n SubscriptionRetentionPolicy,\n SubscriptionName,\n SubscriptionRecord,\n SubscriptionScanCursors,\n SubscriptionStore,\n subscriptionDeliveryKeyString,\n subscriptionKeyString,\n} from \"@effect-agent/thread/Subscription\";\nimport {\n sameAcceptedEventIdentity,\n applySubscriptionDeliveryChange,\n applySubscriptionChange,\n validateEventRetention,\n subscriptionCanSelect,\n subscriptionDeliveryCanSelect,\n} from \"@effect-agent/thread/SubscriptionTransition\";\nimport { Clock, Effect, Layer, Ref, Result, Schema } from \"effect\";\n\ninterface MemorySubscriptionState {\n readonly sequence: number;\n readonly retentionDeadline: number | null;\n readonly tombstoneCount: number;\n readonly eventKeys: ReadonlyArray<string>;\n readonly deliveryKeys: ReadonlyArray<string>;\n readonly maintenanceEvents: string;\n readonly maintenanceDeliveries: string;\n readonly recoveryCounts: ReadonlyMap<string, number>;\n readonly eventDeliveryCounts: ReadonlyMap<string, number>;\n readonly retentionHorizon: number | null;\n readonly registrations: ReadonlyMap<string, string>;\n readonly events: ReadonlyMap<string, string>;\n readonly deliveries: ReadonlyMap<string, string>;\n readonly registrationIndex: ReadonlyMap<string, RegistrationIndex>;\n readonly candidateIndex: ReadonlyMap<string, ReadonlyArray<string>>;\n readonly ownerRegistrationCounts: ReadonlyMap<string, number>;\n readonly eventIndex: ReadonlyMap<string, EventIndex>;\n readonly deliveryIndex: ReadonlyMap<string, DeliveryIndex>;\n readonly ownerDeliveryCounts: ReadonlyMap<string, number>;\n readonly scanCursors: SubscriptionScanCursors;\n}\n\ninterface RegistrationIndex {\n readonly key: SubscriptionKey;\n readonly ordinal: number;\n readonly state: SubscriptionRecord[\"state\"];\n readonly recoveryKey: string | null;\n readonly recoveryAt: number | null;\n}\ninterface EventIndex {\n readonly routingComplete: boolean;\n readonly nextAttemptAtMillis: number;\n}\ninterface DeliveryIndex {\n readonly key: SubscriptionDeliveryKey;\n readonly state: SubscriptionDelivery[\"state\"];\n readonly parked?: boolean;\n readonly observeSettlement?: boolean;\n readonly nextAttemptAtMillis: number;\n}\n\nconst error = (reason: SubscriptionError[\"reason\"], code: string) =>\n SubscriptionError.make({ reason, code });\n\nconst samePartition = (left: SourcePartition, right: SourcePartition): boolean =>\n left.tenantId === right.tenantId && left.address === right.address;\n\nconst sameSource = (left: AcceptedEvent[\"source\"], right: AcceptedEvent[\"source\"]): boolean =>\n left.name === right.name && left.version === right.version;\n\nconst encode = <A, I>(\n schema: Schema.Codec<A, I>,\n value: A,\n code: string,\n): Result.Result<string, SubscriptionError> =>\n Result.try({\n try: () => Schema.encodeSync(Schema.fromJsonString(schema))(value),\n catch: () => error(\"corrupt\", code),\n });\n\nconst decode = <A, I>(\n schema: Schema.Codec<A, I>,\n value: string,\n code: string,\n): Result.Result<A, SubscriptionError> =>\n Result.try({\n try: () => Schema.decodeSync(Schema.fromJsonString(schema))(value),\n catch: () => error(\"corrupt\", code),\n });\n\nconst decodeEffect = <A, I>(schema: Schema.Codec<A, I>, value: string, code: string) =>\n Effect.fromResult(decode(schema, value, code));\n\nconst validate = <A, I>(schema: Schema.Codec<A, I>, value: unknown, code: string) =>\n Schema.decodeUnknownEffect(schema)(value).pipe(Effect.mapError(() => error(\"validation\", code)));\n\nconst jsonBytes = (value: unknown): number =>\n new TextEncoder().encode(JSON.stringify(value)).byteLength;\n\nconst sameDeliveryIdentity = (left: SubscriptionDelivery, right: SubscriptionDelivery): boolean =>\n subscriptionDeliveryKeyString(left.key) === subscriptionDeliveryKeyString(right.key) &&\n left.deliveryId === right.deliveryId &&\n left.source.name === right.source.name &&\n left.source.version === right.source.version &&\n left.threadId === right.threadId &&\n left.admissionKey === right.admissionKey &&\n left.subscriptionFingerprint === right.subscriptionFingerprint &&\n left.eventDigest === right.eventDigest;\n\nconst candidateIndexKey = (record: SubscriptionRecord): string =>\n JSON.stringify([\n record.configuration.source.name,\n record.configuration.source.version,\n record.configuration.matchingKey,\n ]);\n\nconst eventCandidateIndexKey = (event: AcceptedEvent): string =>\n JSON.stringify([event.source.name, event.source.version, event.matchingKey]);\n\nconst sameEventIdentity = sameAcceptedEventIdentity;\n\nconst deliveryBelongsTo = (\n delivery: SubscriptionDelivery,\n record: SubscriptionRecord,\n event: AcceptedEvent,\n): boolean =>\n subscriptionKeyString(delivery.key.subscription) === subscriptionKeyString(record.key) &&\n delivery.key.eventId === event.eventId &&\n sameSource(delivery.source, event.source);\n\n// Ordered in-memory indexes allow bounded maintenance pages without scanning retained values.\nconst removeKeys = (\n keys: ReadonlyArray<string>,\n removed: ReadonlySet<string>,\n): ReadonlyArray<string> => {\n if (removed.size === 0) return keys;\n const result = [...keys];\n\n for (const key of removed) {\n const index = upperBound(result, key) - 1;\n\n if (result[index] === key) result.splice(index, 1);\n }\n\n return result;\n};\n\nconst upperBound = (keys: ReadonlyArray<string>, after: string): number => {\n let low = 0;\n let high = keys.length;\n\n while (low < high) {\n const middle = Math.floor((low + high) / 2);\n const key = keys[middle];\n\n if (key !== undefined && compareScheduleNames(key, after) <= 0) low = middle + 1;\n else high = middle;\n }\n\n return low;\n};\n\nconst insertKey = (keys: ReadonlyArray<string>, key: string): ReadonlyArray<string> => {\n const at = upperBound(keys, key);\n\n if (at > 0 && keys[at - 1] === key) return keys;\n\n return [...keys.slice(0, at), key, ...keys.slice(at)];\n};\n\nconst recoveryCountsAfter = (\n current: MemorySubscriptionState,\n next: ReadonlyMap<string, RegistrationIndex>,\n keys: ReadonlyArray<string>,\n): ReadonlyMap<string, number> => {\n const counts = new Map(current.recoveryCounts);\n\n for (const key of keys) {\n const before = current.registrationIndex.get(key)?.recoveryKey;\n const after = next.get(key)?.recoveryKey;\n\n if (before === after) continue;\n if (before !== null && before !== undefined) counts.set(before, (counts.get(before) ?? 0) - 1);\n if (after !== null && after !== undefined) counts.set(after, (counts.get(after) ?? 0) + 1);\n }\n\n return counts;\n};\n\nconst makeMemorySubscriptionStore = Effect.fn(\"makeMemorySubscriptionStore\")(function* (\n ownedPartition: SourcePartition,\n) {\n const partition = yield* validate(SourcePartition, ownedPartition, \"partition\");\n\n const state = yield* Ref.make<MemorySubscriptionState>({\n sequence: 0,\n retentionDeadline: null,\n tombstoneCount: 0,\n eventKeys: [],\n deliveryKeys: [],\n maintenanceEvents: \"\",\n maintenanceDeliveries: \"\",\n recoveryCounts: new Map(),\n eventDeliveryCounts: new Map(),\n retentionHorizon: null,\n registrations: new Map(),\n events: new Map(),\n deliveries: new Map(),\n registrationIndex: new Map(),\n candidateIndex: new Map(),\n ownerRegistrationCounts: new Map(),\n eventIndex: new Map(),\n deliveryIndex: new Map(),\n ownerDeliveryCounts: new Map(),\n scanCursors: { events: \"\", deliveries: \"\", recovery: 0 },\n });\n\n const failpoint = yield* SubscriptionFailpoint;\n\n const requirePartition = <A extends { readonly partition: SourcePartition }>(\n value: A,\n code: string,\n ) =>\n samePartition(value.partition, partition)\n ? Effect.succeed(value)\n : Effect.fail(error(\"validation\", code));\n\n const requireKey = (key: SubscriptionKey, code: string) =>\n validate(SubscriptionKey, key, code).pipe(\n Effect.flatMap((decoded) => requirePartition(decoded, code)),\n );\n\n const register: SubscriptionStore[\"Service\"][\"register\"] = Effect.fn(\n \"MemorySubscriptionStore.register\",\n )(function* (input, inputLimits) {\n const record = yield* validate(SubscriptionRecord, input, \"register-record\");\n const limits = yield* validate(SubscriptionLimits, inputLimits, \"register-limits\");\n\n yield* requirePartition(record.key, \"register-partition\");\n yield* failpoint.hit(\"subscription:register:before\");\n\n const result = yield* Effect.uninterruptible(\n Ref.modify(\n state,\n (\n current,\n ): readonly [\n Result.Result<SubscriptionRecord, SubscriptionError>,\n MemorySubscriptionState,\n ] => {\n const key = subscriptionKeyString(record.key);\n const existingText = current.registrations.get(key);\n\n if (existingText !== undefined) {\n const existing = decode(SubscriptionRecord, existingText, \"register-existing\");\n\n if (Result.isFailure(existing)) return [Result.fail(existing.failure), current];\n\n return existing.success.creationFingerprint === record.creationFingerprint\n ? [Result.succeed(existing.success), current]\n : [Result.fail(error(\"conflict\", \"registration-identity\")), current];\n }\n if (jsonBytes(record.configuration.context) > limits.maxContextBytes)\n return [Result.fail(error(\"capacity\", \"context-bytes\")), current];\n if (jsonBytes(record.configuration.parameters) > limits.maxPayloadBytes)\n return [Result.fail(error(\"capacity\", \"parameters-bytes\")), current];\n if (\n record.configuration.expiresAtMillis !== null &&\n record.configuration.expiresAtMillis - record.createdAtMillis > limits.maxLifetimeMillis\n )\n return [Result.fail(error(\"capacity\", \"lifetime\")), current];\n if (current.registrations.size >= limits.maxRegistrations)\n return [Result.fail(error(\"capacity\", \"registrations\")), current];\n const ownerCount = current.ownerRegistrationCounts.get(record.key.ownerId) ?? 0;\n\n if (ownerCount >= limits.maxRegistrationsPerOwner)\n return [Result.fail(error(\"capacity\", \"owner-registrations\")), current];\n const assigned = { ...record, ordinal: current.sequence + 1 };\n const encoded = encode(SubscriptionRecord, assigned, \"register-encode\");\n\n if (Result.isFailure(encoded)) return [Result.fail(encoded.failure), current];\n const registrations = new Map(current.registrations);\n\n registrations.set(key, encoded.success);\n const registrationIndex = new Map(current.registrationIndex);\n\n registrationIndex.set(key, {\n key: assigned.key,\n ordinal: assigned.ordinal,\n state: assigned.state,\n recoveryKey: assigned.recovery === null ? null : candidateIndexKey(assigned),\n recoveryAt: assigned.recovery?.nextAttemptAtMillis ?? null,\n });\n const candidateIndex = new Map(current.candidateIndex);\n const candidateKey = candidateIndexKey(assigned);\n\n candidateIndex.set(candidateKey, [...(candidateIndex.get(candidateKey) ?? []), key]);\n const ownerRegistrationCounts = new Map(current.ownerRegistrationCounts);\n\n ownerRegistrationCounts.set(assigned.key.ownerId, ownerCount + 1);\n\n return [\n Result.succeed(assigned),\n {\n ...current,\n sequence: assigned.ordinal,\n registrations,\n registrationIndex,\n recoveryCounts: recoveryCountsAfter(current, registrationIndex, [key]),\n candidateIndex,\n ownerRegistrationCounts,\n },\n ];\n },\n ),\n ).pipe(Effect.flatMap(Effect.fromResult));\n\n yield* failpoint.hit(\"subscription:register:after\");\n\n return result;\n });\n\n const get: SubscriptionStore[\"Service\"][\"get\"] = Effect.fn(\"MemorySubscriptionStore.get\")(\n function* (input) {\n const key = yield* requireKey(input, \"get-key\");\n const text = (yield* Ref.get(state)).registrations.get(subscriptionKeyString(key));\n\n return text === undefined\n ? null\n : yield* decodeEffect(SubscriptionRecord, text, \"get-record\");\n },\n );\n\n const list: SubscriptionStore[\"Service\"][\"list\"] = Effect.fn(\"MemorySubscriptionStore.list\")(\n function* (ownerId, after, limit) {\n if (!Number.isSafeInteger(after) || after < 0 || !Number.isSafeInteger(limit) || limit <= 0)\n return yield* error(\"validation\", \"list-page\");\n const current = yield* Ref.get(state);\n const records: Array<SubscriptionRecord> = [];\n\n for (const [storageKey, indexed] of current.registrationIndex) {\n if (indexed.key.ownerId !== ownerId || indexed.ordinal <= after) continue;\n const text = current.registrations.get(storageKey);\n\n if (text === undefined) return yield* error(\"corrupt\", \"list-index\");\n records.push(yield* decodeEffect(SubscriptionRecord, text, \"list-record\"));\n }\n records.sort((a, b) => a.ordinal - b.ordinal);\n\n return records.slice(0, limit);\n },\n );\n\n const change: SubscriptionStore[\"Service\"][\"change\"] = Effect.fn(\n \"MemorySubscriptionStore.change\",\n )(function* (input, expectedRevision, inputChange) {\n const key = yield* requireKey(input, \"change-key\");\n const change = yield* validate(SubscriptionChange, inputChange, \"change\");\n\n yield* validate(Schema.Int.check(Schema.isGreaterThan(0)), expectedRevision, \"revision\");\n yield* failpoint.hit(\"subscription:change:before\");\n\n const updated = yield* Effect.uninterruptible(\n Ref.modify(\n state,\n (\n current,\n ): readonly [\n Result.Result<SubscriptionRecord, SubscriptionError>,\n MemorySubscriptionState,\n ] => {\n const storageKey = subscriptionKeyString(key);\n const text = current.registrations.get(storageKey);\n\n if (text === undefined) return [Result.fail(error(\"not-found\", \"subscription\")), current];\n const existing = decode(SubscriptionRecord, text, \"change-record\");\n\n if (Result.isFailure(existing)) return [existing, current];\n const updated = applySubscriptionChange(existing.success, expectedRevision, change);\n\n if (Result.isFailure(updated)) return [updated, current];\n const revised = { ...updated.success, ordinal: current.sequence + 1 };\n const encoded = encode(SubscriptionRecord, revised, \"change-encode\");\n\n if (Result.isFailure(encoded)) return [Result.fail(encoded.failure), current];\n const registrations = new Map(current.registrations);\n\n registrations.set(storageKey, encoded.success);\n const registrationIndex = new Map(current.registrationIndex);\n\n registrationIndex.set(storageKey, {\n key,\n ordinal: revised.ordinal,\n state: revised.state,\n recoveryKey: revised.recovery === null ? null : candidateIndexKey(revised),\n recoveryAt: revised.recovery?.nextAttemptAtMillis ?? null,\n });\n const candidateIndex = new Map(current.candidateIndex);\n const oldKey = candidateIndexKey(existing.success);\n const nextKey = candidateIndexKey(revised);\n\n {\n candidateIndex.set(\n oldKey,\n (candidateIndex.get(oldKey) ?? []).filter((key) => key !== storageKey),\n );\n candidateIndex.set(\n nextKey,\n [...(candidateIndex.get(nextKey) ?? []), storageKey].sort(\n (a, b) =>\n (registrationIndex.get(a)?.ordinal ?? 0) -\n (registrationIndex.get(b)?.ordinal ?? 0),\n ),\n );\n }\n\n return [\n Result.succeed(revised),\n {\n ...current,\n sequence: revised.ordinal,\n registrations,\n registrationIndex,\n candidateIndex,\n recoveryCounts: recoveryCountsAfter(current, registrationIndex, [storageKey]),\n },\n ];\n },\n ),\n ).pipe(Effect.flatMap(Effect.fromResult));\n\n yield* failpoint.hit(\"subscription:change:after\");\n\n return updated;\n });\n\n const cancel: SubscriptionStore[\"Service\"][\"cancel\"] = Effect.fn(\n \"MemorySubscriptionStore.cancel\",\n )(function* (input, expectedRevision) {\n const key = yield* requireKey(input, \"cancel-key\");\n\n yield* failpoint.hit(\"subscription:cancel:before\");\n\n const result = yield* Effect.uninterruptible(\n Ref.modify(\n state,\n (\n current,\n ): readonly [\n Result.Result<SubscriptionRecord, SubscriptionError>,\n MemorySubscriptionState,\n ] => {\n const storageKey = subscriptionKeyString(key);\n const text = current.registrations.get(storageKey);\n\n if (text === undefined) return [Result.fail(error(\"not-found\", \"subscription\")), current];\n const decoded = decode(SubscriptionRecord, text, \"cancel-record\");\n\n if (Result.isFailure(decoded)) return [decoded, current];\n if (\n expectedRevision !== undefined &&\n expectedRevision !== decoded.success.configurationRevision &&\n !(\n decoded.success.state === \"cancelled\" &&\n expectedRevision + 1 === decoded.success.configurationRevision\n )\n )\n return [\n Result.fail(\n SubscriptionError.make({\n reason: \"conflict\",\n code: \"configuration-revision\",\n currentRevision: decoded.success.configurationRevision,\n currentState: decoded.success.state,\n }),\n ),\n current,\n ];\n if (decoded.success.state === \"cancelled\")\n return [Result.succeed(decoded.success), current];\n\n const cancelled = {\n ...decoded.success,\n configurationRevision: decoded.success.configurationRevision + 1,\n state: \"cancelled\" as const,\n recovery: null,\n };\n\n const encoded = encode(SubscriptionRecord, cancelled, \"cancel-encode\");\n\n if (Result.isFailure(encoded)) return [Result.fail(encoded.failure), current];\n const registrations = new Map(current.registrations);\n\n registrations.set(storageKey, encoded.success);\n const registrationIndex = new Map(current.registrationIndex);\n const indexed = registrationIndex.get(storageKey);\n\n if (indexed === undefined)\n return [Result.fail(error(\"corrupt\", \"cancel-index\")), current];\n registrationIndex.set(storageKey, {\n ...indexed,\n state: \"cancelled\",\n recoveryAt: null,\n recoveryKey: null,\n });\n\n return [\n Result.succeed(cancelled),\n {\n ...current,\n registrations,\n registrationIndex,\n recoveryCounts: recoveryCountsAfter(current, registrationIndex, [storageKey]),\n },\n ];\n },\n ),\n ).pipe(Effect.flatMap(Effect.fromResult));\n\n yield* failpoint.hit(\"subscription:cancel:after\");\n\n return result;\n });\n\n const accept: SubscriptionStore[\"Service\"][\"accept\"] = Effect.fn(\n \"MemorySubscriptionStore.accept\",\n )(function* (input, inputLimits) {\n const event = yield* validate(AcceptedEvent, input, \"accept-event\");\n const currentTimeMillis = yield* Clock.currentTimeMillis;\n const limits = yield* validate(SubscriptionLimits, inputLimits, \"accept-limits\");\n\n yield* requirePartition(event, \"accept-partition\");\n yield* failpoint.hit(\"subscription:accept:before\");\n\n const result = yield* Effect.uninterruptible(\n Ref.modify(\n state,\n (\n current,\n ): readonly [Result.Result<AcceptedEvent, SubscriptionError>, MemorySubscriptionState] => {\n const existingText = current.events.get(event.eventId);\n\n if (existingText !== undefined) {\n const existing = decode(AcceptedEvent, existingText, \"accept-existing\");\n\n if (Result.isFailure(existing)) return [Result.fail(existing.failure), current];\n\n return sameEventIdentity(existing.success, event)\n ? [Result.succeed(existing.success), current]\n : [Result.fail(error(\"conflict\", \"event-identity\")), current];\n }\n if (\n current.retentionHorizon !== null &&\n current.retentionHorizon !== limits.retention?.replayHorizonMillis\n )\n return [Result.fail(error(\"conflict\", \"retention-horizon\")), current];\n const horizon = validateEventRetention(event, limits, currentTimeMillis);\n\n if (Result.isFailure(horizon)) return [Result.fail(horizon.failure), current];\n if (jsonBytes(event.payload) > limits.maxPayloadBytes)\n return [Result.fail(error(\"capacity\", \"payload-bytes\")), current];\n if (current.events.size - current.tombstoneCount >= limits.maxEvents)\n return [Result.fail(error(\"capacity\", \"events\")), current];\n\n const accepted: AcceptedEvent = {\n ...event,\n cutoff: current.sequence + 1,\n cursor: 0,\n routingComplete: false,\n routingFailure: null,\n };\n\n const encoded = encode(AcceptedEvent, accepted, \"accept-encode\");\n\n if (Result.isFailure(encoded)) return [Result.fail(encoded.failure), current];\n const events = new Map(current.events);\n\n events.set(accepted.eventId, encoded.success);\n const eventIndex = new Map(current.eventIndex);\n\n eventIndex.set(accepted.eventId, {\n routingComplete: false,\n nextAttemptAtMillis: accepted.nextAttemptAtMillis,\n });\n\n return [\n Result.succeed(accepted),\n {\n ...current,\n sequence: accepted.cutoff,\n events,\n eventIndex,\n eventKeys: insertKey(current.eventKeys, accepted.eventId),\n retentionHorizon: limits.retention?.replayHorizonMillis ?? current.retentionHorizon,\n retentionDeadline:\n limits.retention === undefined\n ? current.retentionDeadline\n : accepted.acceptedAtMillis,\n },\n ];\n },\n ),\n ).pipe(Effect.flatMap(Effect.fromResult));\n\n yield* failpoint.hit(\"subscription:accept:after\");\n\n return result;\n });\n\n const event: SubscriptionStore[\"Service\"][\"event\"] = Effect.fn(\"MemorySubscriptionStore.event\")(\n function* (eventId) {\n const text = (yield* Ref.get(state)).events.get(eventId);\n\n return text === undefined ? null : yield* decodeEffect(AcceptedEvent, text, \"event-record\");\n },\n );\n\n const pendingEvents: SubscriptionStore[\"Service\"][\"pendingEvents\"] = Effect.fn(\n \"MemorySubscriptionStore.pendingEvents\",\n )(function* (nowMillis, after, limit) {\n const events: Array<string> = [];\n\n for (const [eventId, indexed] of (yield* Ref.get(state)).eventIndex) {\n if (\n !indexed.routingComplete &&\n indexed.nextAttemptAtMillis <= nowMillis &&\n compareScheduleNames(eventId, after) > 0\n )\n events.push(eventId);\n }\n events.sort(compareScheduleNames);\n\n return events.slice(0, limit);\n });\n\n const candidates: SubscriptionStore[\"Service\"][\"candidates\"] = Effect.fn(\n \"MemorySubscriptionStore.candidates\",\n )(function* (input, limit) {\n const accepted = yield* validate(AcceptedEvent, input, \"candidates-event\");\n\n yield* requirePartition(accepted, \"candidates-partition\");\n const stored = yield* event(accepted.eventId);\n\n if (stored === null || !sameEventIdentity(stored, accepted))\n return yield* error(stored === null ? \"not-found\" : \"conflict\", \"event\");\n const current = yield* Ref.get(state);\n const records: Array<SubscriptionRecord> = [];\n\n for (const storageKey of current.candidateIndex.get(eventCandidateIndexKey(stored)) ?? []) {\n const indexed = current.registrationIndex.get(storageKey);\n\n if (indexed === undefined) return yield* error(\"corrupt\", \"candidate-index\");\n if (indexed.ordinal <= stored.cursor || indexed.ordinal > stored.cutoff) continue;\n const text = current.registrations.get(storageKey);\n\n if (text === undefined) return yield* error(\"corrupt\", \"candidate-record\");\n records.push(yield* decodeEffect(SubscriptionRecord, text, \"candidate-record\"));\n }\n records.sort((a, b) => a.ordinal - b.ordinal);\n\n return records.slice(0, limit);\n });\n\n const select: SubscriptionStore[\"Service\"][\"select\"] = Effect.fn(\n \"MemorySubscriptionStore.select\",\n )(function* (inputEvent, inputDeliveries, cursor, complete, nowMillis, inputLimits) {\n const suppliedEvent = yield* validate(AcceptedEvent, inputEvent, \"select-event\");\n\n const deliveries = yield* validate(\n Schema.Array(SubscriptionDelivery),\n inputDeliveries,\n \"select-deliveries\",\n );\n\n const limits = yield* validate(SubscriptionLimits, inputLimits, \"select-limits\");\n\n yield* requirePartition(suppliedEvent, \"select-partition\");\n yield* failpoint.hit(\"subscription:select:before\");\n const effectiveNowMillis = Math.max(nowMillis, yield* Clock.currentTimeMillis);\n\n yield* Effect.uninterruptible(\n Ref.modify(\n state,\n (current): readonly [Result.Result<void, SubscriptionError>, MemorySubscriptionState] => {\n const eventText = current.events.get(suppliedEvent.eventId);\n\n if (eventText === undefined) return [Result.fail(error(\"not-found\", \"event\")), current];\n const decodedEvent = decode(AcceptedEvent, eventText, \"select-event-record\");\n\n if (Result.isFailure(decodedEvent)) return [Result.fail(decodedEvent.failure), current];\n const accepted = decodedEvent.success;\n\n if (\n !sameEventIdentity(accepted, suppliedEvent) ||\n suppliedEvent.cursor !== accepted.cursor\n )\n return [Result.fail(error(\"conflict\", \"event-cursor\")), current];\n if (accepted.routingComplete)\n return [\n complete && cursor === accepted.cursor\n ? Result.void\n : Result.fail(error(\"conflict\", \"routing-complete\")),\n current,\n ];\n if (!Number.isSafeInteger(cursor) || cursor < accepted.cursor || cursor > accepted.cutoff)\n return [Result.fail(error(\"validation\", \"cursor\")), current];\n\n const additions: Array<readonly [string, string]> = [];\n const updates: Array<readonly [string, string]> = [];\n const additionIndex: Array<readonly [string, DeliveryIndex, string]> = [];\n const registrationUpdates: Array<readonly [string, RegistrationIndex]> = [];\n const owners = new Map(current.ownerDeliveryCounts);\n\n for (const delivery of deliveries) {\n const recordText = current.registrations.get(\n subscriptionKeyString(delivery.key.subscription),\n );\n\n if (recordText === undefined)\n return [Result.fail(error(\"not-found\", \"subscription\")), current];\n const record = decode(SubscriptionRecord, recordText, \"select-registration\");\n\n if (Result.isFailure(record)) return [Result.fail(record.failure), current];\n if (\n !deliveryBelongsTo(delivery, record.success, accepted) ||\n !subscriptionDeliveryCanSelect(delivery, record.success, accepted) ||\n record.success.ordinal <= accepted.cursor ||\n record.success.ordinal > cursor\n )\n return [Result.fail(error(\"conflict\", \"selection\")), current];\n if (!subscriptionCanSelect(record.success, accepted, effectiveNowMillis, false))\n continue;\n const deliveryKey = subscriptionDeliveryKeyString(delivery.key);\n const existingText = current.deliveries.get(deliveryKey);\n\n if (existingText !== undefined) {\n const existing = decode(SubscriptionDelivery, existingText, \"select-existing\");\n\n if (Result.isFailure(existing)) return [Result.fail(existing.failure), current];\n if (!sameDeliveryIdentity(existing.success, delivery))\n return [Result.fail(error(\"conflict\", \"delivery-identity\")), current];\n continue;\n }\n\n const encodedDelivery = encode(\n SubscriptionDelivery,\n delivery,\n \"select-delivery-encode\",\n );\n\n if (Result.isFailure(encodedDelivery))\n return [Result.fail(encodedDelivery.failure), current];\n additions.push([deliveryKey, encodedDelivery.success]);\n additionIndex.push([\n deliveryKey,\n {\n key: delivery.key,\n state: delivery.state,\n nextAttemptAtMillis: delivery.retry.nextAttemptAtMillis,\n },\n record.success.key.ownerId,\n ]);\n const ownerId = record.success.key.ownerId;\n\n owners.set(ownerId, (owners.get(ownerId) ?? 0) + 1);\n if ((owners.get(ownerId) ?? 0) > limits.maxDeliveriesPerOwner)\n return [Result.fail(error(\"capacity\", \"owner-deliveries\")), current];\n if (record.success.configuration.mode === \"once\") {\n const consumed = { ...record.success, state: \"consumed\" as const, recovery: null };\n\n const encodedRecord = encode(\n SubscriptionRecord,\n consumed,\n \"select-registration-encode\",\n );\n\n if (Result.isFailure(encodedRecord))\n return [Result.fail(encodedRecord.failure), current];\n const consumedKey = subscriptionKeyString(consumed.key);\n\n updates.push([consumedKey, encodedRecord.success]);\n const indexed = current.registrationIndex.get(consumedKey);\n\n if (indexed === undefined)\n return [Result.fail(error(\"corrupt\", \"selection-index\")), current];\n registrationUpdates.push([\n consumedKey,\n { ...indexed, state: \"consumed\", recoveryAt: null, recoveryKey: null },\n ]);\n }\n }\n if (current.deliveries.size + additions.length > limits.maxDeliveries)\n return [Result.fail(error(\"capacity\", \"deliveries\")), current];\n const registrations = new Map(current.registrations);\n\n for (const [key, value] of updates) registrations.set(key, value);\n const nextDeliveries = new Map(current.deliveries);\n\n for (const [key, value] of additions) nextDeliveries.set(key, value);\n const deliveryIndex = new Map(current.deliveryIndex);\n\n for (const [key, value] of additionIndex) deliveryIndex.set(key, value);\n const registrationIndex = new Map(current.registrationIndex);\n\n for (const [key, value] of registrationUpdates) registrationIndex.set(key, value);\n\n const eventDeliveryCounts = new Map(current.eventDeliveryCounts);\n\n eventDeliveryCounts.set(\n accepted.eventId,\n (eventDeliveryCounts.get(accepted.eventId) ?? 0) + additions.length,\n );\n\n const nextEvent: AcceptedEvent = {\n ...accepted,\n cursor,\n routingComplete: complete,\n routingFailure: null,\n };\n\n const encodedEvent = encode(AcceptedEvent, nextEvent, \"select-event-encode\");\n\n if (Result.isFailure(encodedEvent)) return [Result.fail(encodedEvent.failure), current];\n const events = new Map(current.events);\n\n events.set(nextEvent.eventId, encodedEvent.success);\n const eventIndex = new Map(current.eventIndex);\n\n eventIndex.set(nextEvent.eventId, {\n routingComplete: nextEvent.routingComplete,\n nextAttemptAtMillis: nextEvent.nextAttemptAtMillis,\n });\n\n return [\n Result.void,\n {\n ...current,\n registrations,\n registrationIndex,\n recoveryCounts: recoveryCountsAfter(\n current,\n registrationIndex,\n registrationUpdates.map(([key]) => key),\n ),\n eventDeliveryCounts,\n events,\n eventIndex,\n deliveries: nextDeliveries,\n deliveryKeys: additions.reduce(\n (keys, [key]) => insertKey(keys, key),\n current.deliveryKeys,\n ),\n deliveryIndex,\n ownerDeliveryCounts: owners,\n },\n ];\n },\n ),\n ).pipe(Effect.flatMap(Effect.fromResult));\n yield* failpoint.hit(\"subscription:select:after\");\n });\n\n const catchUp: SubscriptionStore[\"Service\"][\"catchUp\"] = Effect.fn(\n \"MemorySubscriptionStore.catchUp\",\n )(function* (inputEvent, inputDelivery, nowMillis, inputLimits) {\n const suppliedEvent = yield* validate(AcceptedEvent, inputEvent, \"catch-up-event\");\n const delivery = yield* validate(SubscriptionDelivery, inputDelivery, \"catch-up-delivery\");\n const limits = yield* validate(SubscriptionLimits, inputLimits, \"catch-up-limits\");\n\n yield* requirePartition(suppliedEvent, \"catch-up-partition\");\n yield* failpoint.hit(\"subscription:catch-up:before\");\n const effectiveNowMillis = Math.max(nowMillis, yield* Clock.currentTimeMillis);\n\n yield* Effect.uninterruptible(\n Ref.modify(\n state,\n (current): readonly [Result.Result<void, SubscriptionError>, MemorySubscriptionState] => {\n const eventText = current.events.get(suppliedEvent.eventId);\n\n const recordText = current.registrations.get(\n subscriptionKeyString(delivery.key.subscription),\n );\n\n if (eventText === undefined || recordText === undefined)\n return [\n Result.fail(error(\"not-found\", eventText === undefined ? \"event\" : \"subscription\")),\n current,\n ];\n const accepted = decode(AcceptedEvent, eventText, \"catch-up-event-record\");\n\n if (Result.isFailure(accepted)) return [Result.fail(accepted.failure), current];\n const record = decode(SubscriptionRecord, recordText, \"catch-up-registration\");\n\n if (Result.isFailure(record)) return [Result.fail(record.failure), current];\n if (\n !sameEventIdentity(accepted.success, suppliedEvent) ||\n !deliveryBelongsTo(delivery, record.success, accepted.success) ||\n !subscriptionDeliveryCanSelect(delivery, record.success, accepted.success) ||\n record.success.configuration.mode !== \"once\"\n )\n return [Result.fail(error(\"conflict\", \"catch-up-identity\")), current];\n const key = subscriptionDeliveryKeyString(delivery.key);\n const existingText = current.deliveries.get(key);\n\n if (existingText !== undefined) {\n const existing = decode(SubscriptionDelivery, existingText, \"catch-up-existing\");\n\n if (Result.isFailure(existing)) return [Result.fail(existing.failure), current];\n\n return sameDeliveryIdentity(existing.success, delivery)\n ? [Result.void, current]\n : [Result.fail(error(\"conflict\", \"delivery-identity\")), current];\n }\n if (!subscriptionCanSelect(record.success, accepted.success, effectiveNowMillis, true))\n return [Result.fail(error(\"conflict\", \"catch-up-eligibility\")), current];\n if (current.deliveries.size >= limits.maxDeliveries)\n return [Result.fail(error(\"capacity\", \"deliveries\")), current];\n const ownerCount = current.ownerDeliveryCounts.get(record.success.key.ownerId) ?? 0;\n\n if (ownerCount >= limits.maxDeliveriesPerOwner)\n return [Result.fail(error(\"capacity\", \"owner-deliveries\")), current];\n\n const encodedDelivery = encode(\n SubscriptionDelivery,\n delivery,\n \"catch-up-delivery-encode\",\n );\n\n if (Result.isFailure(encodedDelivery))\n return [Result.fail(encodedDelivery.failure), current];\n const consumed = { ...record.success, state: \"consumed\" as const, recovery: null };\n\n const encodedRecord = encode(\n SubscriptionRecord,\n consumed,\n \"catch-up-registration-encode\",\n );\n\n if (Result.isFailure(encodedRecord)) return [Result.fail(encodedRecord.failure), current];\n const deliveries = new Map(current.deliveries);\n\n deliveries.set(key, encodedDelivery.success);\n const registrations = new Map(current.registrations);\n const consumedKey = subscriptionKeyString(consumed.key);\n\n registrations.set(consumedKey, encodedRecord.success);\n const registrationIndex = new Map(current.registrationIndex);\n const indexed = registrationIndex.get(consumedKey);\n\n if (indexed === undefined)\n return [Result.fail(error(\"corrupt\", \"catch-up-index\")), current];\n registrationIndex.set(consumedKey, {\n ...indexed,\n state: \"consumed\",\n recoveryAt: null,\n recoveryKey: null,\n });\n const deliveryIndex = new Map(current.deliveryIndex);\n\n deliveryIndex.set(key, {\n key: delivery.key,\n state: delivery.state,\n nextAttemptAtMillis: delivery.retry.nextAttemptAtMillis,\n });\n const ownerDeliveryCounts = new Map(current.ownerDeliveryCounts);\n const eventDeliveryCounts = new Map(current.eventDeliveryCounts);\n\n eventDeliveryCounts.set(\n accepted.success.eventId,\n (eventDeliveryCounts.get(accepted.success.eventId) ?? 0) + 1,\n );\n\n ownerDeliveryCounts.set(consumed.key.ownerId, ownerCount + 1);\n\n return [\n Result.void,\n {\n ...current,\n deliveries,\n deliveryIndex,\n deliveryKeys: insertKey(current.deliveryKeys, key),\n ownerDeliveryCounts,\n registrations,\n registrationIndex,\n recoveryCounts: recoveryCountsAfter(current, registrationIndex, [consumedKey]),\n eventDeliveryCounts,\n },\n ];\n },\n ),\n ).pipe(Effect.flatMap(Effect.fromResult));\n yield* failpoint.hit(\"subscription:catch-up:after\");\n });\n\n const deferEvent: SubscriptionStore[\"Service\"][\"deferEvent\"] = Effect.fn(\n \"MemorySubscriptionStore.deferEvent\",\n )(function* (eventId, nextAttemptAtMillis, code) {\n const routingFailure =\n code === undefined\n ? \"routing-failed\"\n : yield* validate(SubscriptionName, code, \"routing-failure\");\n\n yield* failpoint.hit(\"subscription:defer-event:before\");\n yield* Effect.uninterruptible(\n Ref.modify(\n state,\n (current): readonly [Result.Result<void, SubscriptionError>, MemorySubscriptionState] => {\n const text = current.events.get(eventId);\n\n if (text === undefined) return [Result.fail(error(\"not-found\", \"event\")), current];\n const accepted = decode(AcceptedEvent, text, \"defer-event-record\");\n\n if (Result.isFailure(accepted)) return [Result.fail(accepted.failure), current];\n const updated = { ...accepted.success, nextAttemptAtMillis, routingFailure };\n const encoded = encode(AcceptedEvent, updated, \"defer-event-encode\");\n\n if (Result.isFailure(encoded)) return [Result.fail(encoded.failure), current];\n const events = new Map(current.events);\n\n events.set(eventId, encoded.success);\n const eventIndex = new Map(current.eventIndex);\n const indexed = eventIndex.get(eventId);\n\n if (indexed === undefined)\n return [Result.fail(error(\"corrupt\", \"defer-event-index\")), current];\n eventIndex.set(eventId, { ...indexed, nextAttemptAtMillis });\n\n return [Result.void, { ...current, events, eventIndex }];\n },\n ),\n ).pipe(Effect.flatMap(Effect.fromResult));\n yield* failpoint.hit(\"subscription:defer-event:after\");\n });\n\n const delivery: SubscriptionStore[\"Service\"][\"delivery\"] = Effect.fn(\n \"MemorySubscriptionStore.delivery\",\n )(function* (input) {\n const key = yield* validate(SubscriptionDeliveryKey, input, \"delivery-key\");\n\n yield* requirePartition(key.subscription, \"delivery-partition\");\n const text = (yield* Ref.get(state)).deliveries.get(subscriptionDeliveryKeyString(key));\n\n return text === undefined\n ? null\n : yield* decodeEffect(SubscriptionDelivery, text, \"delivery-record\");\n });\n\n const pendingDeliveries: SubscriptionStore[\"Service\"][\"pendingDeliveries\"] = Effect.fn(\n \"MemorySubscriptionStore.pendingDeliveries\",\n )(function* (nowMillis, after, limit) {\n const items: Array<SubscriptionDeliveryKey> = [];\n\n for (const [storageKey, item] of (yield* Ref.get(state)).deliveryIndex) {\n if (\n ((item.state !== \"delivered\" && item.state !== \"refused\" && item.parked !== true) ||\n (item.state === \"delivered\" && item.observeSettlement === true)) &&\n item.nextAttemptAtMillis <= nowMillis &&\n compareScheduleNames(storageKey, after) > 0\n )\n items.push(item.key);\n }\n items.sort((a, b) =>\n compareScheduleNames(subscriptionDeliveryKeyString(a), subscriptionDeliveryKeyString(b)),\n );\n\n return items.slice(0, limit);\n });\n\n const listDeliveries: SubscriptionStore[\"Service\"][\"listDeliveries\"] = Effect.fn(\n \"MemorySubscriptionStore.listDeliveries\",\n )(function* (input, after, limit) {\n const key = yield* requireKey(input, \"list-deliveries-key\");\n const items: Array<SubscriptionDelivery> = [];\n\n for (const text of (yield* Ref.get(state)).deliveries.values()) {\n const item = yield* decodeEffect(SubscriptionDelivery, text, \"list-delivery\");\n const itemKey = subscriptionDeliveryKeyString(item.key);\n\n if (\n subscriptionKeyString(item.key.subscription) === subscriptionKeyString(key) &&\n compareScheduleNames(itemKey, after) > 0\n )\n items.push(item);\n }\n items.sort((a, b) =>\n compareScheduleNames(\n subscriptionDeliveryKeyString(a.key),\n subscriptionDeliveryKeyString(b.key),\n ),\n );\n\n return items.slice(0, limit);\n });\n\n const changeDelivery: SubscriptionStore[\"Service\"][\"changeDelivery\"] = Effect.fn(\n \"MemorySubscriptionStore.changeDelivery\",\n )(function* (inputKey, inputDeliveryId, inputChange) {\n const key = yield* validate(SubscriptionDeliveryKey, inputKey, \"change-delivery-key\");\n const deliveryId = yield* validate(Digest, inputDeliveryId, \"change-delivery-id\");\n const change = yield* validate(DeliveryChange, inputChange, \"change-delivery-change\");\n\n yield* requirePartition(key.subscription, \"change-delivery-partition\");\n yield* failpoint.hit(`subscription:delivery-${change._tag.toLowerCase()}:before`);\n\n const effectiveChange =\n change._tag === \"Prepare\"\n ? { ...change, nowMillis: Math.max(change.nowMillis, yield* Clock.currentTimeMillis) }\n : change;\n\n const result = yield* Effect.uninterruptible(\n Ref.modify(\n state,\n (\n current,\n ): readonly [\n Result.Result<SubscriptionDelivery, SubscriptionError>,\n MemorySubscriptionState,\n ] => {\n const storageKey = subscriptionDeliveryKeyString(key);\n const text = current.deliveries.get(storageKey);\n\n if (text === undefined) return [Result.fail(error(\"not-found\", \"delivery\")), current];\n const decoded = decode(SubscriptionDelivery, text, \"change-delivery-record\");\n\n if (Result.isFailure(decoded)) return [decoded, current];\n\n const registrationText = current.registrations.get(\n subscriptionKeyString(key.subscription),\n );\n\n if (registrationText === undefined)\n return [Result.fail(error(\"corrupt\", \"delivery-registration\")), current];\n\n const registration = decode(\n SubscriptionRecord,\n registrationText,\n \"delivery-registration\",\n );\n\n if (Result.isFailure(registration)) return [Result.fail(registration.failure), current];\n\n const transition = applySubscriptionDeliveryChange(\n decoded.success,\n registration.success,\n deliveryId,\n effectiveChange,\n );\n\n if (Result.isFailure(transition)) return [Result.fail(transition.failure), current];\n if (transition.success === decoded.success)\n return [Result.succeed(decoded.success), current];\n const updated = transition.success;\n const encoded = encode(SubscriptionDelivery, updated, \"change-delivery-encode\");\n\n if (Result.isFailure(encoded)) return [Result.fail(encoded.failure), current];\n const deliveries = new Map(current.deliveries);\n\n deliveries.set(storageKey, encoded.success);\n const deliveryIndex = new Map(current.deliveryIndex);\n const indexed = deliveryIndex.get(storageKey);\n\n if (indexed === undefined)\n return [Result.fail(error(\"corrupt\", \"delivery-index\")), current];\n deliveryIndex.set(storageKey, {\n ...indexed,\n state: updated.state,\n parked: updated.retry.parked ?? false,\n observeSettlement: updated.observeSettlement ?? false,\n nextAttemptAtMillis: updated.retry.nextAttemptAtMillis,\n });\n\n return [Result.succeed(updated), { ...current, deliveries, deliveryIndex }];\n },\n ),\n ).pipe(Effect.flatMap(Effect.fromResult));\n\n yield* failpoint.hit(`subscription:delivery-${change._tag.toLowerCase()}:after`);\n\n return result;\n });\n\n const recovering: SubscriptionStore[\"Service\"][\"recovering\"] = Effect.fn(\n \"MemorySubscriptionStore.recovering\",\n )(function* (nowMillis, after, limit) {\n const records: Array<{ readonly key: SubscriptionKey; readonly ordinal: number }> = [];\n\n for (const item of (yield* Ref.get(state)).registrationIndex.values()) {\n if (\n item.ordinal > after &&\n item.state === \"active\" &&\n item.recoveryAt !== null &&\n item.recoveryAt <= nowMillis\n )\n records.push({ key: item.key, ordinal: item.ordinal });\n }\n records.sort((a, b) => a.ordinal - b.ordinal);\n\n return records.slice(0, limit);\n });\n\n const deferRecovery: SubscriptionStore[\"Service\"][\"deferRecovery\"] = Effect.fn(\n \"MemorySubscriptionStore.deferRecovery\",\n )(function* (input, expectedRevision, recovery) {\n const key = yield* requireKey(input, \"defer-recovery-key\");\n\n yield* failpoint.hit(\"subscription:defer-recovery:before\");\n yield* Effect.uninterruptible(\n Ref.modify(\n state,\n (current): readonly [Result.Result<void, SubscriptionError>, MemorySubscriptionState] => {\n const storageKey = subscriptionKeyString(key);\n const text = current.registrations.get(storageKey);\n\n if (text === undefined) return [Result.fail(error(\"not-found\", \"subscription\")), current];\n const record = decode(SubscriptionRecord, text, \"defer-recovery-record\");\n\n if (Result.isFailure(record)) return [Result.fail(record.failure), current];\n\n if (record.success.configurationRevision !== expectedRevision)\n return [Result.void, current];\n\n const updated = {\n ...record.success,\n recovery:\n record.success.state === \"active\" || record.success.state === \"paused\"\n ? recovery\n : null,\n };\n\n const encoded = encode(SubscriptionRecord, updated, \"defer-recovery-encode\");\n\n if (Result.isFailure(encoded)) return [Result.fail(encoded.failure), current];\n const registrations = new Map(current.registrations);\n\n registrations.set(storageKey, encoded.success);\n const registrationIndex = new Map(current.registrationIndex);\n const indexed = registrationIndex.get(storageKey);\n\n if (indexed === undefined)\n return [Result.fail(error(\"corrupt\", \"recovery-index\")), current];\n registrationIndex.set(storageKey, {\n ...indexed,\n recoveryKey: updated.recovery === null ? null : candidateIndexKey(updated),\n recoveryAt: updated.recovery?.nextAttemptAtMillis ?? null,\n });\n\n return [\n Result.void,\n {\n ...current,\n registrations,\n registrationIndex,\n recoveryCounts: recoveryCountsAfter(current, registrationIndex, [storageKey]),\n },\n ];\n },\n ),\n ).pipe(Effect.flatMap(Effect.fromResult));\n yield* failpoint.hit(\"subscription:defer-recovery:after\");\n });\n\n const readScanCursors: SubscriptionStore[\"Service\"][\"readScanCursors\"] = Ref.get(state).pipe(\n Effect.map((current) => current.scanCursors),\n );\n\n const advanceScanCursors: SubscriptionStore[\"Service\"][\"advanceScanCursors\"] = Effect.fn(\n \"MemorySubscriptionStore.advanceScanCursors\",\n )(function* (input) {\n const cursors = yield* validate(SubscriptionScanCursors, input, \"scan-cursors\");\n\n yield* failpoint.hit(\"subscription:advance-scan-cursors:before\");\n yield* Effect.uninterruptible(\n Ref.update(state, (current) => ({ ...current, scanCursors: cursors })),\n );\n yield* failpoint.hit(\"subscription:advance-scan-cursors:after\");\n });\n\n const nextDeadline = Effect.gen(function* () {\n let deadline: number | null = null;\n const current = yield* Ref.get(state);\n\n if (\n current.scanCursors.events !== \"\" ||\n current.scanCursors.deliveries !== \"\" ||\n current.scanCursors.recovery !== 0\n )\n return 0;\n\n const consider = (value: number) => {\n if (deadline === null || value < deadline) deadline = value;\n };\n\n if (current.retentionDeadline !== null) consider(current.retentionDeadline);\n for (const accepted of current.eventIndex.values())\n if (!accepted.routingComplete) consider(accepted.nextAttemptAtMillis);\n for (const item of current.deliveryIndex.values())\n if (\n (item.state !== \"delivered\" && item.state !== \"refused\" && item.parked !== true) ||\n (item.state === \"delivered\" && item.observeSettlement === true)\n )\n consider(item.nextAttemptAtMillis);\n for (const record of current.registrationIndex.values())\n if (record.state === \"active\" && record.recoveryAt !== null) consider(record.recoveryAt);\n\n return deadline;\n }).pipe(Effect.withSpan(\"MemorySubscriptionStore.nextDeadline\"));\n\n const compact: SubscriptionStore[\"Service\"][\"compact\"] = Effect.fn(\n \"MemorySubscriptionStore.compact\",\n )(function* (nowMillis, inputPolicy, requestedLimit) {\n nowMillis = Math.min(nowMillis, yield* Clock.currentTimeMillis);\n const policy = yield* validate(SubscriptionRetentionPolicy, inputPolicy, \"retention-policy\");\n\n const limit = yield* validate(\n Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 100 })),\n requestedLimit,\n \"maintenance-limit\",\n );\n\n yield* failpoint.hit(\"subscription:compact:before\");\n let corruptCandidates = 0;\n\n const result = yield* Effect.uninterruptible(\n Ref.modify(\n state,\n (current): readonly [Result.Result<number, SubscriptionError>, MemorySubscriptionState] => {\n if (\n current.retentionHorizon !== null &&\n current.retentionHorizon !== policy.replayHorizonMillis\n )\n return [Result.fail(error(\"conflict\", \"retention-horizon\")), current];\n const events = new Map(current.events);\n const eventIndex = new Map(current.eventIndex);\n const deliveries = new Map(current.deliveries);\n const deliveryIndex = new Map(current.deliveryIndex);\n const eventDeliveryCounts = new Map(current.eventDeliveryCounts);\n const ownerDeliveryCounts = new Map(current.ownerDeliveryCounts);\n\n // Page indexes before decoding. Each pass reads at most 2 * limit event values and\n // limit delivery values; relationship checks use maintained reference counts.\n const deliveryPage = current.deliveryKeys.slice(\n upperBound(current.deliveryKeys, current.maintenanceDeliveries),\n upperBound(current.deliveryKeys, current.maintenanceDeliveries) + limit,\n );\n\n const eventPage = current.eventKeys.slice(\n upperBound(current.eventKeys, current.maintenanceEvents),\n upperBound(current.eventKeys, current.maintenanceEvents) + limit,\n );\n\n const cutoff = nowMillis - policy.completedRetentionMillis;\n let removed = 0;\n const removedEvents = new Set<string>();\n const removedDeliveries = new Set<string>();\n\n for (const key of deliveryPage) {\n const text = deliveries.get(key);\n\n if (text === undefined) continue;\n const decoded = decode(SubscriptionDelivery, text, \"compact-delivery\");\n\n if (Result.isFailure(decoded)) {\n corruptCandidates++;\n continue;\n }\n const delivery = decoded.success;\n\n if (\n subscriptionDeliveryKeyString(delivery.key) !== key ||\n !samePartition(delivery.key.subscription.partition, partition)\n ) {\n corruptCandidates++;\n continue;\n }\n\n if (\n delivery.state !== \"refused\" &&\n (delivery.state !== \"delivered\" || delivery.settledAtMillis === undefined)\n )\n continue;\n if (\n (delivery.settledAtMillis ??\n delivery.completedAtMillis ??\n delivery.selectedAtMillis) > cutoff\n )\n continue;\n const eventText = events.get(delivery.key.eventId);\n\n if (eventText === undefined) continue;\n const accepted = decode(AcceptedEvent, eventText, \"compact-delivery-event\");\n\n if (Result.isFailure(accepted)) {\n corruptCandidates++;\n continue;\n }\n const event = accepted.success;\n\n if (\n event.eventId !== delivery.key.eventId ||\n !samePartition(event.partition, partition)\n ) {\n corruptCandidates++;\n continue;\n }\n\n if (\n !event.routingComplete ||\n event.occurredAtMillis === undefined ||\n event.acceptedAtMillis > cutoff ||\n (current.recoveryCounts.get(eventCandidateIndexKey(event)) ?? 0) > 0\n )\n continue;\n deliveries.delete(key);\n removedDeliveries.add(key);\n deliveryIndex.delete(key);\n eventDeliveryCounts.set(\n event.eventId,\n (eventDeliveryCounts.get(event.eventId) ?? 1) - 1,\n );\n const owner = delivery.key.subscription.ownerId;\n\n ownerDeliveryCounts.set(owner, (ownerDeliveryCounts.get(owner) ?? 1) - 1);\n }\n let tombstones = current.tombstoneCount;\n\n for (const key of eventPage) {\n const text = events.get(key);\n\n if (text === undefined) continue;\n const decoded = decode(AcceptedEvent, text, \"compact-event\");\n\n if (Result.isFailure(decoded)) {\n corruptCandidates++;\n continue;\n }\n const event = decoded.success;\n\n if (event.eventId !== key || !samePartition(event.partition, partition)) {\n corruptCandidates++;\n continue;\n }\n\n if (!event.routingComplete || event.occurredAtMillis === undefined) continue;\n const expired = event.occurredAtMillis <= nowMillis - policy.replayHorizonMillis;\n\n if (event.tombstone === true && !expired) continue;\n if (\n event.acceptedAtMillis > cutoff ||\n (eventDeliveryCounts.get(key) ?? 0) > 0 ||\n (current.recoveryCounts.get(eventCandidateIndexKey(event)) ?? 0) > 0\n )\n continue;\n if (expired) {\n events.delete(key);\n removedEvents.add(key);\n eventIndex.delete(key);\n eventDeliveryCounts.delete(key);\n if (event.tombstone === true) tombstones--;\n } else {\n if (tombstones >= policy.maxTombstones) continue;\n\n const encoded = encode(\n AcceptedEvent,\n { ...event, payload: null, tombstone: true },\n \"compact-tombstone\",\n );\n\n if (Result.isFailure(encoded)) continue;\n events.set(key, encoded.success);\n tombstones++;\n }\n removed++;\n }\n\n return [\n Result.succeed(removed),\n {\n ...current,\n events,\n eventIndex,\n deliveries,\n deliveryIndex,\n eventDeliveryCounts,\n ownerDeliveryCounts,\n eventKeys: removeKeys(current.eventKeys, removedEvents),\n deliveryKeys: removeKeys(current.deliveryKeys, removedDeliveries),\n tombstoneCount: tombstones,\n maintenanceEvents: eventPage.length < limit ? \"\" : (eventPage.at(-1) ?? \"\"),\n maintenanceDeliveries: deliveryPage.length < limit ? \"\" : (deliveryPage.at(-1) ?? \"\"),\n retentionHorizon: policy.replayHorizonMillis,\n retentionDeadline: events.size === 0 ? null : nowMillis + 60_000,\n },\n ];\n },\n ),\n ).pipe(Effect.flatMap(Effect.fromResult));\n\n if (corruptCandidates > 0)\n yield* Effect.logWarning(\"Subscription retention preserved corrupt candidates\", {\n count: corruptCandidates,\n });\n yield* failpoint.hit(\"subscription:compact:after\");\n\n return result;\n });\n\n return SubscriptionStore.of({\n partition,\n compact,\n register,\n get,\n list,\n cancel,\n change,\n accept,\n event,\n pendingEvents,\n candidates,\n select,\n catchUp,\n deferEvent,\n delivery,\n pendingDeliveries,\n listDeliveries,\n changeDelivery,\n recovering,\n deferRecovery,\n readScanCursors,\n advanceScanCursors,\n nextDeadline,\n });\n});\n\nexport const memorySubscriptionStoreLayer = (\n partition: SourcePartition,\n): Layer.Layer<SubscriptionStore, SubscriptionError> =>\n Layer.effect(SubscriptionStore, makeMemorySubscriptionStore(partition));\n"],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { Crypto, Layer } from "effect";
2
+ import { ThreadStore } from "@effect-agent/thread/ThreadStore";
3
+ declare namespace MemoryThreadStore_d_exports {
4
+ export { MemoryThreadStoreLive, memoryThreadStoreLayer };
5
+ }
6
+ /**
7
+ * In-memory canonical Thread persistence. Durable accepted work is served by the separate
8
+ * SubmissionLedger port; this Layer deliberately provides only the ThreadStore.
9
+ */
10
+ declare const MemoryThreadStoreLive: Layer.Layer<ThreadStore, never, Crypto.Crypto>;
11
+ /** Configure a finite retained Thread capacity. Invalid construction options throw immediately. */
12
+ declare const memoryThreadStoreLayer: (options?: {
13
+ readonly maxThreads?: number;
14
+ }) => Layer.Layer<ThreadStore, never, Crypto.Crypto>;
15
+ //#endregion
16
+ export { MemoryThreadStoreLive, memoryThreadStoreLayer, MemoryThreadStore_d_exports as t };
17
+ //# sourceMappingURL=MemoryThreadStore.d.mts.map
@@ -0,0 +1,377 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
+ import { Context, Crypto, Effect, Encoding, Layer, Option, PubSub, Ref, Schema, Stream } from "effect";
3
+ import { ThreadId } from "@effect-agent/core/Identifiers";
4
+ import { CanonicalRecordEnvelope, CanonicalSequence, ObservationOffset } from "@effect-agent/thread/Records";
5
+ import { EMPTY_TAIL_DIGEST, digestCanonicalBatch } from "@effect-agent/thread/Digest";
6
+ import { AppendConflict, AppendResult, CheckpointRejected, FenceRejected, FencedAppendRequest, LoadCheckpointRequest, MAX_THREAD_EXPORT_RECORDS, SaveCheckpointRequest, SaveRecoveryCheckpointRequest, ThreadExport, ThreadExportRequest, ThreadMaterialization, ThreadNotMaterialized, ThreadObservation, ThreadRead, ThreadStore, ThreadStoreError, ThreadTail, ThreadTailRequest } from "@effect-agent/thread/ThreadStore";
7
+ //#region src/MemoryThreadStore.ts
8
+ var MemoryThreadStore_exports = /* @__PURE__ */ __exportAll({
9
+ MemoryThreadStoreLive: () => MemoryThreadStoreLive,
10
+ memoryThreadStoreLayer: () => memoryThreadStoreLayer
11
+ });
12
+ const MAX_THREADS = 256;
13
+ const MAX_RECORDS_PER_THREAD = MAX_THREAD_EXPORT_RECORDS;
14
+ const MAX_CHECKPOINTS_PER_THREAD = 1024;
15
+ const ThreadCapacity = Context.Reference("@effect-agent/storage-memory/MemoryThreadStore/ThreadCapacity", { defaultValue: () => MAX_THREADS });
16
+ const storeError = (operation, message, cause) => cause === void 0 ? ThreadStoreError.make({
17
+ operation,
18
+ message
19
+ }) : ThreadStoreError.make({
20
+ operation,
21
+ message,
22
+ cause
23
+ });
24
+ const validate = Effect.fn("MemoryThreadStore.validate")((schema, operation, value) => Schema.encodeUnknownEffect(schema)(value).pipe(Effect.flatMap(Schema.decodeUnknownEffect(schema)), Effect.mapError((error) => storeError(operation, `Invalid ${operation} request`, error))));
25
+ const decodeCanonicalSequence = Schema.decodeSync(CanonicalSequence);
26
+ const ZERO_CANONICAL_SEQUENCE = decodeCanonicalSequence(0);
27
+ const offsetSequence = Effect.fn("MemoryThreadStore.offsetSequence")((threadId, offset) => {
28
+ if (offset === void 0) return Effect.succeed(ZERO_CANONICAL_SEQUENCE);
29
+ const prefix = `memory:v1:${Encoding.encodeBase64(threadId)}:`;
30
+ const encodedSequence = offset.startsWith(prefix) ? offset.slice(prefix.length) : "";
31
+ if (!/^\d+$/.test(encodedSequence)) return Effect.fail(storeError("observe", "Malformed observation offset"));
32
+ const sequence = Number(encodedSequence);
33
+ return Number.isSafeInteger(sequence) ? Schema.decodeUnknownEffect(CanonicalSequence)(sequence).pipe(Effect.mapError(() => storeError("observe", "Malformed observation offset"))) : Effect.fail(storeError("observe", "Malformed observation offset"));
34
+ });
35
+ const observationOffset = (threadId, sequence) => Schema.decodeSync(ObservationOffset)(`memory:v1:${Encoding.encodeBase64(threadId)}:${sequence}`);
36
+ const findThread = Effect.fn("MemoryThreadStore.findThread")((state, threadId) => {
37
+ const thread = state.threads.get(threadId);
38
+ return thread === void 0 ? Effect.fail(ThreadNotMaterialized.make({ threadId })) : Effect.succeed(thread);
39
+ });
40
+ const CheckpointVersionEnvelope = Schema.Struct({ checkpoint: Schema.Struct({
41
+ threadId: ThreadId,
42
+ schemaVersion: Schema.Natural
43
+ }) });
44
+ const validateCheckpointVersion = Effect.fn("MemoryThreadStore.validateCheckpointVersion")(function* (value) {
45
+ const envelope = yield* Schema.decodeUnknownEffect(CheckpointVersionEnvelope)(value).pipe(Effect.mapError(() => storeError("saveCheckpoint", "Invalid saveCheckpoint request")));
46
+ if (envelope.checkpoint.schemaVersion !== 1) return yield* CheckpointRejected.make({
47
+ threadId: envelope.checkpoint.threadId,
48
+ reason: "unsupported-version"
49
+ });
50
+ });
51
+ const makeThreadStore = Effect.gen(function* () {
52
+ const maxThreads = yield* ThreadCapacity;
53
+ const crypto = yield* Crypto.Crypto;
54
+ const state = yield* Ref.make({ threads: /* @__PURE__ */ new Map() });
55
+ const updates = yield* PubSub.sliding(1);
56
+ yield* Effect.addFinalizer(() => PubSub.shutdown(updates));
57
+ const materialize = Effect.fn("MemoryThreadStore.materialize")((unvalidated) => Effect.gen(function* () {
58
+ const request = yield* validate(ThreadMaterialization, "materialize", unvalidated);
59
+ const decision = yield* Ref.modify(state, (current) => {
60
+ const existing = current.threads.get(request.threadId);
61
+ if (existing !== void 0) {
62
+ if (request.producerEpoch < existing.producerEpoch) return [{
63
+ _tag: "failure",
64
+ error: FenceRejected.make({
65
+ threadId: request.threadId,
66
+ actualEpoch: existing.producerEpoch,
67
+ attemptedEpoch: request.producerEpoch
68
+ })
69
+ }, current];
70
+ if (request.producerEpoch === existing.producerEpoch) return [{ _tag: "success" }, current];
71
+ const threads = new Map(current.threads);
72
+ threads.set(request.threadId, {
73
+ ...existing,
74
+ producerEpoch: request.producerEpoch
75
+ });
76
+ return [{ _tag: "success" }, { threads }];
77
+ }
78
+ if (current.threads.size >= maxThreads) return [{
79
+ _tag: "failure",
80
+ error: storeError("materialize", `In-memory thread limit ${maxThreads} exceeded`)
81
+ }, current];
82
+ const threads = new Map(current.threads);
83
+ threads.set(request.threadId, {
84
+ producerEpoch: request.producerEpoch,
85
+ tailSequence: ZERO_CANONICAL_SEQUENCE,
86
+ tailDigest: EMPTY_TAIL_DIGEST,
87
+ records: [],
88
+ recordIds: /* @__PURE__ */ new Set(),
89
+ batches: /* @__PURE__ */ new Map(),
90
+ tailDigests: /* @__PURE__ */ new Map([[ZERO_CANONICAL_SEQUENCE, EMPTY_TAIL_DIGEST]]),
91
+ checkpoints: /* @__PURE__ */ new Map()
92
+ });
93
+ return [{ _tag: "success" }, { threads }];
94
+ });
95
+ if (decision._tag === "failure") return yield* decision.error;
96
+ }));
97
+ const append = Effect.fn("MemoryThreadStore.append")((unvalidated) => Effect.gen(function* () {
98
+ const request = yield* validate(FencedAppendRequest, "append", unvalidated);
99
+ const digest = yield* digestCanonicalBatch(request.expectedTailDigest, request.batch).pipe(Effect.provideService(Crypto.Crypto, crypto), Effect.mapError((error) => storeError("append", error.message, error)));
100
+ const decision = yield* Effect.uninterruptible(Ref.modify(state, (current) => {
101
+ const thread = current.threads.get(request.threadId);
102
+ if (thread === void 0) return [{
103
+ _tag: "failure",
104
+ error: ThreadNotMaterialized.make({ threadId: request.threadId })
105
+ }, current];
106
+ if (request.producerEpoch !== thread.producerEpoch) return [{
107
+ _tag: "failure",
108
+ error: FenceRejected.make({
109
+ threadId: request.threadId,
110
+ actualEpoch: thread.producerEpoch,
111
+ attemptedEpoch: request.producerEpoch
112
+ })
113
+ }, current];
114
+ const previous = thread.batches.get(request.batch.batchId);
115
+ if (previous !== void 0) {
116
+ if (previous.digest !== digest) return [{
117
+ _tag: "failure",
118
+ error: AppendConflict.make({
119
+ threadId: request.threadId,
120
+ batchId: request.batch.batchId,
121
+ reason: "batch-digest"
122
+ })
123
+ }, current];
124
+ return [{
125
+ _tag: "success",
126
+ result: AppendResult.make({
127
+ firstSequence: previous.result.firstSequence,
128
+ lastSequence: previous.result.lastSequence,
129
+ tailDigest: previous.result.tailDigest,
130
+ replayed: true
131
+ }),
132
+ records: []
133
+ }, current];
134
+ }
135
+ if (request.expectedTailSequence !== thread.tailSequence || request.expectedTailDigest !== thread.tailDigest) return [{
136
+ _tag: "failure",
137
+ error: AppendConflict.make({
138
+ threadId: request.threadId,
139
+ batchId: request.batch.batchId,
140
+ reason: "tail",
141
+ actualTailSequence: thread.tailSequence,
142
+ actualTailDigest: thread.tailDigest
143
+ })
144
+ }, current];
145
+ if (thread.records.length + request.batch.records.length > MAX_RECORDS_PER_THREAD) return [{
146
+ _tag: "failure",
147
+ error: storeError("append", `In-memory record limit ${MAX_RECORDS_PER_THREAD} exceeded`)
148
+ }, current];
149
+ const batchRecordIds = /* @__PURE__ */ new Set();
150
+ for (const record of request.batch.records) {
151
+ if (thread.recordIds.has(record.recordId) || batchRecordIds.has(record.recordId)) return [{
152
+ _tag: "failure",
153
+ error: AppendConflict.make({
154
+ threadId: request.threadId,
155
+ batchId: request.batch.batchId,
156
+ reason: "record-identity"
157
+ })
158
+ }, current];
159
+ batchRecordIds.add(record.recordId);
160
+ }
161
+ const records = request.batch.records.map((record, index) => {
162
+ const sequence = decodeCanonicalSequence(thread.tailSequence + index + 1);
163
+ return CanonicalRecordEnvelope.make({
164
+ threadId: request.threadId,
165
+ batchId: request.batch.batchId,
166
+ sequence,
167
+ offset: observationOffset(request.threadId, sequence),
168
+ record
169
+ });
170
+ });
171
+ const lastSequence = decodeCanonicalSequence(thread.tailSequence + records.length);
172
+ const result = AppendResult.make({
173
+ firstSequence: decodeCanonicalSequence(thread.tailSequence + 1),
174
+ lastSequence,
175
+ tailDigest: digest,
176
+ replayed: false
177
+ });
178
+ const batches = new Map(thread.batches);
179
+ batches.set(request.batch.batchId, {
180
+ digest,
181
+ result
182
+ });
183
+ const recordIds = new Set(thread.recordIds);
184
+ for (const recordId of batchRecordIds) recordIds.add(recordId);
185
+ const tailDigests = new Map(thread.tailDigests);
186
+ tailDigests.set(lastSequence, digest);
187
+ const threads = new Map(current.threads);
188
+ threads.set(request.threadId, {
189
+ ...thread,
190
+ tailSequence: lastSequence,
191
+ tailDigest: digest,
192
+ records: [...thread.records, ...records],
193
+ recordIds,
194
+ batches,
195
+ tailDigests
196
+ });
197
+ return [{
198
+ _tag: "success",
199
+ result,
200
+ records
201
+ }, { threads }];
202
+ }).pipe(Effect.tap((decision) => decision._tag === "success" && decision.records.length > 0 ? PubSub.publish(updates, void 0) : Effect.void)));
203
+ if (decision._tag === "failure") return yield* decision.error;
204
+ return decision.result;
205
+ }));
206
+ const readSnapshot = Effect.fn("MemoryThreadStore.readSnapshot")((threadId, afterSequence, limit) => Ref.get(state).pipe(Effect.flatMap((current) => findThread(current, threadId)), Effect.map((thread) => {
207
+ const start = afterSequence ?? ZERO_CANONICAL_SEQUENCE;
208
+ return thread.records.slice(start, start + limit);
209
+ })));
210
+ const read = (unvalidated) => Stream.unwrap(Effect.gen(function* () {
211
+ const request = yield* validate(ThreadRead, "read", unvalidated);
212
+ const records = yield* readSnapshot(request.threadId, request.afterSequence, request.limit);
213
+ return Stream.fromIterable(records);
214
+ }));
215
+ const observe = (unvalidated) => Stream.unwrap(Effect.gen(function* () {
216
+ const request = yield* validate(ThreadObservation, "observe", unvalidated);
217
+ const afterSequence = yield* offsetSequence(request.threadId, request.afterOffset);
218
+ return Stream.unwrap(Effect.gen(function* () {
219
+ const subscription = yield* PubSub.subscribe(updates);
220
+ const initial = yield* readSnapshot(request.threadId, afterSequence, MAX_RECORDS_PER_THREAD);
221
+ const highWater = initial.length === 0 ? afterSequence : initial.at(-1)?.sequence ?? afterSequence;
222
+ const live = Stream.fromEffectRepeat(PubSub.take(subscription)).pipe(Stream.mapAccumEffect(() => highWater, (lastSequence) => readSnapshot(request.threadId, lastSequence, MAX_RECORDS_PER_THREAD).pipe(Effect.map((records) => [records.at(-1)?.sequence ?? lastSequence, records]))));
223
+ return Stream.fromIterable(initial).pipe(Stream.concat(live));
224
+ }));
225
+ }));
226
+ const exportThread = Effect.fn("MemoryThreadStore.export")((unvalidated) => Effect.gen(function* () {
227
+ const request = yield* validate(ThreadExportRequest, "export", unvalidated);
228
+ const thread = yield* Ref.get(state).pipe(Effect.flatMap((current) => findThread(current, request.threadId)));
229
+ return ThreadExport.make({
230
+ format: "effect-agent/thread@1",
231
+ threadId: request.threadId,
232
+ tailSequence: thread.tailSequence,
233
+ tailDigest: thread.tailDigest,
234
+ records: thread.records
235
+ });
236
+ }));
237
+ const inspectTail = Effect.fn("MemoryThreadStore.inspectTail")((unvalidated) => Effect.gen(function* () {
238
+ const request = yield* validate(ThreadTailRequest, "inspectTail", unvalidated);
239
+ const thread = yield* Ref.get(state).pipe(Effect.flatMap((current) => findThread(current, request.threadId)));
240
+ return ThreadTail.make({
241
+ threadId: request.threadId,
242
+ tailSequence: thread.tailSequence,
243
+ tailDigest: thread.tailDigest,
244
+ producerEpoch: thread.producerEpoch
245
+ });
246
+ }));
247
+ const saveCheckpoint = Effect.fn("MemoryThreadStore.saveCheckpoint")((unvalidated) => Effect.gen(function* () {
248
+ yield* validateCheckpointVersion(unvalidated);
249
+ const request = yield* validate(SaveCheckpointRequest, "saveCheckpoint", unvalidated);
250
+ const decision = yield* Ref.modify(state, (current) => {
251
+ const checkpoint = request.checkpoint;
252
+ const thread = current.threads.get(checkpoint.threadId);
253
+ if (thread === void 0) return [{
254
+ _tag: "failure",
255
+ error: ThreadNotMaterialized.make({ threadId: checkpoint.threadId })
256
+ }, current];
257
+ if (checkpoint.throughSequence > thread.tailSequence) return [{
258
+ _tag: "failure",
259
+ error: CheckpointRejected.make({
260
+ threadId: checkpoint.threadId,
261
+ reason: "ahead-of-tail"
262
+ })
263
+ }, current];
264
+ if (thread.tailDigests.get(checkpoint.throughSequence) !== checkpoint.tailDigest) return [{
265
+ _tag: "failure",
266
+ error: CheckpointRejected.make({
267
+ threadId: checkpoint.threadId,
268
+ reason: "digest-mismatch"
269
+ })
270
+ }, current];
271
+ if (!thread.checkpoints.has(checkpoint.throughSequence) && thread.checkpoints.size >= MAX_CHECKPOINTS_PER_THREAD) return [{
272
+ _tag: "failure",
273
+ error: storeError("saveCheckpoint", `In-memory checkpoint limit ${MAX_CHECKPOINTS_PER_THREAD} exceeded`)
274
+ }, current];
275
+ const checkpoints = new Map(thread.checkpoints);
276
+ checkpoints.set(checkpoint.throughSequence, checkpoint);
277
+ const threads = new Map(current.threads);
278
+ threads.set(checkpoint.threadId, {
279
+ ...thread,
280
+ checkpoints
281
+ });
282
+ return [{ _tag: "success" }, { threads }];
283
+ });
284
+ if (decision._tag === "failure") return yield* decision.error;
285
+ }));
286
+ const loadCheckpoint = Effect.fn("MemoryThreadStore.loadCheckpoint")((unvalidated) => Effect.gen(function* () {
287
+ const request = yield* validate(LoadCheckpointRequest, "loadCheckpoint", unvalidated);
288
+ const thread = yield* Ref.get(state).pipe(Effect.flatMap((current) => findThread(current, request.threadId)));
289
+ const maximum = request.atOrBeforeSequence ?? thread.tailSequence;
290
+ let selected;
291
+ for (const [sequence, checkpoint] of thread.checkpoints) if (sequence <= maximum && (selected === void 0 || sequence > selected.throughSequence)) selected = checkpoint;
292
+ if (selected !== void 0 && thread.tailDigests.get(selected.throughSequence) !== selected.tailDigest) return yield* CheckpointRejected.make({
293
+ threadId: request.threadId,
294
+ reason: "digest-mismatch"
295
+ });
296
+ return Option.fromNullishOr(selected);
297
+ }));
298
+ const saveRecoveryCheckpoint = Effect.fn("MemoryThreadStore.saveRecoveryCheckpoint")(function* (unvalidated) {
299
+ const request = yield* validate(SaveRecoveryCheckpointRequest, "saveRecoveryCheckpoint", unvalidated);
300
+ const decision = yield* Ref.modify(state, (current) => {
301
+ const checkpoint = request.checkpoint;
302
+ const thread = current.threads.get(checkpoint.threadId);
303
+ if (thread === void 0) return [{
304
+ _tag: "failure",
305
+ error: ThreadNotMaterialized.make({ threadId: checkpoint.threadId })
306
+ }, current];
307
+ if (thread.producerEpoch !== request.producerEpoch) return [{
308
+ _tag: "failure",
309
+ error: FenceRejected.make({
310
+ threadId: checkpoint.threadId,
311
+ actualEpoch: thread.producerEpoch,
312
+ attemptedEpoch: request.producerEpoch
313
+ })
314
+ }, current];
315
+ if (checkpoint.throughSequence > thread.tailSequence) return [{
316
+ _tag: "failure",
317
+ error: CheckpointRejected.make({
318
+ threadId: checkpoint.threadId,
319
+ reason: "ahead-of-tail"
320
+ })
321
+ }, current];
322
+ if (thread.tailDigests.get(checkpoint.throughSequence) !== checkpoint.tailDigest) return [{
323
+ _tag: "failure",
324
+ error: CheckpointRejected.make({
325
+ threadId: checkpoint.threadId,
326
+ reason: "digest-mismatch"
327
+ })
328
+ }, current];
329
+ if ((thread.recoveryCheckpoint?.throughSequence ?? -1) > checkpoint.throughSequence) return [{ _tag: "success" }, current];
330
+ const threads = new Map(current.threads);
331
+ threads.set(checkpoint.threadId, {
332
+ ...thread,
333
+ recoveryCheckpoint: checkpoint
334
+ });
335
+ return [{ _tag: "success" }, { threads }];
336
+ });
337
+ if (decision._tag === "failure") return yield* decision.error;
338
+ });
339
+ const loadRecoveryCheckpoint = Effect.fn("MemoryThreadStore.loadRecoveryCheckpoint")(function* (unvalidated) {
340
+ const request = yield* validate(LoadCheckpointRequest, "loadRecoveryCheckpoint", unvalidated);
341
+ const thread = yield* Ref.get(state).pipe(Effect.flatMap((current) => findThread(current, request.threadId)));
342
+ const checkpoint = thread.recoveryCheckpoint;
343
+ if (checkpoint === void 0 || checkpoint.throughSequence > (request.atOrBeforeSequence ?? thread.tailSequence)) return Option.none();
344
+ if (thread.tailDigests.get(checkpoint.throughSequence) !== checkpoint.tailDigest) return yield* CheckpointRejected.make({
345
+ threadId: request.threadId,
346
+ reason: "digest-mismatch"
347
+ });
348
+ return Option.some(checkpoint);
349
+ });
350
+ return ThreadStore.of({
351
+ materialize,
352
+ append,
353
+ read,
354
+ observe,
355
+ export: exportThread,
356
+ inspectTail,
357
+ checkpoints: {
358
+ save: saveCheckpoint,
359
+ load: loadCheckpoint
360
+ },
361
+ recoveryCheckpoints: {
362
+ save: saveRecoveryCheckpoint,
363
+ load: loadRecoveryCheckpoint
364
+ }
365
+ });
366
+ });
367
+ /**
368
+ * In-memory canonical Thread persistence. Durable accepted work is served by the separate
369
+ * SubmissionLedger port; this Layer deliberately provides only the ThreadStore.
370
+ */
371
+ const MemoryThreadStoreLive = Layer.effect(ThreadStore, makeThreadStore);
372
+ /** Configure a finite retained Thread capacity. Invalid construction options throw immediately. */
373
+ const memoryThreadStoreLayer = (options = {}) => MemoryThreadStoreLive.pipe(Layer.provide(Layer.succeed(ThreadCapacity)(Schema.decodeSync(Schema.Int.check(Schema.isGreaterThan(0), Schema.isLessThanOrEqualTo(65536)))(options.maxThreads ?? MAX_THREADS))));
374
+ //#endregion
375
+ export { MemoryThreadStoreLive, memoryThreadStoreLayer, MemoryThreadStore_exports as t };
376
+
377
+ //# sourceMappingURL=MemoryThreadStore.mjs.map