@effect-agent/storage-memory 0.1.0-beta.45 → 0.1.0-beta.47

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.
@@ -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 SourcePartition,\n SubscriptionDelivery,\n SubscriptionDeliveryKey,\n SubscriptionError,\n SubscriptionFailpoint,\n SubscriptionKey,\n SubscriptionLimits,\n SubscriptionName,\n SubscriptionRecord,\n SubscriptionScanCursors,\n SubscriptionStore,\n subscriptionDeliveryKeyString,\n subscriptionKeyString,\n} from \"@effect-agent/thread/Subscription\";\nimport {\n applySubscriptionDeliveryChange,\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 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 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 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 = (left: AcceptedEvent, right: AcceptedEvent): boolean =>\n samePartition(left.partition, right.partition) &&\n left.eventId === right.eventId &&\n sameSource(left.source, right.source) &&\n left.matchingKey === right.matchingKey &&\n left.payloadDigest === right.payloadDigest;\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\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 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 - record.createdAtMillis >\n 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 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 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 cancel: SubscriptionStore[\"Service\"][\"cancel\"] = Effect.fn(\n \"MemorySubscriptionStore.cancel\",\n )(function* (input) {\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 (decoded.success.state === \"cancelled\")\n return [Result.succeed(decoded.success), current];\n const cancelled = { ...decoded.success, state: \"cancelled\" as const, recovery: null };\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, { ...indexed, state: \"cancelled\", recoveryAt: null });\n\n return [Result.succeed(cancelled), { ...current, registrations, registrationIndex }];\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 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 (jsonBytes(event.payload) > limits.maxPayloadBytes)\n return [Result.fail(error(\"capacity\", \"payload-bytes\")), current];\n if (current.events.size >= 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 { ...current, sequence: accepted.cutoff, events, eventIndex },\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 },\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 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 events,\n eventIndex,\n deliveries: nextDeliveries,\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, { ...indexed, state: \"consumed\", recoveryAt: null });\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\n ownerDeliveryCounts.set(consumed.key.ownerId, ownerCount + 1);\n\n return [\n Result.void,\n {\n ...current,\n deliveries,\n deliveryIndex,\n ownerDeliveryCounts,\n registrations,\n registrationIndex,\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\" &&\n item.state !== \"refused\" &&\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 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, 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 const updated = {\n ...record.success,\n recovery: record.success.state === \"active\" ? recovery : 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 recoveryAt: updated.recovery?.nextAttemptAtMillis ?? null,\n });\n\n return [Result.void, { ...current, registrations, registrationIndex }];\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 for (const accepted of current.eventIndex.values())\n if (!accepted.routingComplete) consider(accepted.nextAttemptAtMillis);\n for (const item of current.deliveryIndex.values())\n if (item.state !== \"delivered\" && item.state !== \"refused\")\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 return SubscriptionStore.of({\n partition,\n register,\n get,\n list,\n cancel,\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":";;;;;;;;AAwDA,MAAM,SAAS,QAAqC,SAClD,kBAAkB,KAAK;CAAE;CAAQ;AAAK,CAAC;AAEzC,MAAM,iBAAiB,MAAuB,UAC5C,KAAK,aAAa,MAAM,YAAY,KAAK,YAAY,MAAM;AAE7D,MAAM,cAAc,MAA+B,UACjD,KAAK,SAAS,MAAM,QAAQ,KAAK,YAAY,MAAM;AAErD,MAAM,UACJ,QACA,OACA,SAEA,OAAO,IAAI;CACT,WAAW,OAAO,WAAW,OAAO,eAAe,MAAM,CAAC,CAAC,CAAC,KAAK;CACjE,aAAa,MAAM,WAAW,IAAI;AACpC,CAAC;AAEH,MAAM,UACJ,QACA,OACA,SAEA,OAAO,IAAI;CACT,WAAW,OAAO,WAAW,OAAO,eAAe,MAAM,CAAC,CAAC,CAAC,KAAK;CACjE,aAAa,MAAM,WAAW,IAAI;AACpC,CAAC;AAEH,MAAM,gBAAsB,QAA4B,OAAe,SACrE,OAAO,WAAW,OAAO,QAAQ,OAAO,IAAI,CAAC;AAE/C,MAAM,YAAkB,QAA4B,OAAgB,SAClE,OAAO,oBAAoB,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,OAAO,eAAe,MAAM,cAAc,IAAI,CAAC,CAAC;AAEjG,MAAM,aAAa,UACjB,IAAI,YAAY,CAAC,CAAC,OAAO,KAAK,UAAU,KAAK,CAAC,CAAC,CAAC;AAElD,MAAM,wBAAwB,MAA4B,UACxD,8BAA8B,KAAK,GAAG,MAAM,8BAA8B,MAAM,GAAG,KACnF,KAAK,eAAe,MAAM,cAC1B,KAAK,OAAO,SAAS,MAAM,OAAO,QAClC,KAAK,OAAO,YAAY,MAAM,OAAO,WACrC,KAAK,aAAa,MAAM,YACxB,KAAK,iBAAiB,MAAM,gBAC5B,KAAK,4BAA4B,MAAM,2BACvC,KAAK,gBAAgB,MAAM;AAE7B,MAAM,qBAAqB,WACzB,KAAK,UAAU;CACb,OAAO,cAAc,OAAO;CAC5B,OAAO,cAAc,OAAO;CAC5B,OAAO,cAAc;AACvB,CAAC;AAEH,MAAM,0BAA0B,UAC9B,KAAK,UAAU;CAAC,MAAM,OAAO;CAAM,MAAM,OAAO;CAAS,MAAM;AAAW,CAAC;AAE7E,MAAM,qBAAqB,MAAqB,UAC9C,cAAc,KAAK,WAAW,MAAM,SAAS,KAC7C,KAAK,YAAY,MAAM,WACvB,WAAW,KAAK,QAAQ,MAAM,MAAM,KACpC,KAAK,gBAAgB,MAAM,eAC3B,KAAK,kBAAkB,MAAM;AAE/B,MAAM,qBACJ,UACA,QACA,UAEA,sBAAsB,SAAS,IAAI,YAAY,MAAM,sBAAsB,OAAO,GAAG,KACrF,SAAS,IAAI,YAAY,MAAM,WAC/B,WAAW,SAAS,QAAQ,MAAM,MAAM;AAE1C,MAAM,8BAA8B,OAAO,GAAG,6BAA6B,CAAC,CAAC,WAC3E,gBACA;CACA,MAAM,YAAY,OAAO,SAAS,iBAAiB,gBAAgB,WAAW;CAE9E,MAAM,QAAQ,OAAO,IAAI,KAA8B;EACrD,UAAU;EACV,+BAAe,IAAI,IAAI;EACvB,wBAAQ,IAAI,IAAI;EAChB,4BAAY,IAAI,IAAI;EACpB,mCAAmB,IAAI,IAAI;EAC3B,gCAAgB,IAAI,IAAI;EACxB,yCAAyB,IAAI,IAAI;EACjC,4BAAY,IAAI,IAAI;EACpB,+BAAe,IAAI,IAAI;EACvB,qCAAqB,IAAI,IAAI;EAC7B,aAAa;GAAE,QAAQ;GAAI,YAAY;GAAI,UAAU;EAAE;CACzD,CAAC;CAED,MAAM,YAAY,OAAO;CAEzB,MAAM,oBACJ,OACA,SAEA,cAAc,MAAM,WAAW,SAAS,IACpC,OAAO,QAAQ,KAAK,IACpB,OAAO,KAAK,MAAM,cAAc,IAAI,CAAC;CAE3C,MAAM,cAAc,KAAsB,SACxC,SAAS,iBAAiB,KAAK,IAAI,CAAC,CAAC,KACnC,OAAO,SAAS,YAAY,iBAAiB,SAAS,IAAI,CAAC,CAC7D;CAEF,MAAM,WAAqD,OAAO,GAChE,kCACF,CAAC,CAAC,WAAW,OAAO,aAAa;EAC/B,MAAM,SAAS,OAAO,SAAS,oBAAoB,OAAO,iBAAiB;EAC3E,MAAM,SAAS,OAAO,SAAS,oBAAoB,aAAa,iBAAiB;EAEjF,OAAO,iBAAiB,OAAO,KAAK,oBAAoB;EACxD,OAAO,UAAU,IAAI,8BAA8B;EAEnD,MAAM,SAAS,OAAO,OAAO,gBAC3B,IAAI,OACF,QAEE,YAIG;GACH,MAAM,MAAM,sBAAsB,OAAO,GAAG;GAC5C,MAAM,eAAe,QAAQ,cAAc,IAAI,GAAG;GAElD,IAAI,iBAAiB,KAAA,GAAW;IAC9B,MAAM,WAAW,OAAO,oBAAoB,cAAc,mBAAmB;IAE7E,IAAI,OAAO,UAAU,QAAQ,GAAG,OAAO,CAAC,OAAO,KAAK,SAAS,OAAO,GAAG,OAAO;IAE9E,OAAO,SAAS,QAAQ,wBAAwB,OAAO,sBACnD,CAAC,OAAO,QAAQ,SAAS,OAAO,GAAG,OAAO,IAC1C,CAAC,OAAO,KAAK,MAAM,YAAY,uBAAuB,CAAC,GAAG,OAAO;GACvE;GACA,IAAI,UAAU,OAAO,cAAc,OAAO,IAAI,OAAO,iBACnD,OAAO,CAAC,OAAO,KAAK,MAAM,YAAY,eAAe,CAAC,GAAG,OAAO;GAClE,IAAI,UAAU,OAAO,cAAc,UAAU,IAAI,OAAO,iBACtD,OAAO,CAAC,OAAO,KAAK,MAAM,YAAY,kBAAkB,CAAC,GAAG,OAAO;GACrE,IACE,OAAO,cAAc,kBAAkB,OAAO,kBAC9C,OAAO,mBAEP,OAAO,CAAC,OAAO,KAAK,MAAM,YAAY,UAAU,CAAC,GAAG,OAAO;GAC7D,IAAI,QAAQ,cAAc,QAAQ,OAAO,kBACvC,OAAO,CAAC,OAAO,KAAK,MAAM,YAAY,eAAe,CAAC,GAAG,OAAO;GAClE,MAAM,aAAa,QAAQ,wBAAwB,IAAI,OAAO,IAAI,OAAO,KAAK;GAE9E,IAAI,cAAc,OAAO,0BACvB,OAAO,CAAC,OAAO,KAAK,MAAM,YAAY,qBAAqB,CAAC,GAAG,OAAO;GACxE,MAAM,WAAW;IAAE,GAAG;IAAQ,SAAS,QAAQ,WAAW;GAAE;GAC5D,MAAM,UAAU,OAAO,oBAAoB,UAAU,iBAAiB;GAEtE,IAAI,OAAO,UAAU,OAAO,GAAG,OAAO,CAAC,OAAO,KAAK,QAAQ,OAAO,GAAG,OAAO;GAC5E,MAAM,gBAAgB,IAAI,IAAI,QAAQ,aAAa;GAEnD,cAAc,IAAI,KAAK,QAAQ,OAAO;GACtC,MAAM,oBAAoB,IAAI,IAAI,QAAQ,iBAAiB;GAE3D,kBAAkB,IAAI,KAAK;IACzB,KAAK,SAAS;IACd,SAAS,SAAS;IAClB,OAAO,SAAS;IAChB,YAAY,SAAS,UAAU,uBAAuB;GACxD,CAAC;GACD,MAAM,iBAAiB,IAAI,IAAI,QAAQ,cAAc;GACrD,MAAM,eAAe,kBAAkB,QAAQ;GAE/C,eAAe,IAAI,cAAc,CAAC,GAAI,eAAe,IAAI,YAAY,KAAK,CAAC,GAAI,GAAG,CAAC;GACnF,MAAM,0BAA0B,IAAI,IAAI,QAAQ,uBAAuB;GAEvE,wBAAwB,IAAI,SAAS,IAAI,SAAS,aAAa,CAAC;GAEhE,OAAO,CACL,OAAO,QAAQ,QAAQ,GACvB;IACE,GAAG;IACH,UAAU,SAAS;IACnB;IACA;IACA;IACA;GACF,CACF;EACF,CACF,CACF,CAAC,CAAC,KAAK,OAAO,QAAQ,OAAO,UAAU,CAAC;EAExC,OAAO,UAAU,IAAI,6BAA6B;EAElD,OAAO;CACT,CAAC;CAED,MAAM,MAA2C,OAAO,GAAG,6BAA6B,CAAC,CACvF,WAAW,OAAO;EAChB,MAAM,MAAM,OAAO,WAAW,OAAO,SAAS;EAC9C,MAAM,QAAQ,OAAO,IAAI,IAAI,KAAK,EAAA,CAAG,cAAc,IAAI,sBAAsB,GAAG,CAAC;EAEjF,OAAO,SAAS,KAAA,IACZ,OACA,OAAO,aAAa,oBAAoB,MAAM,YAAY;CAChE,CACF;CAEA,MAAM,OAA6C,OAAO,GAAG,8BAA8B,CAAC,CAC1F,WAAW,SAAS,OAAO,OAAO;EAChC,IAAI,CAAC,OAAO,cAAc,KAAK,KAAK,QAAQ,KAAK,CAAC,OAAO,cAAc,KAAK,KAAK,SAAS,GACxF,OAAO,OAAO,MAAM,cAAc,WAAW;EAC/C,MAAM,UAAU,OAAO,IAAI,IAAI,KAAK;EACpC,MAAM,UAAqC,CAAC;EAE5C,KAAK,MAAM,CAAC,YAAY,YAAY,QAAQ,mBAAmB;GAC7D,IAAI,QAAQ,IAAI,YAAY,WAAW,QAAQ,WAAW,OAAO;GACjE,MAAM,OAAO,QAAQ,cAAc,IAAI,UAAU;GAEjD,IAAI,SAAS,KAAA,GAAW,OAAO,OAAO,MAAM,WAAW,YAAY;GACnE,QAAQ,KAAK,OAAO,aAAa,oBAAoB,MAAM,aAAa,CAAC;EAC3E;EACA,QAAQ,MAAM,GAAG,MAAM,EAAE,UAAU,EAAE,OAAO;EAE5C,OAAO,QAAQ,MAAM,GAAG,KAAK;CAC/B,CACF;CAEA,MAAM,SAAiD,OAAO,GAC5D,gCACF,CAAC,CAAC,WAAW,OAAO;EAClB,MAAM,MAAM,OAAO,WAAW,OAAO,YAAY;EAEjD,OAAO,UAAU,IAAI,4BAA4B;EAEjD,MAAM,SAAS,OAAO,OAAO,gBAC3B,IAAI,OACF,QAEE,YAIG;GACH,MAAM,aAAa,sBAAsB,GAAG;GAC5C,MAAM,OAAO,QAAQ,cAAc,IAAI,UAAU;GAEjD,IAAI,SAAS,KAAA,GAAW,OAAO,CAAC,OAAO,KAAK,MAAM,aAAa,cAAc,CAAC,GAAG,OAAO;GACxF,MAAM,UAAU,OAAO,oBAAoB,MAAM,eAAe;GAEhE,IAAI,OAAO,UAAU,OAAO,GAAG,OAAO,CAAC,SAAS,OAAO;GACvD,IAAI,QAAQ,QAAQ,UAAU,aAC5B,OAAO,CAAC,OAAO,QAAQ,QAAQ,OAAO,GAAG,OAAO;GAClD,MAAM,YAAY;IAAE,GAAG,QAAQ;IAAS,OAAO;IAAsB,UAAU;GAAK;GACpF,MAAM,UAAU,OAAO,oBAAoB,WAAW,eAAe;GAErE,IAAI,OAAO,UAAU,OAAO,GAAG,OAAO,CAAC,OAAO,KAAK,QAAQ,OAAO,GAAG,OAAO;GAC5E,MAAM,gBAAgB,IAAI,IAAI,QAAQ,aAAa;GAEnD,cAAc,IAAI,YAAY,QAAQ,OAAO;GAC7C,MAAM,oBAAoB,IAAI,IAAI,QAAQ,iBAAiB;GAC3D,MAAM,UAAU,kBAAkB,IAAI,UAAU;GAEhD,IAAI,YAAY,KAAA,GACd,OAAO,CAAC,OAAO,KAAK,MAAM,WAAW,cAAc,CAAC,GAAG,OAAO;GAChE,kBAAkB,IAAI,YAAY;IAAE,GAAG;IAAS,OAAO;IAAa,YAAY;GAAK,CAAC;GAEtF,OAAO,CAAC,OAAO,QAAQ,SAAS,GAAG;IAAE,GAAG;IAAS;IAAe;GAAkB,CAAC;EACrF,CACF,CACF,CAAC,CAAC,KAAK,OAAO,QAAQ,OAAO,UAAU,CAAC;EAExC,OAAO,UAAU,IAAI,2BAA2B;EAEhD,OAAO;CACT,CAAC;CAED,MAAM,SAAiD,OAAO,GAC5D,gCACF,CAAC,CAAC,WAAW,OAAO,aAAa;EAC/B,MAAM,QAAQ,OAAO,SAAS,eAAe,OAAO,cAAc;EAClE,MAAM,SAAS,OAAO,SAAS,oBAAoB,aAAa,eAAe;EAE/E,OAAO,iBAAiB,OAAO,kBAAkB;EACjD,OAAO,UAAU,IAAI,4BAA4B;EAEjD,MAAM,SAAS,OAAO,OAAO,gBAC3B,IAAI,OACF,QAEE,YACwF;GACxF,MAAM,eAAe,QAAQ,OAAO,IAAI,MAAM,OAAO;GAErD,IAAI,iBAAiB,KAAA,GAAW;IAC9B,MAAM,WAAW,OAAO,eAAe,cAAc,iBAAiB;IAEtE,IAAI,OAAO,UAAU,QAAQ,GAAG,OAAO,CAAC,OAAO,KAAK,SAAS,OAAO,GAAG,OAAO;IAE9E,OAAO,kBAAkB,SAAS,SAAS,KAAK,IAC5C,CAAC,OAAO,QAAQ,SAAS,OAAO,GAAG,OAAO,IAC1C,CAAC,OAAO,KAAK,MAAM,YAAY,gBAAgB,CAAC,GAAG,OAAO;GAChE;GACA,IAAI,UAAU,MAAM,OAAO,IAAI,OAAO,iBACpC,OAAO,CAAC,OAAO,KAAK,MAAM,YAAY,eAAe,CAAC,GAAG,OAAO;GAClE,IAAI,QAAQ,OAAO,QAAQ,OAAO,WAChC,OAAO,CAAC,OAAO,KAAK,MAAM,YAAY,QAAQ,CAAC,GAAG,OAAO;GAE3D,MAAM,WAA0B;IAC9B,GAAG;IACH,QAAQ,QAAQ,WAAW;IAC3B,QAAQ;IACR,iBAAiB;IACjB,gBAAgB;GAClB;GAEA,MAAM,UAAU,OAAO,eAAe,UAAU,eAAe;GAE/D,IAAI,OAAO,UAAU,OAAO,GAAG,OAAO,CAAC,OAAO,KAAK,QAAQ,OAAO,GAAG,OAAO;GAC5E,MAAM,SAAS,IAAI,IAAI,QAAQ,MAAM;GAErC,OAAO,IAAI,SAAS,SAAS,QAAQ,OAAO;GAC5C,MAAM,aAAa,IAAI,IAAI,QAAQ,UAAU;GAE7C,WAAW,IAAI,SAAS,SAAS;IAC/B,iBAAiB;IACjB,qBAAqB,SAAS;GAChC,CAAC;GAED,OAAO,CACL,OAAO,QAAQ,QAAQ,GACvB;IAAE,GAAG;IAAS,UAAU,SAAS;IAAQ;IAAQ;GAAW,CAC9D;EACF,CACF,CACF,CAAC,CAAC,KAAK,OAAO,QAAQ,OAAO,UAAU,CAAC;EAExC,OAAO,UAAU,IAAI,2BAA2B;EAEhD,OAAO;CACT,CAAC;CAED,MAAM,QAA+C,OAAO,GAAG,+BAA+B,CAAC,CAC7F,WAAW,SAAS;EAClB,MAAM,QAAQ,OAAO,IAAI,IAAI,KAAK,EAAA,CAAG,OAAO,IAAI,OAAO;EAEvD,OAAO,SAAS,KAAA,IAAY,OAAO,OAAO,aAAa,eAAe,MAAM,cAAc;CAC5F,CACF;CAEA,MAAM,gBAA+D,OAAO,GAC1E,uCACF,CAAC,CAAC,WAAW,WAAW,OAAO,OAAO;EACpC,MAAM,SAAwB,CAAC;EAE/B,KAAK,MAAM,CAAC,SAAS,aAAa,OAAO,IAAI,IAAI,KAAK,EAAA,CAAG,YACvD,IACE,CAAC,QAAQ,mBACT,QAAQ,uBAAuB,aAC/B,qBAAqB,SAAS,KAAK,IAAI,GAEvC,OAAO,KAAK,OAAO;EAEvB,OAAO,KAAK,oBAAoB;EAEhC,OAAO,OAAO,MAAM,GAAG,KAAK;CAC9B,CAAC;CAED,MAAM,aAAyD,OAAO,GACpE,oCACF,CAAC,CAAC,WAAW,OAAO,OAAO;EACzB,MAAM,WAAW,OAAO,SAAS,eAAe,OAAO,kBAAkB;EAEzE,OAAO,iBAAiB,UAAU,sBAAsB;EACxD,MAAM,SAAS,OAAO,MAAM,SAAS,OAAO;EAE5C,IAAI,WAAW,QAAQ,CAAC,kBAAkB,QAAQ,QAAQ,GACxD,OAAO,OAAO,MAAM,WAAW,OAAO,cAAc,YAAY,OAAO;EACzE,MAAM,UAAU,OAAO,IAAI,IAAI,KAAK;EACpC,MAAM,UAAqC,CAAC;EAE5C,KAAK,MAAM,cAAc,QAAQ,eAAe,IAAI,uBAAuB,MAAM,CAAC,KAAK,CAAC,GAAG;GACzF,MAAM,UAAU,QAAQ,kBAAkB,IAAI,UAAU;GAExD,IAAI,YAAY,KAAA,GAAW,OAAO,OAAO,MAAM,WAAW,iBAAiB;GAC3E,IAAI,QAAQ,WAAW,OAAO,UAAU,QAAQ,UAAU,OAAO,QAAQ;GACzE,MAAM,OAAO,QAAQ,cAAc,IAAI,UAAU;GAEjD,IAAI,SAAS,KAAA,GAAW,OAAO,OAAO,MAAM,WAAW,kBAAkB;GACzE,QAAQ,KAAK,OAAO,aAAa,oBAAoB,MAAM,kBAAkB,CAAC;EAChF;EACA,QAAQ,MAAM,GAAG,MAAM,EAAE,UAAU,EAAE,OAAO;EAE5C,OAAO,QAAQ,MAAM,GAAG,KAAK;CAC/B,CAAC;CAED,MAAM,SAAiD,OAAO,GAC5D,gCACF,CAAC,CAAC,WAAW,YAAY,iBAAiB,QAAQ,UAAU,WAAW,aAAa;EAClF,MAAM,gBAAgB,OAAO,SAAS,eAAe,YAAY,cAAc;EAE/E,MAAM,aAAa,OAAO,SACxB,OAAO,MAAM,oBAAoB,GACjC,iBACA,mBACF;EAEA,MAAM,SAAS,OAAO,SAAS,oBAAoB,aAAa,eAAe;EAE/E,OAAO,iBAAiB,eAAe,kBAAkB;EACzD,OAAO,UAAU,IAAI,4BAA4B;EACjD,MAAM,qBAAqB,KAAK,IAAI,WAAW,OAAO,MAAM,iBAAiB;EAE7E,OAAO,OAAO,gBACZ,IAAI,OACF,QACC,YAAwF;GACvF,MAAM,YAAY,QAAQ,OAAO,IAAI,cAAc,OAAO;GAE1D,IAAI,cAAc,KAAA,GAAW,OAAO,CAAC,OAAO,KAAK,MAAM,aAAa,OAAO,CAAC,GAAG,OAAO;GACtF,MAAM,eAAe,OAAO,eAAe,WAAW,qBAAqB;GAE3E,IAAI,OAAO,UAAU,YAAY,GAAG,OAAO,CAAC,OAAO,KAAK,aAAa,OAAO,GAAG,OAAO;GACtF,MAAM,WAAW,aAAa;GAE9B,IACE,CAAC,kBAAkB,UAAU,aAAa,KAC1C,cAAc,WAAW,SAAS,QAElC,OAAO,CAAC,OAAO,KAAK,MAAM,YAAY,cAAc,CAAC,GAAG,OAAO;GACjE,IAAI,SAAS,iBACX,OAAO,CACL,YAAY,WAAW,SAAS,SAC5B,OAAO,OACP,OAAO,KAAK,MAAM,YAAY,kBAAkB,CAAC,GACrD,OACF;GACF,IAAI,CAAC,OAAO,cAAc,MAAM,KAAK,SAAS,SAAS,UAAU,SAAS,SAAS,QACjF,OAAO,CAAC,OAAO,KAAK,MAAM,cAAc,QAAQ,CAAC,GAAG,OAAO;GAE7D,MAAM,YAA8C,CAAC;GACrD,MAAM,UAA4C,CAAC;GACnD,MAAM,gBAAiE,CAAC;GACxE,MAAM,sBAAmE,CAAC;GAC1E,MAAM,SAAS,IAAI,IAAI,QAAQ,mBAAmB;GAElD,KAAK,MAAM,YAAY,YAAY;IACjC,MAAM,aAAa,QAAQ,cAAc,IACvC,sBAAsB,SAAS,IAAI,YAAY,CACjD;IAEA,IAAI,eAAe,KAAA,GACjB,OAAO,CAAC,OAAO,KAAK,MAAM,aAAa,cAAc,CAAC,GAAG,OAAO;IAClE,MAAM,SAAS,OAAO,oBAAoB,YAAY,qBAAqB;IAE3E,IAAI,OAAO,UAAU,MAAM,GAAG,OAAO,CAAC,OAAO,KAAK,OAAO,OAAO,GAAG,OAAO;IAC1E,IACE,CAAC,kBAAkB,UAAU,OAAO,SAAS,QAAQ,KACrD,CAAC,8BAA8B,UAAU,OAAO,SAAS,QAAQ,KACjE,OAAO,QAAQ,WAAW,SAAS,UACnC,OAAO,QAAQ,UAAU,QAEzB,OAAO,CAAC,OAAO,KAAK,MAAM,YAAY,WAAW,CAAC,GAAG,OAAO;IAC9D,IAAI,CAAC,sBAAsB,OAAO,SAAS,UAAU,oBAAoB,KAAK,GAC5E;IACF,MAAM,cAAc,8BAA8B,SAAS,GAAG;IAC9D,MAAM,eAAe,QAAQ,WAAW,IAAI,WAAW;IAEvD,IAAI,iBAAiB,KAAA,GAAW;KAC9B,MAAM,WAAW,OAAO,sBAAsB,cAAc,iBAAiB;KAE7E,IAAI,OAAO,UAAU,QAAQ,GAAG,OAAO,CAAC,OAAO,KAAK,SAAS,OAAO,GAAG,OAAO;KAC9E,IAAI,CAAC,qBAAqB,SAAS,SAAS,QAAQ,GAClD,OAAO,CAAC,OAAO,KAAK,MAAM,YAAY,mBAAmB,CAAC,GAAG,OAAO;KACtE;IACF;IAEA,MAAM,kBAAkB,OACtB,sBACA,UACA,wBACF;IAEA,IAAI,OAAO,UAAU,eAAe,GAClC,OAAO,CAAC,OAAO,KAAK,gBAAgB,OAAO,GAAG,OAAO;IACvD,UAAU,KAAK,CAAC,aAAa,gBAAgB,OAAO,CAAC;IACrD,cAAc,KAAK;KACjB;KACA;MACE,KAAK,SAAS;MACd,OAAO,SAAS;MAChB,qBAAqB,SAAS,MAAM;KACtC;KACA,OAAO,QAAQ,IAAI;IACrB,CAAC;IACD,MAAM,UAAU,OAAO,QAAQ,IAAI;IAEnC,OAAO,IAAI,UAAU,OAAO,IAAI,OAAO,KAAK,KAAK,CAAC;IAClD,KAAK,OAAO,IAAI,OAAO,KAAK,KAAK,OAAO,uBACtC,OAAO,CAAC,OAAO,KAAK,MAAM,YAAY,kBAAkB,CAAC,GAAG,OAAO;IACrE,IAAI,OAAO,QAAQ,cAAc,SAAS,QAAQ;KAChD,MAAM,WAAW;MAAE,GAAG,OAAO;MAAS,OAAO;MAAqB,UAAU;KAAK;KAEjF,MAAM,gBAAgB,OACpB,oBACA,UACA,4BACF;KAEA,IAAI,OAAO,UAAU,aAAa,GAChC,OAAO,CAAC,OAAO,KAAK,cAAc,OAAO,GAAG,OAAO;KACrD,MAAM,cAAc,sBAAsB,SAAS,GAAG;KAEtD,QAAQ,KAAK,CAAC,aAAa,cAAc,OAAO,CAAC;KACjD,MAAM,UAAU,QAAQ,kBAAkB,IAAI,WAAW;KAEzD,IAAI,YAAY,KAAA,GACd,OAAO,CAAC,OAAO,KAAK,MAAM,WAAW,iBAAiB,CAAC,GAAG,OAAO;KACnE,oBAAoB,KAAK,CACvB,aACA;MAAE,GAAG;MAAS,OAAO;MAAY,YAAY;KAAK,CACpD,CAAC;IACH;GACF;GACA,IAAI,QAAQ,WAAW,OAAO,UAAU,SAAS,OAAO,eACtD,OAAO,CAAC,OAAO,KAAK,MAAM,YAAY,YAAY,CAAC,GAAG,OAAO;GAC/D,MAAM,gBAAgB,IAAI,IAAI,QAAQ,aAAa;GAEnD,KAAK,MAAM,CAAC,KAAK,UAAU,SAAS,cAAc,IAAI,KAAK,KAAK;GAChE,MAAM,iBAAiB,IAAI,IAAI,QAAQ,UAAU;GAEjD,KAAK,MAAM,CAAC,KAAK,UAAU,WAAW,eAAe,IAAI,KAAK,KAAK;GACnE,MAAM,gBAAgB,IAAI,IAAI,QAAQ,aAAa;GAEnD,KAAK,MAAM,CAAC,KAAK,UAAU,eAAe,cAAc,IAAI,KAAK,KAAK;GACtE,MAAM,oBAAoB,IAAI,IAAI,QAAQ,iBAAiB;GAE3D,KAAK,MAAM,CAAC,KAAK,UAAU,qBAAqB,kBAAkB,IAAI,KAAK,KAAK;GAEhF,MAAM,YAA2B;IAC/B,GAAG;IACH;IACA,iBAAiB;IACjB,gBAAgB;GAClB;GAEA,MAAM,eAAe,OAAO,eAAe,WAAW,qBAAqB;GAE3E,IAAI,OAAO,UAAU,YAAY,GAAG,OAAO,CAAC,OAAO,KAAK,aAAa,OAAO,GAAG,OAAO;GACtF,MAAM,SAAS,IAAI,IAAI,QAAQ,MAAM;GAErC,OAAO,IAAI,UAAU,SAAS,aAAa,OAAO;GAClD,MAAM,aAAa,IAAI,IAAI,QAAQ,UAAU;GAE7C,WAAW,IAAI,UAAU,SAAS;IAChC,iBAAiB,UAAU;IAC3B,qBAAqB,UAAU;GACjC,CAAC;GAED,OAAO,CACL,OAAO,MACP;IACE,GAAG;IACH;IACA;IACA;IACA;IACA,YAAY;IACZ;IACA,qBAAqB;GACvB,CACF;EACF,CACF,CACF,CAAC,CAAC,KAAK,OAAO,QAAQ,OAAO,UAAU,CAAC;EACxC,OAAO,UAAU,IAAI,2BAA2B;CAClD,CAAC;CAED,MAAM,UAAmD,OAAO,GAC9D,iCACF,CAAC,CAAC,WAAW,YAAY,eAAe,WAAW,aAAa;EAC9D,MAAM,gBAAgB,OAAO,SAAS,eAAe,YAAY,gBAAgB;EACjF,MAAM,WAAW,OAAO,SAAS,sBAAsB,eAAe,mBAAmB;EACzF,MAAM,SAAS,OAAO,SAAS,oBAAoB,aAAa,iBAAiB;EAEjF,OAAO,iBAAiB,eAAe,oBAAoB;EAC3D,OAAO,UAAU,IAAI,8BAA8B;EACnD,MAAM,qBAAqB,KAAK,IAAI,WAAW,OAAO,MAAM,iBAAiB;EAE7E,OAAO,OAAO,gBACZ,IAAI,OACF,QACC,YAAwF;GACvF,MAAM,YAAY,QAAQ,OAAO,IAAI,cAAc,OAAO;GAE1D,MAAM,aAAa,QAAQ,cAAc,IACvC,sBAAsB,SAAS,IAAI,YAAY,CACjD;GAEA,IAAI,cAAc,KAAA,KAAa,eAAe,KAAA,GAC5C,OAAO,CACL,OAAO,KAAK,MAAM,aAAa,cAAc,KAAA,IAAY,UAAU,cAAc,CAAC,GAClF,OACF;GACF,MAAM,WAAW,OAAO,eAAe,WAAW,uBAAuB;GAEzE,IAAI,OAAO,UAAU,QAAQ,GAAG,OAAO,CAAC,OAAO,KAAK,SAAS,OAAO,GAAG,OAAO;GAC9E,MAAM,SAAS,OAAO,oBAAoB,YAAY,uBAAuB;GAE7E,IAAI,OAAO,UAAU,MAAM,GAAG,OAAO,CAAC,OAAO,KAAK,OAAO,OAAO,GAAG,OAAO;GAC1E,IACE,CAAC,kBAAkB,SAAS,SAAS,aAAa,KAClD,CAAC,kBAAkB,UAAU,OAAO,SAAS,SAAS,OAAO,KAC7D,CAAC,8BAA8B,UAAU,OAAO,SAAS,SAAS,OAAO,KACzE,OAAO,QAAQ,cAAc,SAAS,QAEtC,OAAO,CAAC,OAAO,KAAK,MAAM,YAAY,mBAAmB,CAAC,GAAG,OAAO;GACtE,MAAM,MAAM,8BAA8B,SAAS,GAAG;GACtD,MAAM,eAAe,QAAQ,WAAW,IAAI,GAAG;GAE/C,IAAI,iBAAiB,KAAA,GAAW;IAC9B,MAAM,WAAW,OAAO,sBAAsB,cAAc,mBAAmB;IAE/E,IAAI,OAAO,UAAU,QAAQ,GAAG,OAAO,CAAC,OAAO,KAAK,SAAS,OAAO,GAAG,OAAO;IAE9E,OAAO,qBAAqB,SAAS,SAAS,QAAQ,IAClD,CAAC,OAAO,MAAM,OAAO,IACrB,CAAC,OAAO,KAAK,MAAM,YAAY,mBAAmB,CAAC,GAAG,OAAO;GACnE;GACA,IAAI,CAAC,sBAAsB,OAAO,SAAS,SAAS,SAAS,oBAAoB,IAAI,GACnF,OAAO,CAAC,OAAO,KAAK,MAAM,YAAY,sBAAsB,CAAC,GAAG,OAAO;GACzE,IAAI,QAAQ,WAAW,QAAQ,OAAO,eACpC,OAAO,CAAC,OAAO,KAAK,MAAM,YAAY,YAAY,CAAC,GAAG,OAAO;GAC/D,MAAM,aAAa,QAAQ,oBAAoB,IAAI,OAAO,QAAQ,IAAI,OAAO,KAAK;GAElF,IAAI,cAAc,OAAO,uBACvB,OAAO,CAAC,OAAO,KAAK,MAAM,YAAY,kBAAkB,CAAC,GAAG,OAAO;GAErE,MAAM,kBAAkB,OACtB,sBACA,UACA,0BACF;GAEA,IAAI,OAAO,UAAU,eAAe,GAClC,OAAO,CAAC,OAAO,KAAK,gBAAgB,OAAO,GAAG,OAAO;GACvD,MAAM,WAAW;IAAE,GAAG,OAAO;IAAS,OAAO;IAAqB,UAAU;GAAK;GAEjF,MAAM,gBAAgB,OACpB,oBACA,UACA,8BACF;GAEA,IAAI,OAAO,UAAU,aAAa,GAAG,OAAO,CAAC,OAAO,KAAK,cAAc,OAAO,GAAG,OAAO;GACxF,MAAM,aAAa,IAAI,IAAI,QAAQ,UAAU;GAE7C,WAAW,IAAI,KAAK,gBAAgB,OAAO;GAC3C,MAAM,gBAAgB,IAAI,IAAI,QAAQ,aAAa;GACnD,MAAM,cAAc,sBAAsB,SAAS,GAAG;GAEtD,cAAc,IAAI,aAAa,cAAc,OAAO;GACpD,MAAM,oBAAoB,IAAI,IAAI,QAAQ,iBAAiB;GAC3D,MAAM,UAAU,kBAAkB,IAAI,WAAW;GAEjD,IAAI,YAAY,KAAA,GACd,OAAO,CAAC,OAAO,KAAK,MAAM,WAAW,gBAAgB,CAAC,GAAG,OAAO;GAClE,kBAAkB,IAAI,aAAa;IAAE,GAAG;IAAS,OAAO;IAAY,YAAY;GAAK,CAAC;GACtF,MAAM,gBAAgB,IAAI,IAAI,QAAQ,aAAa;GAEnD,cAAc,IAAI,KAAK;IACrB,KAAK,SAAS;IACd,OAAO,SAAS;IAChB,qBAAqB,SAAS,MAAM;GACtC,CAAC;GACD,MAAM,sBAAsB,IAAI,IAAI,QAAQ,mBAAmB;GAE/D,oBAAoB,IAAI,SAAS,IAAI,SAAS,aAAa,CAAC;GAE5D,OAAO,CACL,OAAO,MACP;IACE,GAAG;IACH;IACA;IACA;IACA;IACA;GACF,CACF;EACF,CACF,CACF,CAAC,CAAC,KAAK,OAAO,QAAQ,OAAO,UAAU,CAAC;EACxC,OAAO,UAAU,IAAI,6BAA6B;CACpD,CAAC;CAED,MAAM,aAAyD,OAAO,GACpE,oCACF,CAAC,CAAC,WAAW,SAAS,qBAAqB,MAAM;EAC/C,MAAM,iBACJ,SAAS,KAAA,IACL,mBACA,OAAO,SAAS,kBAAkB,MAAM,iBAAiB;EAE/D,OAAO,UAAU,IAAI,iCAAiC;EACtD,OAAO,OAAO,gBACZ,IAAI,OACF,QACC,YAAwF;GACvF,MAAM,OAAO,QAAQ,OAAO,IAAI,OAAO;GAEvC,IAAI,SAAS,KAAA,GAAW,OAAO,CAAC,OAAO,KAAK,MAAM,aAAa,OAAO,CAAC,GAAG,OAAO;GACjF,MAAM,WAAW,OAAO,eAAe,MAAM,oBAAoB;GAEjE,IAAI,OAAO,UAAU,QAAQ,GAAG,OAAO,CAAC,OAAO,KAAK,SAAS,OAAO,GAAG,OAAO;GAC9E,MAAM,UAAU;IAAE,GAAG,SAAS;IAAS;IAAqB;GAAe;GAC3E,MAAM,UAAU,OAAO,eAAe,SAAS,oBAAoB;GAEnE,IAAI,OAAO,UAAU,OAAO,GAAG,OAAO,CAAC,OAAO,KAAK,QAAQ,OAAO,GAAG,OAAO;GAC5E,MAAM,SAAS,IAAI,IAAI,QAAQ,MAAM;GAErC,OAAO,IAAI,SAAS,QAAQ,OAAO;GACnC,MAAM,aAAa,IAAI,IAAI,QAAQ,UAAU;GAC7C,MAAM,UAAU,WAAW,IAAI,OAAO;GAEtC,IAAI,YAAY,KAAA,GACd,OAAO,CAAC,OAAO,KAAK,MAAM,WAAW,mBAAmB,CAAC,GAAG,OAAO;GACrE,WAAW,IAAI,SAAS;IAAE,GAAG;IAAS;GAAoB,CAAC;GAE3D,OAAO,CAAC,OAAO,MAAM;IAAE,GAAG;IAAS;IAAQ;GAAW,CAAC;EACzD,CACF,CACF,CAAC,CAAC,KAAK,OAAO,QAAQ,OAAO,UAAU,CAAC;EACxC,OAAO,UAAU,IAAI,gCAAgC;CACvD,CAAC;CAED,MAAM,WAAqD,OAAO,GAChE,kCACF,CAAC,CAAC,WAAW,OAAO;EAClB,MAAM,MAAM,OAAO,SAAS,yBAAyB,OAAO,cAAc;EAE1E,OAAO,iBAAiB,IAAI,cAAc,oBAAoB;EAC9D,MAAM,QAAQ,OAAO,IAAI,IAAI,KAAK,EAAA,CAAG,WAAW,IAAI,8BAA8B,GAAG,CAAC;EAEtF,OAAO,SAAS,KAAA,IACZ,OACA,OAAO,aAAa,sBAAsB,MAAM,iBAAiB;CACvE,CAAC;CAED,MAAM,oBAAuE,OAAO,GAClF,2CACF,CAAC,CAAC,WAAW,WAAW,OAAO,OAAO;EACpC,MAAM,QAAwC,CAAC;EAE/C,KAAK,MAAM,CAAC,YAAY,UAAU,OAAO,IAAI,IAAI,KAAK,EAAA,CAAG,eACvD,IACE,KAAK,UAAU,eACf,KAAK,UAAU,aACf,KAAK,uBAAuB,aAC5B,qBAAqB,YAAY,KAAK,IAAI,GAE1C,MAAM,KAAK,KAAK,GAAG;EAEvB,MAAM,MAAM,GAAG,MACb,qBAAqB,8BAA8B,CAAC,GAAG,8BAA8B,CAAC,CAAC,CACzF;EAEA,OAAO,MAAM,MAAM,GAAG,KAAK;CAC7B,CAAC;CAED,MAAM,iBAAiE,OAAO,GAC5E,wCACF,CAAC,CAAC,WAAW,OAAO,OAAO,OAAO;EAChC,MAAM,MAAM,OAAO,WAAW,OAAO,qBAAqB;EAC1D,MAAM,QAAqC,CAAC;EAE5C,KAAK,MAAM,SAAS,OAAO,IAAI,IAAI,KAAK,EAAA,CAAG,WAAW,OAAO,GAAG;GAC9D,MAAM,OAAO,OAAO,aAAa,sBAAsB,MAAM,eAAe;GAC5E,MAAM,UAAU,8BAA8B,KAAK,GAAG;GAEtD,IACE,sBAAsB,KAAK,IAAI,YAAY,MAAM,sBAAsB,GAAG,KAC1E,qBAAqB,SAAS,KAAK,IAAI,GAEvC,MAAM,KAAK,IAAI;EACnB;EACA,MAAM,MAAM,GAAG,MACb,qBACE,8BAA8B,EAAE,GAAG,GACnC,8BAA8B,EAAE,GAAG,CACrC,CACF;EAEA,OAAO,MAAM,MAAM,GAAG,KAAK;CAC7B,CAAC;CAED,MAAM,iBAAiE,OAAO,GAC5E,wCACF,CAAC,CAAC,WAAW,UAAU,iBAAiB,aAAa;EACnD,MAAM,MAAM,OAAO,SAAS,yBAAyB,UAAU,qBAAqB;EACpF,MAAM,aAAa,OAAO,SAAS,QAAQ,iBAAiB,oBAAoB;EAChF,MAAM,SAAS,OAAO,SAAS,gBAAgB,aAAa,wBAAwB;EAEpF,OAAO,iBAAiB,IAAI,cAAc,2BAA2B;EACrE,OAAO,UAAU,IAAI,yBAAyB,OAAO,KAAK,YAAY,EAAE,QAAQ;EAEhF,MAAM,kBACJ,OAAO,SAAS,YACZ;GAAE,GAAG;GAAQ,WAAW,KAAK,IAAI,OAAO,WAAW,OAAO,MAAM,iBAAiB;EAAE,IACnF;EAEN,MAAM,SAAS,OAAO,OAAO,gBAC3B,IAAI,OACF,QAEE,YAIG;GACH,MAAM,aAAa,8BAA8B,GAAG;GACpD,MAAM,OAAO,QAAQ,WAAW,IAAI,UAAU;GAE9C,IAAI,SAAS,KAAA,GAAW,OAAO,CAAC,OAAO,KAAK,MAAM,aAAa,UAAU,CAAC,GAAG,OAAO;GACpF,MAAM,UAAU,OAAO,sBAAsB,MAAM,wBAAwB;GAE3E,IAAI,OAAO,UAAU,OAAO,GAAG,OAAO,CAAC,SAAS,OAAO;GAEvD,MAAM,mBAAmB,QAAQ,cAAc,IAC7C,sBAAsB,IAAI,YAAY,CACxC;GAEA,IAAI,qBAAqB,KAAA,GACvB,OAAO,CAAC,OAAO,KAAK,MAAM,WAAW,uBAAuB,CAAC,GAAG,OAAO;GAEzE,MAAM,eAAe,OACnB,oBACA,kBACA,uBACF;GAEA,IAAI,OAAO,UAAU,YAAY,GAAG,OAAO,CAAC,OAAO,KAAK,aAAa,OAAO,GAAG,OAAO;GAEtF,MAAM,aAAa,gCACjB,QAAQ,SACR,aAAa,SACb,YACA,eACF;GAEA,IAAI,OAAO,UAAU,UAAU,GAAG,OAAO,CAAC,OAAO,KAAK,WAAW,OAAO,GAAG,OAAO;GAClF,IAAI,WAAW,YAAY,QAAQ,SACjC,OAAO,CAAC,OAAO,QAAQ,QAAQ,OAAO,GAAG,OAAO;GAClD,MAAM,UAAU,WAAW;GAC3B,MAAM,UAAU,OAAO,sBAAsB,SAAS,wBAAwB;GAE9E,IAAI,OAAO,UAAU,OAAO,GAAG,OAAO,CAAC,OAAO,KAAK,QAAQ,OAAO,GAAG,OAAO;GAC5E,MAAM,aAAa,IAAI,IAAI,QAAQ,UAAU;GAE7C,WAAW,IAAI,YAAY,QAAQ,OAAO;GAC1C,MAAM,gBAAgB,IAAI,IAAI,QAAQ,aAAa;GACnD,MAAM,UAAU,cAAc,IAAI,UAAU;GAE5C,IAAI,YAAY,KAAA,GACd,OAAO,CAAC,OAAO,KAAK,MAAM,WAAW,gBAAgB,CAAC,GAAG,OAAO;GAClE,cAAc,IAAI,YAAY;IAC5B,GAAG;IACH,OAAO,QAAQ;IACf,qBAAqB,QAAQ,MAAM;GACrC,CAAC;GAED,OAAO,CAAC,OAAO,QAAQ,OAAO,GAAG;IAAE,GAAG;IAAS;IAAY;GAAc,CAAC;EAC5E,CACF,CACF,CAAC,CAAC,KAAK,OAAO,QAAQ,OAAO,UAAU,CAAC;EAExC,OAAO,UAAU,IAAI,yBAAyB,OAAO,KAAK,YAAY,EAAE,OAAO;EAE/E,OAAO;CACT,CAAC;CAED,MAAM,aAAyD,OAAO,GACpE,oCACF,CAAC,CAAC,WAAW,WAAW,OAAO,OAAO;EACpC,MAAM,UAA8E,CAAC;EAErF,KAAK,MAAM,SAAS,OAAO,IAAI,IAAI,KAAK,EAAA,CAAG,kBAAkB,OAAO,GAClE,IACE,KAAK,UAAU,SACf,KAAK,UAAU,YACf,KAAK,eAAe,QACpB,KAAK,cAAc,WAEnB,QAAQ,KAAK;GAAE,KAAK,KAAK;GAAK,SAAS,KAAK;EAAQ,CAAC;EAEzD,QAAQ,MAAM,GAAG,MAAM,EAAE,UAAU,EAAE,OAAO;EAE5C,OAAO,QAAQ,MAAM,GAAG,KAAK;CAC/B,CAAC;CAED,MAAM,gBAA+D,OAAO,GAC1E,uCACF,CAAC,CAAC,WAAW,OAAO,UAAU;EAC5B,MAAM,MAAM,OAAO,WAAW,OAAO,oBAAoB;EAEzD,OAAO,UAAU,IAAI,oCAAoC;EACzD,OAAO,OAAO,gBACZ,IAAI,OACF,QACC,YAAwF;GACvF,MAAM,aAAa,sBAAsB,GAAG;GAC5C,MAAM,OAAO,QAAQ,cAAc,IAAI,UAAU;GAEjD,IAAI,SAAS,KAAA,GAAW,OAAO,CAAC,OAAO,KAAK,MAAM,aAAa,cAAc,CAAC,GAAG,OAAO;GACxF,MAAM,SAAS,OAAO,oBAAoB,MAAM,uBAAuB;GAEvE,IAAI,OAAO,UAAU,MAAM,GAAG,OAAO,CAAC,OAAO,KAAK,OAAO,OAAO,GAAG,OAAO;GAE1E,MAAM,UAAU;IACd,GAAG,OAAO;IACV,UAAU,OAAO,QAAQ,UAAU,WAAW,WAAW;GAC3D;GAEA,MAAM,UAAU,OAAO,oBAAoB,SAAS,uBAAuB;GAE3E,IAAI,OAAO,UAAU,OAAO,GAAG,OAAO,CAAC,OAAO,KAAK,QAAQ,OAAO,GAAG,OAAO;GAC5E,MAAM,gBAAgB,IAAI,IAAI,QAAQ,aAAa;GAEnD,cAAc,IAAI,YAAY,QAAQ,OAAO;GAC7C,MAAM,oBAAoB,IAAI,IAAI,QAAQ,iBAAiB;GAC3D,MAAM,UAAU,kBAAkB,IAAI,UAAU;GAEhD,IAAI,YAAY,KAAA,GACd,OAAO,CAAC,OAAO,KAAK,MAAM,WAAW,gBAAgB,CAAC,GAAG,OAAO;GAClE,kBAAkB,IAAI,YAAY;IAChC,GAAG;IACH,YAAY,QAAQ,UAAU,uBAAuB;GACvD,CAAC;GAED,OAAO,CAAC,OAAO,MAAM;IAAE,GAAG;IAAS;IAAe;GAAkB,CAAC;EACvE,CACF,CACF,CAAC,CAAC,KAAK,OAAO,QAAQ,OAAO,UAAU,CAAC;EACxC,OAAO,UAAU,IAAI,mCAAmC;CAC1D,CAAC;CAED,MAAM,kBAAmE,IAAI,IAAI,KAAK,CAAC,CAAC,KACtF,OAAO,KAAK,YAAY,QAAQ,WAAW,CAC7C;CAEA,MAAM,qBAAyE,OAAO,GACpF,4CACF,CAAC,CAAC,WAAW,OAAO;EAClB,MAAM,UAAU,OAAO,SAAS,yBAAyB,OAAO,cAAc;EAE9E,OAAO,UAAU,IAAI,0CAA0C;EAC/D,OAAO,OAAO,gBACZ,IAAI,OAAO,QAAQ,aAAa;GAAE,GAAG;GAAS,aAAa;EAAQ,EAAE,CACvE;EACA,OAAO,UAAU,IAAI,yCAAyC;CAChE,CAAC;CAED,MAAM,eAAe,OAAO,IAAI,aAAa;EAC3C,IAAI,WAA0B;EAC9B,MAAM,UAAU,OAAO,IAAI,IAAI,KAAK;EAEpC,IACE,QAAQ,YAAY,WAAW,MAC/B,QAAQ,YAAY,eAAe,MACnC,QAAQ,YAAY,aAAa,GAEjC,OAAO;EAET,MAAM,YAAY,UAAkB;GAClC,IAAI,aAAa,QAAQ,QAAQ,UAAU,WAAW;EACxD;EAEA,KAAK,MAAM,YAAY,QAAQ,WAAW,OAAO,GAC/C,IAAI,CAAC,SAAS,iBAAiB,SAAS,SAAS,mBAAmB;EACtE,KAAK,MAAM,QAAQ,QAAQ,cAAc,OAAO,GAC9C,IAAI,KAAK,UAAU,eAAe,KAAK,UAAU,WAC/C,SAAS,KAAK,mBAAmB;EACrC,KAAK,MAAM,UAAU,QAAQ,kBAAkB,OAAO,GACpD,IAAI,OAAO,UAAU,YAAY,OAAO,eAAe,MAAM,SAAS,OAAO,UAAU;EAEzF,OAAO;CACT,CAAC,CAAC,CAAC,KAAK,OAAO,SAAS,sCAAsC,CAAC;CAE/D,OAAO,kBAAkB,GAAG;EAC1B;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;AACH,CAAC;AAED,MAAa,gCACX,cAEA,MAAM,OAAO,mBAAmB,4BAA4B,SAAS,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { Crypto, Layer } from "effect";
2
+ import { ThreadStore } from "@effect-agent/thread/ThreadStore";
3
+ declare namespace MemoryThreadStore_d_exports {
4
+ export { MemoryThreadStoreLive };
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
+ //#endregion
12
+ export { MemoryThreadStoreLive, MemoryThreadStore_d_exports as t };
13
+ //# sourceMappingURL=MemoryThreadStore.d.mts.map
@@ -0,0 +1,311 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
+ import { 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, SaveCheckpointRequest, 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({ MemoryThreadStoreLive: () => MemoryThreadStoreLive });
9
+ const MAX_THREADS = 256;
10
+ const MAX_RECORDS_PER_THREAD = 65536;
11
+ const MAX_CHECKPOINTS_PER_THREAD = 1024;
12
+ const storeError = (operation, message, cause) => cause === void 0 ? ThreadStoreError.make({
13
+ operation,
14
+ message
15
+ }) : ThreadStoreError.make({
16
+ operation,
17
+ message,
18
+ cause
19
+ });
20
+ 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))));
21
+ const decodeCanonicalSequence = Schema.decodeSync(CanonicalSequence);
22
+ const ZERO_CANONICAL_SEQUENCE = decodeCanonicalSequence(0);
23
+ const offsetSequence = Effect.fn("MemoryThreadStore.offsetSequence")((threadId, offset) => {
24
+ if (offset === void 0) return Effect.succeed(ZERO_CANONICAL_SEQUENCE);
25
+ const prefix = `memory:v1:${Encoding.encodeBase64(threadId)}:`;
26
+ const encodedSequence = offset.startsWith(prefix) ? offset.slice(prefix.length) : "";
27
+ if (!/^\d+$/.test(encodedSequence)) return Effect.fail(storeError("observe", "Malformed observation offset"));
28
+ const sequence = Number(encodedSequence);
29
+ return Number.isSafeInteger(sequence) ? Schema.decodeUnknownEffect(CanonicalSequence)(sequence).pipe(Effect.mapError(() => storeError("observe", "Malformed observation offset"))) : Effect.fail(storeError("observe", "Malformed observation offset"));
30
+ });
31
+ const observationOffset = (threadId, sequence) => Schema.decodeSync(ObservationOffset)(`memory:v1:${Encoding.encodeBase64(threadId)}:${sequence}`);
32
+ const findThread = Effect.fn("MemoryThreadStore.findThread")((state, threadId) => {
33
+ const thread = state.threads.get(threadId);
34
+ return thread === void 0 ? Effect.fail(ThreadNotMaterialized.make({ threadId })) : Effect.succeed(thread);
35
+ });
36
+ const CheckpointVersionEnvelope = Schema.Struct({ checkpoint: Schema.Struct({
37
+ threadId: ThreadId,
38
+ schemaVersion: Schema.Natural
39
+ }) });
40
+ const validateCheckpointVersion = Effect.fn("MemoryThreadStore.validateCheckpointVersion")(function* (value) {
41
+ const envelope = yield* Schema.decodeUnknownEffect(CheckpointVersionEnvelope)(value).pipe(Effect.mapError(() => storeError("saveCheckpoint", "Invalid saveCheckpoint request")));
42
+ if (envelope.checkpoint.schemaVersion !== 1) return yield* CheckpointRejected.make({
43
+ threadId: envelope.checkpoint.threadId,
44
+ reason: "unsupported-version"
45
+ });
46
+ });
47
+ const makeThreadStore = Effect.gen(function* () {
48
+ const crypto = yield* Crypto.Crypto;
49
+ const state = yield* Ref.make({ threads: /* @__PURE__ */ new Map() });
50
+ const updates = yield* PubSub.sliding(1);
51
+ yield* Effect.addFinalizer(() => PubSub.shutdown(updates));
52
+ const materialize = Effect.fn("MemoryThreadStore.materialize")((unvalidated) => Effect.gen(function* () {
53
+ const request = yield* validate(ThreadMaterialization, "materialize", unvalidated);
54
+ const decision = yield* Ref.modify(state, (current) => {
55
+ const existing = current.threads.get(request.threadId);
56
+ if (existing !== void 0) {
57
+ if (request.producerEpoch < existing.producerEpoch) return [{
58
+ _tag: "failure",
59
+ error: FenceRejected.make({
60
+ threadId: request.threadId,
61
+ actualEpoch: existing.producerEpoch,
62
+ attemptedEpoch: request.producerEpoch
63
+ })
64
+ }, current];
65
+ if (request.producerEpoch === existing.producerEpoch) return [{ _tag: "success" }, current];
66
+ const threads = new Map(current.threads);
67
+ threads.set(request.threadId, {
68
+ ...existing,
69
+ producerEpoch: request.producerEpoch
70
+ });
71
+ return [{ _tag: "success" }, { threads }];
72
+ }
73
+ if (current.threads.size >= MAX_THREADS) return [{
74
+ _tag: "failure",
75
+ error: storeError("materialize", `In-memory thread limit ${MAX_THREADS} exceeded`)
76
+ }, current];
77
+ const threads = new Map(current.threads);
78
+ threads.set(request.threadId, {
79
+ producerEpoch: request.producerEpoch,
80
+ tailSequence: ZERO_CANONICAL_SEQUENCE,
81
+ tailDigest: EMPTY_TAIL_DIGEST,
82
+ records: [],
83
+ recordIds: /* @__PURE__ */ new Set(),
84
+ batches: /* @__PURE__ */ new Map(),
85
+ tailDigests: /* @__PURE__ */ new Map([[ZERO_CANONICAL_SEQUENCE, EMPTY_TAIL_DIGEST]]),
86
+ checkpoints: /* @__PURE__ */ new Map()
87
+ });
88
+ return [{ _tag: "success" }, { threads }];
89
+ });
90
+ if (decision._tag === "failure") return yield* decision.error;
91
+ }));
92
+ const append = Effect.fn("MemoryThreadStore.append")((unvalidated) => Effect.gen(function* () {
93
+ const request = yield* validate(FencedAppendRequest, "append", unvalidated);
94
+ const digest = yield* digestCanonicalBatch(request.expectedTailDigest, request.batch).pipe(Effect.provideService(Crypto.Crypto, crypto), Effect.mapError((error) => storeError("append", error.message, error)));
95
+ const decision = yield* Effect.uninterruptible(Ref.modify(state, (current) => {
96
+ const thread = current.threads.get(request.threadId);
97
+ if (thread === void 0) return [{
98
+ _tag: "failure",
99
+ error: ThreadNotMaterialized.make({ threadId: request.threadId })
100
+ }, current];
101
+ if (request.producerEpoch !== thread.producerEpoch) return [{
102
+ _tag: "failure",
103
+ error: FenceRejected.make({
104
+ threadId: request.threadId,
105
+ actualEpoch: thread.producerEpoch,
106
+ attemptedEpoch: request.producerEpoch
107
+ })
108
+ }, current];
109
+ const previous = thread.batches.get(request.batch.batchId);
110
+ if (previous !== void 0) {
111
+ if (previous.digest !== digest) return [{
112
+ _tag: "failure",
113
+ error: AppendConflict.make({
114
+ threadId: request.threadId,
115
+ batchId: request.batch.batchId,
116
+ reason: "batch-digest"
117
+ })
118
+ }, current];
119
+ return [{
120
+ _tag: "success",
121
+ result: AppendResult.make({
122
+ firstSequence: previous.result.firstSequence,
123
+ lastSequence: previous.result.lastSequence,
124
+ tailDigest: previous.result.tailDigest,
125
+ replayed: true
126
+ }),
127
+ records: []
128
+ }, current];
129
+ }
130
+ if (request.expectedTailSequence !== thread.tailSequence || request.expectedTailDigest !== thread.tailDigest) return [{
131
+ _tag: "failure",
132
+ error: AppendConflict.make({
133
+ threadId: request.threadId,
134
+ batchId: request.batch.batchId,
135
+ reason: "tail",
136
+ actualTailSequence: thread.tailSequence,
137
+ actualTailDigest: thread.tailDigest
138
+ })
139
+ }, current];
140
+ if (thread.records.length + request.batch.records.length > MAX_RECORDS_PER_THREAD) return [{
141
+ _tag: "failure",
142
+ error: storeError("append", `In-memory record limit ${MAX_RECORDS_PER_THREAD} exceeded`)
143
+ }, current];
144
+ const batchRecordIds = /* @__PURE__ */ new Set();
145
+ for (const record of request.batch.records) {
146
+ if (thread.recordIds.has(record.recordId) || batchRecordIds.has(record.recordId)) return [{
147
+ _tag: "failure",
148
+ error: AppendConflict.make({
149
+ threadId: request.threadId,
150
+ batchId: request.batch.batchId,
151
+ reason: "record-identity"
152
+ })
153
+ }, current];
154
+ batchRecordIds.add(record.recordId);
155
+ }
156
+ const records = request.batch.records.map((record, index) => {
157
+ const sequence = decodeCanonicalSequence(thread.tailSequence + index + 1);
158
+ return CanonicalRecordEnvelope.make({
159
+ threadId: request.threadId,
160
+ batchId: request.batch.batchId,
161
+ sequence,
162
+ offset: observationOffset(request.threadId, sequence),
163
+ record
164
+ });
165
+ });
166
+ const lastSequence = decodeCanonicalSequence(thread.tailSequence + records.length);
167
+ const result = AppendResult.make({
168
+ firstSequence: decodeCanonicalSequence(thread.tailSequence + 1),
169
+ lastSequence,
170
+ tailDigest: digest,
171
+ replayed: false
172
+ });
173
+ const batches = new Map(thread.batches);
174
+ batches.set(request.batch.batchId, {
175
+ digest,
176
+ result
177
+ });
178
+ const recordIds = new Set(thread.recordIds);
179
+ for (const recordId of batchRecordIds) recordIds.add(recordId);
180
+ const tailDigests = new Map(thread.tailDigests);
181
+ tailDigests.set(lastSequence, digest);
182
+ const threads = new Map(current.threads);
183
+ threads.set(request.threadId, {
184
+ ...thread,
185
+ tailSequence: lastSequence,
186
+ tailDigest: digest,
187
+ records: [...thread.records, ...records],
188
+ recordIds,
189
+ batches,
190
+ tailDigests
191
+ });
192
+ return [{
193
+ _tag: "success",
194
+ result,
195
+ records
196
+ }, { threads }];
197
+ }).pipe(Effect.tap((decision) => decision._tag === "success" && decision.records.length > 0 ? PubSub.publish(updates, void 0) : Effect.void)));
198
+ if (decision._tag === "failure") return yield* decision.error;
199
+ return decision.result;
200
+ }));
201
+ const readSnapshot = Effect.fn("MemoryThreadStore.readSnapshot")((threadId, afterSequence, limit) => Ref.get(state).pipe(Effect.flatMap((current) => findThread(current, threadId)), Effect.map((thread) => thread.records.filter((record) => record.sequence > (afterSequence ?? ZERO_CANONICAL_SEQUENCE)).slice(0, limit))));
202
+ const read = (unvalidated) => Stream.unwrap(Effect.gen(function* () {
203
+ const request = yield* validate(ThreadRead, "read", unvalidated);
204
+ const records = yield* readSnapshot(request.threadId, request.afterSequence, request.limit);
205
+ return Stream.fromIterable(records);
206
+ }));
207
+ const observe = (unvalidated) => Stream.unwrap(Effect.gen(function* () {
208
+ const request = yield* validate(ThreadObservation, "observe", unvalidated);
209
+ const afterSequence = yield* offsetSequence(request.threadId, request.afterOffset);
210
+ return Stream.unwrap(Effect.gen(function* () {
211
+ const subscription = yield* PubSub.subscribe(updates);
212
+ const initial = yield* readSnapshot(request.threadId, afterSequence, MAX_RECORDS_PER_THREAD);
213
+ const highWater = initial.length === 0 ? afterSequence : initial.at(-1)?.sequence ?? afterSequence;
214
+ 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]))));
215
+ return Stream.fromIterable(initial).pipe(Stream.concat(live));
216
+ }));
217
+ }));
218
+ const exportThread = Effect.fn("MemoryThreadStore.export")((unvalidated) => Effect.gen(function* () {
219
+ const request = yield* validate(ThreadExportRequest, "export", unvalidated);
220
+ const thread = yield* Ref.get(state).pipe(Effect.flatMap((current) => findThread(current, request.threadId)));
221
+ return ThreadExport.make({
222
+ format: "effect-agent/thread@1",
223
+ threadId: request.threadId,
224
+ tailSequence: thread.tailSequence,
225
+ tailDigest: thread.tailDigest,
226
+ records: thread.records
227
+ });
228
+ }));
229
+ const inspectTail = Effect.fn("MemoryThreadStore.inspectTail")((unvalidated) => Effect.gen(function* () {
230
+ const request = yield* validate(ThreadTailRequest, "inspectTail", unvalidated);
231
+ const thread = yield* Ref.get(state).pipe(Effect.flatMap((current) => findThread(current, request.threadId)));
232
+ return ThreadTail.make({
233
+ threadId: request.threadId,
234
+ tailSequence: thread.tailSequence,
235
+ tailDigest: thread.tailDigest,
236
+ producerEpoch: thread.producerEpoch
237
+ });
238
+ }));
239
+ const saveCheckpoint = Effect.fn("MemoryThreadStore.saveCheckpoint")((unvalidated) => Effect.gen(function* () {
240
+ yield* validateCheckpointVersion(unvalidated);
241
+ const request = yield* validate(SaveCheckpointRequest, "saveCheckpoint", unvalidated);
242
+ const decision = yield* Ref.modify(state, (current) => {
243
+ const checkpoint = request.checkpoint;
244
+ const thread = current.threads.get(checkpoint.threadId);
245
+ if (thread === void 0) return [{
246
+ _tag: "failure",
247
+ error: ThreadNotMaterialized.make({ threadId: checkpoint.threadId })
248
+ }, current];
249
+ if (checkpoint.throughSequence > thread.tailSequence) return [{
250
+ _tag: "failure",
251
+ error: CheckpointRejected.make({
252
+ threadId: checkpoint.threadId,
253
+ reason: "ahead-of-tail"
254
+ })
255
+ }, current];
256
+ if (thread.tailDigests.get(checkpoint.throughSequence) !== checkpoint.tailDigest) return [{
257
+ _tag: "failure",
258
+ error: CheckpointRejected.make({
259
+ threadId: checkpoint.threadId,
260
+ reason: "digest-mismatch"
261
+ })
262
+ }, current];
263
+ if (!thread.checkpoints.has(checkpoint.throughSequence) && thread.checkpoints.size >= MAX_CHECKPOINTS_PER_THREAD) return [{
264
+ _tag: "failure",
265
+ error: storeError("saveCheckpoint", `In-memory checkpoint limit ${MAX_CHECKPOINTS_PER_THREAD} exceeded`)
266
+ }, current];
267
+ const checkpoints = new Map(thread.checkpoints);
268
+ checkpoints.set(checkpoint.throughSequence, checkpoint);
269
+ const threads = new Map(current.threads);
270
+ threads.set(checkpoint.threadId, {
271
+ ...thread,
272
+ checkpoints
273
+ });
274
+ return [{ _tag: "success" }, { threads }];
275
+ });
276
+ if (decision._tag === "failure") return yield* decision.error;
277
+ }));
278
+ const loadCheckpoint = Effect.fn("MemoryThreadStore.loadCheckpoint")((unvalidated) => Effect.gen(function* () {
279
+ const request = yield* validate(LoadCheckpointRequest, "loadCheckpoint", unvalidated);
280
+ const thread = yield* Ref.get(state).pipe(Effect.flatMap((current) => findThread(current, request.threadId)));
281
+ const maximum = request.atOrBeforeSequence ?? thread.tailSequence;
282
+ let selected;
283
+ for (const [sequence, checkpoint] of thread.checkpoints) if (sequence <= maximum && (selected === void 0 || sequence > selected.throughSequence)) selected = checkpoint;
284
+ if (selected !== void 0 && thread.tailDigests.get(selected.throughSequence) !== selected.tailDigest) return yield* CheckpointRejected.make({
285
+ threadId: request.threadId,
286
+ reason: "digest-mismatch"
287
+ });
288
+ return Option.fromNullishOr(selected);
289
+ }));
290
+ return ThreadStore.of({
291
+ materialize,
292
+ append,
293
+ read,
294
+ observe,
295
+ export: exportThread,
296
+ inspectTail,
297
+ checkpoints: {
298
+ save: saveCheckpoint,
299
+ load: loadCheckpoint
300
+ }
301
+ });
302
+ });
303
+ /**
304
+ * In-memory canonical Thread persistence. Durable accepted work is served by the separate
305
+ * SubmissionLedger port; this Layer deliberately provides only the ThreadStore.
306
+ */
307
+ const MemoryThreadStoreLive = Layer.effect(ThreadStore, makeThreadStore);
308
+ //#endregion
309
+ export { MemoryThreadStoreLive, MemoryThreadStore_exports as t };
310
+
311
+ //# sourceMappingURL=MemoryThreadStore.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MemoryThreadStore.mjs","names":[],"sources":["../src/MemoryThreadStore.ts"],"sourcesContent":["import { ThreadId } from \"@effect-agent/core/Identifiers\";\nimport { digestCanonicalBatch, EMPTY_TAIL_DIGEST } from \"@effect-agent/thread/Digest\";\nimport {\n type ProducerEpoch,\n type RecordId,\n CanonicalRecordEnvelope,\n CanonicalSequence,\n ObservationOffset,\n type BatchId,\n type Digest,\n} from \"@effect-agent/thread/Records\";\nimport {\n type ThreadCheckpoint,\n AppendConflict,\n AppendResult,\n CheckpointRejected,\n ThreadExportRequest,\n ThreadExport,\n ThreadMaterialization,\n ThreadNotMaterialized,\n ThreadObservation,\n ThreadRead,\n ThreadStore,\n type ThreadCheckpoints,\n ThreadStoreError,\n ThreadTail,\n ThreadTailRequest,\n FenceRejected,\n FencedAppendRequest,\n LoadCheckpointRequest,\n SaveCheckpointRequest,\n} from \"@effect-agent/thread/ThreadStore\";\nimport { Crypto, Effect, Encoding, Layer, Option, PubSub, Ref, Schema, Stream } from \"effect\";\n\nconst MAX_THREADS = 256;\nconst MAX_RECORDS_PER_THREAD = 65_536;\nconst MAX_CHECKPOINTS_PER_THREAD = 1_024;\n\ninterface StoredBatch {\n readonly digest: Digest;\n readonly result: AppendResult;\n}\n\ninterface StoredThread {\n readonly producerEpoch: ProducerEpoch;\n readonly tailSequence: CanonicalSequence;\n readonly tailDigest: Digest;\n readonly records: ReadonlyArray<CanonicalRecordEnvelope>;\n readonly recordIds: ReadonlySet<RecordId>;\n readonly batches: ReadonlyMap<BatchId, StoredBatch>;\n readonly tailDigests: ReadonlyMap<CanonicalSequence, Digest>;\n readonly checkpoints: ReadonlyMap<CanonicalSequence, ThreadCheckpoint>;\n}\n\ninterface MemoryState {\n readonly threads: ReadonlyMap<ThreadId, StoredThread>;\n}\n\ntype AppendDecision =\n | {\n readonly _tag: \"failure\";\n readonly error: ThreadStoreError | ThreadNotMaterialized | AppendConflict | FenceRejected;\n }\n | {\n readonly _tag: \"success\";\n readonly result: AppendResult;\n readonly records: ReadonlyArray<CanonicalRecordEnvelope>;\n };\n\ntype MaterializeDecision =\n | { readonly _tag: \"failure\"; readonly error: ThreadStoreError | FenceRejected }\n | { readonly _tag: \"success\" };\n\ntype CheckpointDecision =\n | {\n readonly _tag: \"failure\";\n readonly error: ThreadNotMaterialized | ThreadStoreError | CheckpointRejected;\n }\n | { readonly _tag: \"success\" };\n\nconst storeError = (operation: string, message: string, cause?: unknown): ThreadStoreError =>\n cause === undefined\n ? ThreadStoreError.make({ operation, message })\n : ThreadStoreError.make({ operation, message, cause });\n\nconst validate = Effect.fn(\"MemoryThreadStore.validate\")(\n <A, I>(\n schema: Schema.Codec<A, I>,\n operation: string,\n value: unknown,\n ): Effect.Effect<A, ThreadStoreError> =>\n Schema.encodeUnknownEffect(schema)(value).pipe(\n Effect.flatMap(Schema.decodeUnknownEffect(schema)),\n Effect.mapError((error) => storeError(operation, `Invalid ${operation} request`, error)),\n ),\n);\n\nconst decodeCanonicalSequence = Schema.decodeSync(CanonicalSequence);\nconst ZERO_CANONICAL_SEQUENCE = decodeCanonicalSequence(0);\n\nconst offsetSequence = Effect.fn(\"MemoryThreadStore.offsetSequence\")((\n threadId: ThreadId,\n offset: ObservationOffset | undefined,\n): Effect.Effect<CanonicalSequence, ThreadStoreError> => {\n if (offset === undefined) return Effect.succeed(ZERO_CANONICAL_SEQUENCE);\n const prefix = `memory:v1:${Encoding.encodeBase64(threadId)}:`;\n const encodedSequence = offset.startsWith(prefix) ? offset.slice(prefix.length) : \"\";\n\n if (!/^\\d+$/.test(encodedSequence)) {\n return Effect.fail(storeError(\"observe\", \"Malformed observation offset\"));\n }\n const sequence = Number(encodedSequence);\n\n return Number.isSafeInteger(sequence)\n ? Schema.decodeUnknownEffect(CanonicalSequence)(sequence).pipe(\n Effect.mapError(() => storeError(\"observe\", \"Malformed observation offset\")),\n )\n : Effect.fail(storeError(\"observe\", \"Malformed observation offset\"));\n});\n\nconst observationOffset = (threadId: ThreadId, sequence: CanonicalSequence): ObservationOffset =>\n Schema.decodeSync(ObservationOffset)(`memory:v1:${Encoding.encodeBase64(threadId)}:${sequence}`);\n\nconst findThread = Effect.fn(\"MemoryThreadStore.findThread\")((\n state: MemoryState,\n threadId: ThreadId,\n): Effect.Effect<StoredThread, ThreadNotMaterialized> => {\n const thread = state.threads.get(threadId);\n\n return thread === undefined\n ? Effect.fail(ThreadNotMaterialized.make({ threadId }))\n : Effect.succeed(thread);\n});\n\nconst CheckpointVersionEnvelope = Schema.Struct({\n checkpoint: Schema.Struct({\n threadId: ThreadId,\n schemaVersion: Schema.Natural,\n }),\n});\n\nconst validateCheckpointVersion = Effect.fn(\"MemoryThreadStore.validateCheckpointVersion\")(\n function* (value: unknown): Effect.fn.Return<void, ThreadStoreError | CheckpointRejected> {\n const envelope = yield* Schema.decodeUnknownEffect(CheckpointVersionEnvelope)(value).pipe(\n Effect.mapError(() => storeError(\"saveCheckpoint\", \"Invalid saveCheckpoint request\")),\n );\n\n if (envelope.checkpoint.schemaVersion !== 1) {\n return yield* CheckpointRejected.make({\n threadId: envelope.checkpoint.threadId,\n reason: \"unsupported-version\",\n });\n }\n },\n);\n\nconst makeThreadStore = Effect.gen(function* () {\n const crypto = yield* Crypto.Crypto;\n const state = yield* Ref.make<MemoryState>({ threads: new Map() });\n const updates = yield* PubSub.sliding<void>(1);\n\n yield* Effect.addFinalizer(() => PubSub.shutdown(updates));\n\n const materialize: ThreadStore[\"Service\"][\"materialize\"] = Effect.fn(\n \"MemoryThreadStore.materialize\",\n )((unvalidated) =>\n Effect.gen(function* () {\n const request = yield* validate(ThreadMaterialization, \"materialize\", unvalidated);\n\n const decision = yield* Ref.modify(\n state,\n (current): readonly [MaterializeDecision, MemoryState] => {\n const existing = current.threads.get(request.threadId);\n\n if (existing !== undefined) {\n if (request.producerEpoch < existing.producerEpoch) {\n return [\n {\n _tag: \"failure\",\n error: FenceRejected.make({\n threadId: request.threadId,\n actualEpoch: existing.producerEpoch,\n attemptedEpoch: request.producerEpoch,\n }),\n },\n current,\n ];\n }\n if (request.producerEpoch === existing.producerEpoch) {\n return [{ _tag: \"success\" }, current];\n }\n const threads = new Map(current.threads);\n\n threads.set(request.threadId, {\n ...existing,\n producerEpoch: request.producerEpoch,\n });\n\n return [{ _tag: \"success\" }, { threads }];\n }\n if (current.threads.size >= MAX_THREADS) {\n return [\n {\n _tag: \"failure\",\n error: storeError(\"materialize\", `In-memory thread limit ${MAX_THREADS} exceeded`),\n },\n current,\n ];\n }\n const threads = new Map(current.threads);\n\n threads.set(request.threadId, {\n producerEpoch: request.producerEpoch,\n tailSequence: ZERO_CANONICAL_SEQUENCE,\n tailDigest: EMPTY_TAIL_DIGEST,\n records: [],\n recordIds: new Set(),\n batches: new Map(),\n tailDigests: new Map([[ZERO_CANONICAL_SEQUENCE, EMPTY_TAIL_DIGEST]]),\n checkpoints: new Map(),\n });\n\n return [{ _tag: \"success\" }, { threads }];\n },\n );\n\n if (decision._tag === \"failure\") return yield* decision.error;\n }),\n );\n\n const append: ThreadStore[\"Service\"][\"append\"] = Effect.fn(\"MemoryThreadStore.append\")(\n (unvalidated) =>\n Effect.gen(function* () {\n const request = yield* validate(FencedAppendRequest, \"append\", unvalidated);\n\n const digest = yield* digestCanonicalBatch(request.expectedTailDigest, request.batch).pipe(\n Effect.provideService(Crypto.Crypto, crypto),\n Effect.mapError((error) => storeError(\"append\", error.message, error)),\n );\n\n const decision = yield* Effect.uninterruptible(\n Ref.modify(state, (current): readonly [AppendDecision, MemoryState] => {\n const thread = current.threads.get(request.threadId);\n\n if (thread === undefined) {\n return [\n {\n _tag: \"failure\",\n error: ThreadNotMaterialized.make({\n threadId: request.threadId,\n }),\n },\n current,\n ];\n }\n if (request.producerEpoch !== thread.producerEpoch) {\n return [\n {\n _tag: \"failure\",\n error: FenceRejected.make({\n threadId: request.threadId,\n actualEpoch: thread.producerEpoch,\n attemptedEpoch: request.producerEpoch,\n }),\n },\n current,\n ];\n }\n const previous = thread.batches.get(request.batch.batchId);\n\n if (previous !== undefined) {\n if (previous.digest !== digest) {\n return [\n {\n _tag: \"failure\",\n error: AppendConflict.make({\n threadId: request.threadId,\n batchId: request.batch.batchId,\n reason: \"batch-digest\",\n }),\n },\n current,\n ];\n }\n\n return [\n {\n _tag: \"success\",\n result: AppendResult.make({\n firstSequence: previous.result.firstSequence,\n lastSequence: previous.result.lastSequence,\n tailDigest: previous.result.tailDigest,\n replayed: true,\n }),\n records: [],\n },\n current,\n ];\n }\n if (\n request.expectedTailSequence !== thread.tailSequence ||\n request.expectedTailDigest !== thread.tailDigest\n ) {\n return [\n {\n _tag: \"failure\",\n error: AppendConflict.make({\n threadId: request.threadId,\n batchId: request.batch.batchId,\n reason: \"tail\",\n actualTailSequence: thread.tailSequence,\n actualTailDigest: thread.tailDigest,\n }),\n },\n current,\n ];\n }\n if (thread.records.length + request.batch.records.length > MAX_RECORDS_PER_THREAD) {\n return [\n {\n _tag: \"failure\",\n error: storeError(\n \"append\",\n `In-memory record limit ${MAX_RECORDS_PER_THREAD} exceeded`,\n ),\n },\n current,\n ];\n }\n\n const batchRecordIds = new Set<RecordId>();\n\n for (const record of request.batch.records) {\n if (thread.recordIds.has(record.recordId) || batchRecordIds.has(record.recordId)) {\n return [\n {\n _tag: \"failure\",\n error: AppendConflict.make({\n threadId: request.threadId,\n batchId: request.batch.batchId,\n reason: \"record-identity\",\n }),\n },\n current,\n ];\n }\n batchRecordIds.add(record.recordId);\n }\n\n const records = request.batch.records.map((record, index) => {\n const sequence = decodeCanonicalSequence(thread.tailSequence + index + 1);\n\n return CanonicalRecordEnvelope.make({\n threadId: request.threadId,\n batchId: request.batch.batchId,\n sequence,\n offset: observationOffset(request.threadId, sequence),\n record,\n });\n });\n\n const lastSequence = decodeCanonicalSequence(thread.tailSequence + records.length);\n\n const result = AppendResult.make({\n firstSequence: decodeCanonicalSequence(thread.tailSequence + 1),\n lastSequence,\n tailDigest: digest,\n replayed: false,\n });\n\n const batches = new Map(thread.batches);\n\n batches.set(request.batch.batchId, { digest, result });\n const recordIds = new Set(thread.recordIds);\n\n for (const recordId of batchRecordIds) recordIds.add(recordId);\n const tailDigests = new Map(thread.tailDigests);\n\n tailDigests.set(lastSequence, digest);\n const threads = new Map(current.threads);\n\n threads.set(request.threadId, {\n ...thread,\n tailSequence: lastSequence,\n tailDigest: digest,\n records: [...thread.records, ...records],\n recordIds,\n batches,\n tailDigests,\n });\n\n return [{ _tag: \"success\", result, records }, { threads }];\n }).pipe(\n Effect.tap((decision) =>\n decision._tag === \"success\" && decision.records.length > 0\n ? PubSub.publish(updates, undefined)\n : Effect.void,\n ),\n ),\n );\n\n if (decision._tag === \"failure\") return yield* decision.error;\n\n return decision.result;\n }),\n );\n\n const readSnapshot = Effect.fn(\"MemoryThreadStore.readSnapshot\")(\n (threadId: ThreadId, afterSequence: CanonicalSequence | undefined, limit: number) =>\n Ref.get(state).pipe(\n Effect.flatMap((current) => findThread(current, threadId)),\n Effect.map((thread) =>\n thread.records\n .filter((record) => record.sequence > (afterSequence ?? ZERO_CANONICAL_SEQUENCE))\n .slice(0, limit),\n ),\n ),\n );\n\n const read: ThreadStore[\"Service\"][\"read\"] = (unvalidated) =>\n Stream.unwrap(\n Effect.gen(function* () {\n const request = yield* validate(ThreadRead, \"read\", unvalidated);\n const records = yield* readSnapshot(request.threadId, request.afterSequence, request.limit);\n\n return Stream.fromIterable(records);\n }),\n );\n\n const observe: ThreadStore[\"Service\"][\"observe\"] = (unvalidated) =>\n Stream.unwrap(\n Effect.gen(function* () {\n const request = yield* validate(ThreadObservation, \"observe\", unvalidated);\n const afterSequence = yield* offsetSequence(request.threadId, request.afterOffset);\n\n return Stream.unwrap(\n Effect.gen(function* () {\n const subscription = yield* PubSub.subscribe(updates);\n\n const initial = yield* readSnapshot(\n request.threadId,\n afterSequence,\n MAX_RECORDS_PER_THREAD,\n );\n\n const highWater =\n initial.length === 0 ? afterSequence : (initial.at(-1)?.sequence ?? afterSequence);\n\n const live = Stream.fromEffectRepeat(PubSub.take(subscription)).pipe(\n Stream.mapAccumEffect(\n () => highWater,\n (lastSequence) =>\n readSnapshot(request.threadId, lastSequence, MAX_RECORDS_PER_THREAD).pipe(\n Effect.map(\n (records) => [records.at(-1)?.sequence ?? lastSequence, records] as const,\n ),\n ),\n ),\n );\n\n return Stream.fromIterable(initial).pipe(Stream.concat(live));\n }),\n );\n }),\n );\n\n const exportThread: ThreadStore[\"Service\"][\"export\"] = Effect.fn(\"MemoryThreadStore.export\")(\n (unvalidated) =>\n Effect.gen(function* () {\n const request = yield* validate(ThreadExportRequest, \"export\", unvalidated);\n\n const thread = yield* Ref.get(state).pipe(\n Effect.flatMap((current) => findThread(current, request.threadId)),\n );\n\n return ThreadExport.make({\n format: \"effect-agent/thread@1\",\n threadId: request.threadId,\n tailSequence: thread.tailSequence,\n tailDigest: thread.tailDigest,\n records: thread.records,\n });\n }),\n );\n\n const inspectTail: ThreadStore[\"Service\"][\"inspectTail\"] = Effect.fn(\n \"MemoryThreadStore.inspectTail\",\n )((unvalidated) =>\n Effect.gen(function* () {\n const request = yield* validate(ThreadTailRequest, \"inspectTail\", unvalidated);\n\n const thread = yield* Ref.get(state).pipe(\n Effect.flatMap((current) => findThread(current, request.threadId)),\n );\n\n return ThreadTail.make({\n threadId: request.threadId,\n tailSequence: thread.tailSequence,\n tailDigest: thread.tailDigest,\n producerEpoch: thread.producerEpoch,\n });\n }),\n );\n\n const saveCheckpoint: ThreadCheckpoints[\"save\"] = Effect.fn(\"MemoryThreadStore.saveCheckpoint\")(\n (unvalidated) =>\n Effect.gen(function* () {\n yield* validateCheckpointVersion(unvalidated);\n const request = yield* validate(SaveCheckpointRequest, \"saveCheckpoint\", unvalidated);\n\n const decision = yield* Ref.modify(\n state,\n (current): readonly [CheckpointDecision, MemoryState] => {\n const checkpoint = request.checkpoint;\n const thread = current.threads.get(checkpoint.threadId);\n\n if (thread === undefined) {\n return [\n {\n _tag: \"failure\",\n error: ThreadNotMaterialized.make({\n threadId: checkpoint.threadId,\n }),\n },\n current,\n ];\n }\n if (checkpoint.throughSequence > thread.tailSequence) {\n return [\n {\n _tag: \"failure\",\n error: CheckpointRejected.make({\n threadId: checkpoint.threadId,\n reason: \"ahead-of-tail\",\n }),\n },\n current,\n ];\n }\n if (thread.tailDigests.get(checkpoint.throughSequence) !== checkpoint.tailDigest) {\n return [\n {\n _tag: \"failure\",\n error: CheckpointRejected.make({\n threadId: checkpoint.threadId,\n reason: \"digest-mismatch\",\n }),\n },\n current,\n ];\n }\n if (\n !thread.checkpoints.has(checkpoint.throughSequence) &&\n thread.checkpoints.size >= MAX_CHECKPOINTS_PER_THREAD\n ) {\n return [\n {\n _tag: \"failure\",\n error: storeError(\n \"saveCheckpoint\",\n `In-memory checkpoint limit ${MAX_CHECKPOINTS_PER_THREAD} exceeded`,\n ),\n },\n current,\n ];\n }\n const checkpoints = new Map(thread.checkpoints);\n\n checkpoints.set(checkpoint.throughSequence, checkpoint);\n const threads = new Map(current.threads);\n\n threads.set(checkpoint.threadId, { ...thread, checkpoints });\n\n return [{ _tag: \"success\" }, { threads }];\n },\n );\n\n if (decision._tag === \"failure\") return yield* decision.error;\n }),\n );\n\n const loadCheckpoint: ThreadCheckpoints[\"load\"] = Effect.fn(\"MemoryThreadStore.loadCheckpoint\")(\n (unvalidated) =>\n Effect.gen(function* () {\n const request = yield* validate(LoadCheckpointRequest, \"loadCheckpoint\", unvalidated);\n\n const thread = yield* Ref.get(state).pipe(\n Effect.flatMap((current) => findThread(current, request.threadId)),\n );\n\n const maximum = request.atOrBeforeSequence ?? thread.tailSequence;\n let selected: ThreadCheckpoint | undefined;\n\n for (const [sequence, checkpoint] of thread.checkpoints) {\n if (\n sequence <= maximum &&\n (selected === undefined || sequence > selected.throughSequence)\n ) {\n selected = checkpoint;\n }\n }\n if (\n selected !== undefined &&\n thread.tailDigests.get(selected.throughSequence) !== selected.tailDigest\n ) {\n return yield* CheckpointRejected.make({\n threadId: request.threadId,\n reason: \"digest-mismatch\",\n });\n }\n\n return Option.fromNullishOr(selected);\n }),\n );\n\n return ThreadStore.of({\n materialize,\n append,\n read,\n observe,\n export: exportThread,\n inspectTail,\n checkpoints: { save: saveCheckpoint, load: loadCheckpoint },\n });\n});\n\n/**\n * In-memory canonical Thread persistence. Durable accepted work is served by the separate\n * SubmissionLedger port; this Layer deliberately provides only the ThreadStore.\n */\nexport const MemoryThreadStoreLive = Layer.effect(ThreadStore, makeThreadStore);\n"],"mappings":"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"}
package/dist/index.d.mts CHANGED
@@ -1,53 +1,6 @@
1
- import { MemoryIndexError, SemanticMemoryIndex, SemanticMemoryProfile } from "@effect-agent/core";
2
- import { ScheduleStore, SourcePartition, SubmissionLedger, SubscriptionError, SubscriptionStore, ThreadStore } from "@effect-agent/thread";
3
- import { Crypto, Effect, Layer, Option, Schema } from "effect";
4
- //#region src/memory-ledger.d.ts
5
- /** Construction options for the in-memory reference SubmissionLedger. */
6
- interface MemorySubmissionLedgerOptions {
7
- /**
8
- * Test-only fault seam for `resolveAdmission` (SUB-031): when the effect yields a reason,
9
- * the resolution answers `Indeterminate` with it instead of consulting the store — modelling
10
- * an authoritative child owner that is temporarily unreachable. `Option.none()` restores the
11
- * store-derived answer. Ledger state is never mutated by the fault.
12
- */
13
- readonly resolveAdmissionFault?: Effect.Effect<Option.Option<string>>;
14
- }
15
- /**
16
- * In-memory reference SubmissionLedger Layer (durability `non-durable`). All state lives in one
17
- * `Ref` owned by the Layer's Scope; no daemon fibers are spawned and no wall clock is consulted.
18
- */
19
- declare const memorySubmissionLedgerLayer: (options?: MemorySubmissionLedgerOptions) => Layer.Layer<SubmissionLedger>;
20
- declare const MemorySubmissionLedgerLive: Layer.Layer<SubmissionLedger>;
21
- //#endregion
22
- //#region src/memory-schedule-store.d.ts
23
- declare const memoryScheduleStoreLayer: () => Layer.Layer<ScheduleStore>;
24
- declare const MemoryScheduleStoreLive: Layer.Layer<ScheduleStore>;
25
- //#endregion
26
- //#region src/memory-subscription-store.d.ts
27
- declare const memorySubscriptionStoreLayer: (partition: SourcePartition) => Layer.Layer<SubscriptionStore, SubscriptionError>;
28
- //#endregion
29
- //#region src/memory-storage.d.ts
30
- declare const MemoryThreadStoreLive: Layer.Layer<ThreadStore, never, Crypto.Crypto>;
31
- /**
32
- * In-memory canonical Thread persistence. Durable accepted work is served by the separate
33
- * SubmissionLedger port; this Layer deliberately provides only the ThreadStore.
34
- */
35
- declare const MemoryStorageLive: Layer.Layer<ThreadStore, never, Crypto.Crypto>;
36
- //#endregion
37
- //#region src/semantic-memory-index.d.ts
38
- declare const InMemorySemanticIndexCapacity_base: Schema.Class<InMemorySemanticIndexCapacity, Schema.Struct<{
39
- readonly maxSources: Schema.Int;
40
- readonly maxChunks: Schema.Int;
41
- readonly maxSourceBytes: Schema.optionalKey<Schema.Int>;
42
- }>, {}>;
43
- /**
44
- * Hard per-Layer bounds for disposable semantic index state. maxChunks times profile dimensions
45
- * must not exceed 16,777,216 vector components. maxSourceBytes bounds the aggregate UTF-8 JSON
46
- * of retained source identities and defaults to 16 MiB; it is not a general heap limit.
47
- */
48
- declare class InMemorySemanticIndexCapacity extends InMemorySemanticIndexCapacity_base {}
49
- /** Scoped disposable semantic index. No persistent build or recovery state is retained. */
50
- declare const inMemorySemanticIndexLayer: (profile: SemanticMemoryProfile, capacity: InMemorySemanticIndexCapacity) => Layer.Layer<SemanticMemoryIndex, MemoryIndexError>;
51
- //#endregion
52
- export { InMemorySemanticIndexCapacity, MemoryScheduleStoreLive, MemoryStorageLive, MemorySubmissionLedgerLive, MemorySubmissionLedgerOptions, MemoryThreadStoreLive, inMemorySemanticIndexLayer, memoryScheduleStoreLayer, memorySubmissionLedgerLayer, memorySubscriptionStoreLayer };
53
- //# sourceMappingURL=index.d.mts.map
1
+ import { t as MemoryScheduleStore_d_exports } from "./MemoryScheduleStore.mjs";
2
+ import { t as MemorySemanticIndex_d_exports } from "./MemorySemanticIndex.mjs";
3
+ import { t as MemorySubmissionLedger_d_exports } from "./MemorySubmissionLedger.mjs";
4
+ import { t as MemorySubscriptionStore_d_exports } from "./MemorySubscriptionStore.mjs";
5
+ import { t as MemoryThreadStore_d_exports } from "./MemoryThreadStore.mjs";
6
+ export { MemoryScheduleStore_d_exports as MemoryScheduleStore, MemorySemanticIndex_d_exports as MemorySemanticIndex, MemorySubmissionLedger_d_exports as MemorySubmissionLedger, MemorySubscriptionStore_d_exports as MemorySubscriptionStore, MemoryThreadStore_d_exports as MemoryThreadStore };