@effect-agent/storage-sqlite 0.1.0-beta.48 → 0.1.0-beta.50
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.
- package/dist/SqliteScheduleStore.mjs +1 -1
- package/dist/SqliteSubmissionLedger.mjs +48 -3
- package/dist/SqliteSubmissionLedger.mjs.map +1 -1
- package/dist/SqliteSubscriptionStore.mjs +17 -585
- package/dist/SqliteSubscriptionStore.mjs.map +1 -1
- package/dist/SqliteThreadStore.mjs +1 -1
- package/dist/{sqlite-journal-C5SZnSdC.mjs → sqlite-journal-BxBxOUEI.mjs} +2 -29
- package/dist/sqlite-journal-BxBxOUEI.mjs.map +1 -0
- package/package.json +1 -1
- package/src/SqliteSubmissionLedger.ts +82 -0
- package/src/SqliteSubscriptionStore.ts +31 -1038
- package/src/internal/sqlite-journal.ts +0 -39
- package/dist/sqlite-journal-C5SZnSdC.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SqliteSubscriptionStore.mjs","names":[],"sources":["../src/SqliteSubscriptionStore.ts"],"sourcesContent":["import { Digest } from \"@effect-agent/thread/Records\";\nimport { type SubscriptionFailpointError } from \"@effect-agent/thread/Subscription\";\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} from \"@effect-agent/thread/Subscription\";\nimport {\n applySubscriptionDeliveryChange,\n sameAcceptedEventIdentity,\n sameSourcePartition,\n subscriptionCanSelect,\n subscriptionDeliveryCanSelect,\n} from \"@effect-agent/thread/SubscriptionTransition\";\nimport { Clock, Effect, Layer, Result, Schema } from \"effect\";\nimport * as SqlClientService from \"effect/unstable/sql/SqlClient\";\nimport type { SqlError } from \"effect/unstable/sql/SqlError\";\n\nimport { initializeSqliteJournal } from \"./internal/sqlite-journal.ts\";\nimport type { SqliteStorageConfig } from \"./SqliteStorageConfig.ts\";\nimport type { SqliteStorageFailpoint } from \"./SqliteStorageFailpoint.ts\";\nimport type { SqliteStorageInitializationError } from \"./SqliteThreadStore.ts\";\n\nconst StoredJson = Schema.String.check(Schema.isMaxLength(16 * 1024 * 1024));\nconst CountRow = Schema.Struct({ count: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)) });\nconst SequenceRow = Schema.Struct({ sequence: Schema.Natural });\n\nconst ScanRow = Schema.Struct({\n event_scan_cursor: Schema.String,\n delivery_scan_cursor: Schema.String,\n recovery_scan_cursor: Schema.Natural,\n});\n\nconst JsonRow = Schema.Struct({ record_json: StoredJson });\n\nconst RegistrationRow = Schema.Struct({\n owner_id: Schema.String,\n subscription_id: Schema.String,\n ordinal: Schema.Natural,\n source_name: Schema.String,\n source_version: Schema.String,\n matching_key: Schema.String,\n state: SubscriptionRecord.fields.state,\n expires_at_millis: Schema.Number,\n recovery_at_millis: Schema.NullOr(Schema.Number),\n record_json: StoredJson,\n});\n\nconst EventRow = Schema.Struct({\n event_id: Schema.String,\n source_name: Schema.String,\n source_version: Schema.String,\n matching_key: Schema.String,\n payload_digest: Digest,\n cutoff: Schema.Natural,\n cursor: Schema.Natural,\n routing_complete: Schema.Number,\n next_attempt_at_millis: Schema.Number,\n record_json: StoredJson,\n});\n\nconst DeliveryRow = Schema.Struct({\n owner_id: Schema.String,\n subscription_id: Schema.String,\n event_id: Schema.String,\n delivery_key: Schema.String,\n state: SubscriptionDelivery.fields.state,\n next_attempt_at_millis: Schema.Number,\n record_json: StoredJson,\n});\n\nconst error = (reason: SubscriptionError[\"reason\"], code: string) =>\n SubscriptionError.make({ reason, code });\n\nconst unavailable = (operation: string) => error(\"storage\", operation);\nconst corrupt = (operation: string) => error(\"corrupt\", operation);\nconst bytes = (value: unknown) => new TextEncoder().encode(JSON.stringify(value)).byteLength;\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 encode = <A, I>(schema: Schema.Codec<A, I>, value: A, code: string) =>\n Schema.encodeEffect(Schema.fromJsonString(schema))(value).pipe(\n Effect.mapError(() => corrupt(code)),\n );\n\nconst decode = <A, I>(schema: Schema.Codec<A, I>, value: string, code: string) =>\n Schema.decodeEffect(Schema.fromJsonString(schema))(value).pipe(\n Effect.mapError(() => corrupt(code)),\n );\n\nconst decodeRows = <A, I>(schema: Schema.Codec<A, I>, rows: unknown, code: string) =>\n Schema.decodeUnknownEffect(Schema.Array(schema))(rows).pipe(Effect.mapError(() => corrupt(code)));\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 makeSubscriptionStore = Effect.fn(\"SqliteSubscriptionStore.make\")(function* (\n owned: SourcePartition,\n) {\n const partition = yield* validate(SourcePartition, owned, \"partition\");\n const sql = yield* SqlClientService.SqlClient;\n const failpoint = yield* SubscriptionFailpoint;\n\n yield* initializeSqliteJournal();\n yield* sql`\n INSERT INTO effect_agent_subscription_sequences (\n tenant_id, source_address, sequence, event_scan_cursor, delivery_scan_cursor, recovery_scan_cursor\n ) VALUES (${partition.tenantId}, ${partition.address}, 0, '', '', 0) ON CONFLICT DO NOTHING\n `.pipe(Effect.mapError(() => unavailable(\"initialize subscription partition\")));\n\n const transact = <A>(effect: Effect.Effect<A, SubscriptionError | SubscriptionFailpointError>) =>\n sql\n .withTransaction(effect)\n .pipe(Effect.catchTag(\"SqlError\", () => Effect.fail(unavailable(\"transaction\"))));\n\n const query = <A extends object>(\n effect: Effect.Effect<ReadonlyArray<A>, SqlError>,\n code: string,\n ) => effect.pipe(Effect.mapError(() => unavailable(code)));\n\n const requirePartition = (candidate: SourcePartition, code: string) =>\n sameSourcePartition(candidate, partition)\n ? Effect.void\n : Effect.fail(error(\"validation\", code));\n\n const requireKey = Effect.fn(\"SqliteSubscriptionStore.requireKey\")(function* (\n input: SubscriptionKey,\n code: string,\n ) {\n const key = yield* validate(SubscriptionKey, input, code);\n\n yield* requirePartition(key.partition, code);\n\n return key;\n });\n\n const readRegistration = Effect.fn(\"SqliteSubscriptionStore.readRegistration\")(function* (\n key: SubscriptionKey,\n code: string,\n ) {\n const rows = yield* query(\n sql<Record<string, unknown>>`\n SELECT owner_id, subscription_id, ordinal, source_name, source_version, matching_key, state,\n expires_at_millis, recovery_at_millis, record_json FROM effect_agent_subscriptions\n WHERE tenant_id=${partition.tenantId} AND source_address=${partition.address}\n AND owner_id=${key.ownerId} AND subscription_id=${key.subscriptionId}\n `,\n code,\n );\n\n const decodedRows = yield* decodeRows(RegistrationRow, rows, code);\n\n if (decodedRows.length > 1) return yield* corrupt(code);\n const row = decodedRows[0];\n\n if (row === undefined) return null;\n const record = yield* decode(SubscriptionRecord, row.record_json, code);\n\n if (\n !sameSourcePartition(record.key.partition, partition) ||\n record.key.ownerId !== row.owner_id ||\n record.key.subscriptionId !== row.subscription_id ||\n record.ordinal !== row.ordinal ||\n record.configuration.source.name !== row.source_name ||\n record.configuration.source.version !== row.source_version ||\n record.configuration.matchingKey !== row.matching_key ||\n record.state !== row.state ||\n record.configuration.expiresAtMillis !== row.expires_at_millis ||\n (record.recovery?.nextAttemptAtMillis ?? null) !== row.recovery_at_millis\n )\n return yield* corrupt(`${code}-projection`);\n\n return record;\n });\n\n const readEvent = Effect.fn(\"SqliteSubscriptionStore.readEvent\")(function* (\n eventId: string,\n code: string,\n ) {\n const rows = yield* query(\n sql<Record<string, unknown>>`\n SELECT event_id, source_name, source_version, matching_key, payload_digest, cutoff, cursor,\n routing_complete, next_attempt_at_millis, record_json FROM effect_agent_subscription_events\n WHERE tenant_id=${partition.tenantId} AND source_address=${partition.address} AND event_id=${eventId}\n `,\n code,\n );\n\n const decodedRows = yield* decodeRows(EventRow, rows, code);\n\n if (decodedRows.length > 1) return yield* corrupt(code);\n const row = decodedRows[0];\n\n if (row === undefined) return null;\n const event = yield* decode(AcceptedEvent, row.record_json, code);\n\n if (\n !sameSourcePartition(event.partition, partition) ||\n event.eventId !== row.event_id ||\n event.source.name !== row.source_name ||\n event.source.version !== row.source_version ||\n event.matchingKey !== row.matching_key ||\n event.payloadDigest !== row.payload_digest ||\n event.cutoff !== row.cutoff ||\n event.cursor !== row.cursor ||\n (event.routingComplete ? 1 : 0) !== row.routing_complete ||\n event.nextAttemptAtMillis !== row.next_attempt_at_millis\n )\n return yield* corrupt(`${code}-projection`);\n\n return event;\n });\n\n const readDelivery = Effect.fn(\"SqliteSubscriptionStore.readDelivery\")(function* (\n key: SubscriptionDeliveryKey,\n code: string,\n ) {\n const rows = yield* query(\n sql<Record<string, unknown>>`\n SELECT owner_id, subscription_id, event_id, delivery_key, state, next_attempt_at_millis, record_json\n FROM effect_agent_subscription_deliveries\n WHERE tenant_id=${partition.tenantId} AND source_address=${partition.address}\n AND owner_id=${key.subscription.ownerId} AND subscription_id=${key.subscription.subscriptionId}\n AND event_id=${key.eventId}\n `,\n code,\n );\n\n const decodedRows = yield* decodeRows(DeliveryRow, rows, code);\n\n if (decodedRows.length > 1) return yield* corrupt(code);\n const row = decodedRows[0];\n\n if (row === undefined) return null;\n const delivery = yield* decode(SubscriptionDelivery, row.record_json, code);\n\n if (\n !sameSourcePartition(delivery.key.subscription.partition, partition) ||\n delivery.key.subscription.ownerId !== row.owner_id ||\n delivery.key.subscription.subscriptionId !== row.subscription_id ||\n delivery.key.eventId !== row.event_id ||\n subscriptionDeliveryKeyString(delivery.key) !== row.delivery_key ||\n delivery.state !== row.state ||\n delivery.retry.nextAttemptAtMillis !== row.next_attempt_at_millis\n )\n return yield* corrupt(`${code}-projection`);\n\n return delivery;\n });\n\n const count = Effect.fn(\"SqliteSubscriptionStore.count\")(function* (\n statement: Effect.Effect<ReadonlyArray<Record<string, unknown>>, SqlError>,\n code: string,\n ) {\n const rows = yield* query(statement, code);\n const decoded = yield* decodeRows(CountRow, rows, code);\n\n if (decoded.length !== 1) return yield* corrupt(code);\n\n return decoded[0].count;\n });\n\n const nextSequence = Effect.fn(\"SqliteSubscriptionStore.nextSequence\")(function* () {\n const rows = yield* query(\n sql<Record<string, unknown>>`\n UPDATE effect_agent_subscription_sequences SET sequence=sequence+1\n WHERE tenant_id=${partition.tenantId} AND source_address=${partition.address}\n RETURNING sequence\n `,\n \"advance subscription sequence\",\n );\n\n const decoded = yield* decodeRows(SequenceRow, rows, \"advance subscription sequence\");\n\n if (decoded.length !== 1) return yield* corrupt(\"subscription sequence\");\n\n return decoded[0].sequence;\n });\n\n const writeRegistration = Effect.fn(\"SqliteSubscriptionStore.writeRegistration\")(function* (\n record: SubscriptionRecord,\n ) {\n const json = yield* encode(SubscriptionRecord, record, \"encode subscription\");\n\n yield* query(\n sql<Record<string, unknown>>`\n UPDATE effect_agent_subscriptions SET state=${record.state}, expires_at_millis=${record.configuration.expiresAtMillis},\n recovery_at_millis=${record.recovery?.nextAttemptAtMillis ?? null}, record_json=${json}\n WHERE tenant_id=${partition.tenantId} AND source_address=${partition.address}\n AND owner_id=${record.key.ownerId} AND subscription_id=${record.key.subscriptionId}\n `,\n \"write subscription\",\n );\n });\n\n const writeEvent = Effect.fn(\"SqliteSubscriptionStore.writeEvent\")(function* (\n event: AcceptedEvent,\n ) {\n const json = yield* encode(AcceptedEvent, event, \"encode event\");\n\n yield* query(\n sql<Record<string, unknown>>`\n UPDATE effect_agent_subscription_events SET cursor=${event.cursor}, routing_complete=${event.routingComplete ? 1 : 0},\n next_attempt_at_millis=${event.nextAttemptAtMillis}, record_json=${json}\n WHERE tenant_id=${partition.tenantId} AND source_address=${partition.address} AND event_id=${event.eventId}\n `,\n \"write event\",\n );\n });\n\n const writeDelivery = Effect.fn(\"SqliteSubscriptionStore.writeDelivery\")(function* (\n delivery: SubscriptionDelivery,\n ) {\n const json = yield* encode(SubscriptionDelivery, delivery, \"encode delivery\");\n\n yield* query(\n sql<Record<string, unknown>>`\n UPDATE effect_agent_subscription_deliveries SET state=${delivery.state},\n next_attempt_at_millis=${delivery.retry.nextAttemptAtMillis}, record_json=${json}\n WHERE tenant_id=${partition.tenantId} AND source_address=${partition.address}\n AND owner_id=${delivery.key.subscription.ownerId} AND subscription_id=${delivery.key.subscription.subscriptionId}\n AND event_id=${delivery.key.eventId}\n `,\n \"write delivery\",\n );\n });\n\n const register: SubscriptionStore[\"Service\"][\"register\"] = Effect.fn(\n \"SqliteSubscriptionStore.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.partition, \"register-partition\");\n\n const result = yield* transact(\n Effect.gen(function* () {\n const existing = yield* readRegistration(record.key, \"register-existing\");\n\n if (existing !== null) {\n if (existing.creationFingerprint !== record.creationFingerprint)\n return yield* error(\"conflict\", \"registration-identity\");\n\n return { value: existing, changed: false } as const;\n }\n if (bytes(record.configuration.context) > limits.maxContextBytes)\n return yield* error(\"capacity\", \"context-bytes\");\n if (bytes(record.configuration.parameters) > limits.maxPayloadBytes)\n return yield* error(\"capacity\", \"parameters-bytes\");\n if (\n record.configuration.expiresAtMillis - record.createdAtMillis >\n limits.maxLifetimeMillis\n )\n return yield* error(\"capacity\", \"lifetime\");\n if (\n (yield* count(\n sql<\n Record<string, unknown>\n >`SELECT COUNT(*) AS count FROM effect_agent_subscriptions WHERE tenant_id=${partition.tenantId} AND source_address=${partition.address}`,\n \"count registrations\",\n )) >= limits.maxRegistrations\n )\n return yield* error(\"capacity\", \"registrations\");\n if (\n (yield* count(\n sql<\n Record<string, unknown>\n >`SELECT COUNT(*) AS count FROM effect_agent_subscriptions WHERE tenant_id=${partition.tenantId} AND source_address=${partition.address} AND owner_id=${record.key.ownerId}`,\n \"count owner registrations\",\n )) >= limits.maxRegistrationsPerOwner\n )\n return yield* error(\"capacity\", \"owner-registrations\");\n const assigned = { ...record, ordinal: yield* nextSequence() };\n const json = yield* encode(SubscriptionRecord, assigned, \"encode registration\");\n\n yield* failpoint.hit(\"subscription:register:before\");\n yield* query(\n sql<Record<string, unknown>>`\n INSERT INTO effect_agent_subscriptions (tenant_id, source_address, owner_id, subscription_id, ordinal,\n source_name, source_version, matching_key, state, expires_at_millis, recovery_at_millis, record_json)\n VALUES (${partition.tenantId}, ${partition.address}, ${assigned.key.ownerId}, ${assigned.key.subscriptionId}, ${assigned.ordinal},\n ${assigned.configuration.source.name}, ${assigned.configuration.source.version}, ${assigned.configuration.matchingKey}, ${assigned.state},\n ${assigned.configuration.expiresAtMillis}, ${assigned.recovery?.nextAttemptAtMillis ?? null}, ${json})\n `,\n \"insert registration\",\n );\n\n return { value: assigned, changed: true } as const;\n }),\n );\n\n if (result.changed) yield* failpoint.hit(\"subscription:register:after\");\n\n return result.value;\n });\n\n const get: SubscriptionStore[\"Service\"][\"get\"] = Effect.fn(\"SqliteSubscriptionStore.get\")(\n function* (input) {\n return yield* readRegistration(yield* requireKey(input, \"get-key\"), \"get subscription\");\n },\n );\n\n const list: SubscriptionStore[\"Service\"][\"list\"] = Effect.fn(\"SqliteSubscriptionStore.list\")(\n function* (ownerId, after, limit) {\n const rows = yield* query(\n sql<Record<string, unknown>>`\n SELECT owner_id, subscription_id, ordinal FROM effect_agent_subscriptions WHERE tenant_id=${partition.tenantId} AND source_address=${partition.address}\n AND owner_id=${ownerId} AND ordinal>${after} ORDER BY ordinal LIMIT ${limit}\n `,\n \"list subscriptions\",\n );\n\n const decoded = yield* decodeRows(\n Schema.Struct({\n owner_id: Schema.String,\n subscription_id: Schema.String,\n ordinal: Schema.Natural,\n }),\n rows,\n \"list subscriptions\",\n );\n\n return yield* Effect.forEach(\n decoded,\n Effect.fn(\"SqliteSubscriptionStore.listRecord\")(function* (row) {\n const record = yield* readRegistration(\n { partition, ownerId: row.owner_id, subscriptionId: row.subscription_id },\n \"list subscription\",\n );\n\n if (record === null || record.ordinal !== row.ordinal)\n return yield* corrupt(\"list subscription projection\");\n\n return record;\n }),\n );\n },\n );\n\n const cancel: SubscriptionStore[\"Service\"][\"cancel\"] = Effect.fn(\n \"SqliteSubscriptionStore.cancel\",\n )(function* (input) {\n const key = yield* requireKey(input, \"cancel-key\");\n\n const result = yield* transact(\n Effect.gen(function* () {\n const current = yield* readRegistration(key, \"cancel subscription\");\n\n if (current === null) return yield* error(\"not-found\", \"subscription\");\n if (current.state === \"cancelled\") return { value: current, changed: false } as const;\n const updated = { ...current, state: \"cancelled\" as const, recovery: null };\n\n yield* failpoint.hit(\"subscription:cancel:before\");\n yield* writeRegistration(updated);\n\n return { value: updated, changed: true } as const;\n }),\n );\n\n if (result.changed) yield* failpoint.hit(\"subscription:cancel:after\");\n\n return result.value;\n });\n\n const accept: SubscriptionStore[\"Service\"][\"accept\"] = Effect.fn(\n \"SqliteSubscriptionStore.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.partition, \"accept-partition\");\n\n const result = yield* transact(\n Effect.gen(function* () {\n const existing = yield* readEvent(event.eventId, \"accept event\");\n\n if (existing !== null) {\n if (!sameAcceptedEventIdentity(existing, event))\n return yield* error(\"conflict\", \"event-identity\");\n\n return { value: existing, changed: false } as const;\n }\n if (bytes(event.payload) > limits.maxPayloadBytes)\n return yield* error(\"capacity\", \"payload-bytes\");\n if (\n (yield* count(\n sql<\n Record<string, unknown>\n >`SELECT COUNT(*) AS count FROM effect_agent_subscription_events WHERE tenant_id=${partition.tenantId} AND source_address=${partition.address}`,\n \"count events\",\n )) >= limits.maxEvents\n )\n return yield* error(\"capacity\", \"events\");\n\n const accepted: AcceptedEvent = {\n ...event,\n cutoff: yield* nextSequence(),\n cursor: 0,\n routingComplete: false,\n routingFailure: null,\n };\n\n const json = yield* encode(AcceptedEvent, accepted, \"encode accepted event\");\n\n yield* failpoint.hit(\"subscription:accept:before\");\n yield* query(\n sql<Record<string, unknown>>`\n INSERT INTO effect_agent_subscription_events (tenant_id, source_address, event_id, source_name, source_version,\n matching_key, payload_digest, cutoff, cursor, routing_complete, next_attempt_at_millis, record_json)\n VALUES (${partition.tenantId}, ${partition.address}, ${accepted.eventId}, ${accepted.source.name}, ${accepted.source.version},\n ${accepted.matchingKey}, ${accepted.payloadDigest}, ${accepted.cutoff}, ${accepted.cursor}, 0, ${accepted.nextAttemptAtMillis}, ${json})\n `,\n \"insert event\",\n );\n\n return { value: accepted, changed: true } as const;\n }),\n );\n\n if (result.changed) yield* failpoint.hit(\"subscription:accept:after\");\n\n return result.value;\n });\n\n const event: SubscriptionStore[\"Service\"][\"event\"] = Effect.fn(\"SqliteSubscriptionStore.event\")(\n (eventId) => readEvent(eventId, \"get event\"),\n );\n\n const pendingEvents: SubscriptionStore[\"Service\"][\"pendingEvents\"] = Effect.fn(\n \"SqliteSubscriptionStore.pendingEvents\",\n )(function* (nowMillis, after, limit) {\n const rows = yield* query(\n sql<Record<string, unknown>>`\n SELECT event_id FROM effect_agent_subscription_events WHERE tenant_id=${partition.tenantId} AND source_address=${partition.address}\n AND routing_complete=0 AND next_attempt_at_millis<=${nowMillis} AND event_id>${after} ORDER BY event_id LIMIT ${limit}\n `,\n \"pending events\",\n );\n\n return yield* decodeRows(\n Schema.Struct({ event_id: Schema.String }),\n rows,\n \"pending event keys\",\n ).pipe(Effect.map((items) => items.map((item) => item.event_id)));\n });\n\n const candidates: SubscriptionStore[\"Service\"][\"candidates\"] = Effect.fn(\n \"SqliteSubscriptionStore.candidates\",\n )(function* (input, limit) {\n const supplied = yield* validate(AcceptedEvent, input, \"candidates-event\");\n\n yield* requirePartition(supplied.partition, \"candidates-partition\");\n const stored = yield* readEvent(supplied.eventId, \"candidates event\");\n\n if (stored === null) return yield* error(\"not-found\", \"event\");\n if (!sameAcceptedEventIdentity(stored, supplied)) return yield* error(\"conflict\", \"event\");\n\n const rows = yield* query(\n sql<Record<string, unknown>>`\n SELECT owner_id, subscription_id, ordinal FROM effect_agent_subscriptions WHERE tenant_id=${partition.tenantId} AND source_address=${partition.address}\n AND source_name=${stored.source.name} AND source_version=${stored.source.version} AND matching_key=${stored.matchingKey}\n AND ordinal>${stored.cursor} AND ordinal<=${stored.cutoff} ORDER BY ordinal LIMIT ${limit}\n `,\n \"subscription candidates\",\n );\n\n const decoded = yield* decodeRows(\n Schema.Struct({\n owner_id: Schema.String,\n subscription_id: Schema.String,\n ordinal: Schema.Natural,\n }),\n rows,\n \"subscription candidates\",\n );\n\n return yield* Effect.forEach(\n decoded,\n Effect.fn(\"SqliteSubscriptionStore.candidateRecord\")(function* (row) {\n const record = yield* readRegistration(\n { partition, ownerId: row.owner_id, subscriptionId: row.subscription_id },\n \"subscription candidate\",\n );\n\n if (record === null || record.ordinal !== row.ordinal)\n return yield* corrupt(\"subscription candidate projection\");\n\n return record;\n }),\n );\n });\n\n const insertDelivery = Effect.fn(\"SqliteSubscriptionStore.insertDelivery\")(function* (\n delivery: SubscriptionDelivery,\n ) {\n const json = yield* encode(SubscriptionDelivery, delivery, \"encode selected delivery\");\n\n yield* query(\n sql<Record<string, unknown>>`\n INSERT INTO effect_agent_subscription_deliveries (tenant_id, source_address, owner_id, subscription_id, event_id,\n delivery_key, state, next_attempt_at_millis, record_json)\n VALUES (${partition.tenantId}, ${partition.address}, ${delivery.key.subscription.ownerId}, ${delivery.key.subscription.subscriptionId},\n ${delivery.key.eventId}, ${subscriptionDeliveryKeyString(delivery.key)}, ${delivery.state}, ${delivery.retry.nextAttemptAtMillis}, ${json})\n `,\n \"insert delivery\",\n );\n });\n\n const select: SubscriptionStore[\"Service\"][\"select\"] = Effect.fn(\n \"SqliteSubscriptionStore.select\",\n )(function* (inputEvent, inputDeliveries, cursor, complete, nowMillis, inputLimits) {\n const supplied = 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(supplied.partition, \"select-partition\");\n for (const candidate of deliveries)\n yield* requirePartition(candidate.key.subscription.partition, \"select-delivery-partition\");\n\n const changed = yield* transact(\n Effect.gen(function* () {\n const accepted = yield* readEvent(supplied.eventId, \"select event\");\n\n if (accepted === null) return yield* error(\"not-found\", \"event\");\n if (!sameAcceptedEventIdentity(accepted, supplied) || accepted.cursor !== supplied.cursor)\n return yield* error(\"conflict\", \"event-cursor\");\n if (accepted.routingComplete) return false;\n if (!Number.isSafeInteger(cursor) || cursor < accepted.cursor || cursor > accepted.cutoff)\n return yield* error(\"validation\", \"cursor\");\n yield* failpoint.hit(\"subscription:select:before\");\n const effectiveNowMillis = Math.max(nowMillis, yield* Clock.currentTimeMillis);\n const additions: Array<{ delivery: SubscriptionDelivery; record: SubscriptionRecord }> = [];\n\n for (const delivery of deliveries) {\n const record = yield* readRegistration(delivery.key.subscription, \"select registration\");\n\n if (record === null) return yield* error(\"not-found\", \"subscription\");\n if (\n !subscriptionDeliveryCanSelect(delivery, record, accepted) ||\n delivery.key.eventId !== accepted.eventId ||\n delivery.source.name !== accepted.source.name ||\n delivery.source.version !== accepted.source.version ||\n record.ordinal <= accepted.cursor ||\n record.ordinal > cursor\n )\n return yield* error(\"conflict\", \"selection\");\n const existing = yield* readDelivery(delivery.key, \"select existing delivery\");\n\n if (existing !== null) {\n if (!sameDeliveryIdentity(existing, delivery))\n return yield* error(\"conflict\", \"delivery-identity\");\n continue;\n }\n if (!subscriptionCanSelect(record, accepted, effectiveNowMillis, false)) continue;\n additions.push({ delivery, record });\n }\n\n const total = yield* count(\n sql<\n Record<string, unknown>\n >`SELECT COUNT(*) AS count FROM effect_agent_subscription_deliveries WHERE tenant_id=${partition.tenantId} AND source_address=${partition.address}`,\n \"count deliveries\",\n );\n\n if (total + additions.length > limits.maxDeliveries)\n return yield* error(\"capacity\", \"deliveries\");\n for (const ownerId of new Set(additions.map(({ record }) => record.key.ownerId))) {\n const existing = yield* count(\n sql<\n Record<string, unknown>\n >`SELECT COUNT(*) AS count FROM effect_agent_subscription_deliveries WHERE tenant_id=${partition.tenantId} AND source_address=${partition.address} AND owner_id=${ownerId}`,\n \"count owner deliveries\",\n );\n\n if (\n existing + additions.filter(({ record }) => record.key.ownerId === ownerId).length >\n limits.maxDeliveriesPerOwner\n )\n return yield* error(\"capacity\", \"owner-deliveries\");\n }\n for (const addition of additions) {\n yield* insertDelivery(addition.delivery);\n if (addition.record.configuration.mode === \"once\")\n yield* writeRegistration({ ...addition.record, state: \"consumed\", recovery: null });\n }\n yield* writeEvent({ ...accepted, cursor, routingComplete: complete, routingFailure: null });\n\n return true;\n }),\n );\n\n if (changed) yield* failpoint.hit(\"subscription:select:after\");\n });\n\n const catchUp: SubscriptionStore[\"Service\"][\"catchUp\"] = Effect.fn(\n \"SqliteSubscriptionStore.catchUp\",\n )(function* (inputEvent, inputDelivery, nowMillis, inputLimits) {\n const supplied = 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(supplied.partition, \"catch-up-partition\");\n yield* requirePartition(delivery.key.subscription.partition, \"catch-up-delivery-partition\");\n\n const changed = yield* transact(\n Effect.gen(function* () {\n const accepted = yield* readEvent(supplied.eventId, \"catch-up event\");\n const record = yield* readRegistration(delivery.key.subscription, \"catch-up subscription\");\n\n if (accepted === null || record === null)\n return yield* error(\"not-found\", accepted === null ? \"event\" : \"subscription\");\n if (\n !sameAcceptedEventIdentity(accepted, supplied) ||\n !subscriptionDeliveryCanSelect(delivery, record, accepted) ||\n delivery.key.eventId !== accepted.eventId ||\n delivery.source.name !== accepted.source.name ||\n delivery.source.version !== accepted.source.version ||\n record.configuration.mode !== \"once\"\n )\n return yield* error(\"conflict\", \"catch-up-identity\");\n const existing = yield* readDelivery(delivery.key, \"catch-up existing delivery\");\n\n if (existing !== null) {\n if (!sameDeliveryIdentity(existing, delivery))\n return yield* error(\"conflict\", \"delivery-identity\");\n\n return false;\n }\n yield* failpoint.hit(\"subscription:catch-up:before\");\n const effectiveNowMillis = Math.max(nowMillis, yield* Clock.currentTimeMillis);\n\n if (!subscriptionCanSelect(record, accepted, effectiveNowMillis, true))\n return yield* error(\"conflict\", \"catch-up-eligibility\");\n if (\n (yield* count(\n sql<\n Record<string, unknown>\n >`SELECT COUNT(*) AS count FROM effect_agent_subscription_deliveries WHERE tenant_id=${partition.tenantId} AND source_address=${partition.address}`,\n \"count deliveries\",\n )) >= limits.maxDeliveries\n )\n return yield* error(\"capacity\", \"deliveries\");\n if (\n (yield* count(\n sql<\n Record<string, unknown>\n >`SELECT COUNT(*) AS count FROM effect_agent_subscription_deliveries WHERE tenant_id=${partition.tenantId} AND source_address=${partition.address} AND owner_id=${record.key.ownerId}`,\n \"count owner deliveries\",\n )) >= limits.maxDeliveriesPerOwner\n )\n return yield* error(\"capacity\", \"owner-deliveries\");\n yield* insertDelivery(delivery);\n yield* writeRegistration({ ...record, state: \"consumed\", recovery: null });\n\n return true;\n }),\n );\n\n if (changed) yield* failpoint.hit(\"subscription:catch-up:after\");\n });\n\n const deferEvent: SubscriptionStore[\"Service\"][\"deferEvent\"] = Effect.fn(\n \"SqliteSubscriptionStore.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* transact(\n Effect.gen(function* () {\n const accepted = yield* readEvent(eventId, \"defer event\");\n\n if (accepted === null) return yield* error(\"not-found\", \"event\");\n yield* failpoint.hit(\"subscription:defer-event:before\");\n yield* writeEvent({ ...accepted, nextAttemptAtMillis, routingFailure });\n }),\n );\n yield* failpoint.hit(\"subscription:defer-event:after\");\n });\n\n const delivery: SubscriptionStore[\"Service\"][\"delivery\"] = Effect.fn(\n \"SqliteSubscriptionStore.delivery\",\n )(function* (input) {\n const key = yield* validate(SubscriptionDeliveryKey, input, \"delivery-key\");\n\n yield* requirePartition(key.subscription.partition, \"delivery-partition\");\n\n return yield* readDelivery(key, \"get delivery\");\n });\n\n const pendingDeliveries: SubscriptionStore[\"Service\"][\"pendingDeliveries\"] = Effect.fn(\n \"SqliteSubscriptionStore.pendingDeliveries\",\n )(function* (nowMillis, after, limit) {\n const rows = yield* query(\n sql<Record<string, unknown>>`\n SELECT owner_id, subscription_id, event_id FROM effect_agent_subscription_deliveries\n WHERE tenant_id=${partition.tenantId} AND source_address=${partition.address} AND state NOT IN ('delivered','refused')\n AND next_attempt_at_millis<=${nowMillis} AND delivery_key>${after} ORDER BY delivery_key LIMIT ${limit}\n `,\n \"pending deliveries\",\n );\n\n const rowSchema = Schema.Struct({\n owner_id: Schema.String,\n subscription_id: Schema.String,\n event_id: Schema.String,\n });\n\n return yield* decodeRows(rowSchema, rows, \"pending delivery keys\").pipe(\n Effect.map((items) =>\n items.map((item) => ({\n subscription: { partition, ownerId: item.owner_id, subscriptionId: item.subscription_id },\n eventId: item.event_id,\n })),\n ),\n );\n });\n\n const listDeliveries: SubscriptionStore[\"Service\"][\"listDeliveries\"] = Effect.fn(\n \"SqliteSubscriptionStore.listDeliveries\",\n )(function* (input, after, limit) {\n const key = yield* requireKey(input, \"list-deliveries-key\");\n\n const rows = yield* query(\n sql<Record<string, unknown>>`\n SELECT record_json FROM effect_agent_subscription_deliveries WHERE tenant_id=${partition.tenantId} AND source_address=${partition.address}\n AND owner_id=${key.ownerId} AND subscription_id=${key.subscriptionId} AND delivery_key>${after} ORDER BY delivery_key LIMIT ${limit}\n `,\n \"list deliveries\",\n );\n\n const decoded = yield* decodeRows(JsonRow, rows, \"list deliveries\");\n\n return yield* Effect.forEach(decoded, (row) =>\n decode(SubscriptionDelivery, row.record_json, \"list delivery\"),\n );\n });\n\n const changeDelivery: SubscriptionStore[\"Service\"][\"changeDelivery\"] = Effect.fn(\n \"SqliteSubscriptionStore.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.partition, \"change-delivery-partition\");\n\n const result = yield* transact(\n Effect.gen(function* () {\n const existing = yield* readDelivery(key, \"change delivery\");\n const record = yield* readRegistration(key.subscription, \"change delivery subscription\");\n\n if (existing === null || record === null)\n return yield* error(\"not-found\", existing === null ? \"delivery\" : \"subscription\");\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 transition = applySubscriptionDeliveryChange(\n existing,\n record,\n deliveryId,\n effectiveChange,\n );\n\n if (Result.isFailure(transition)) return yield* transition.failure;\n if (transition.success === existing) return { value: existing, changed: false } as const;\n yield* writeDelivery(transition.success);\n\n return { value: transition.success, changed: true } as const;\n }),\n );\n\n if (result.changed)\n yield* failpoint.hit(`subscription:delivery-${change._tag.toLowerCase()}:after`);\n\n return result.value;\n });\n\n const recovering: SubscriptionStore[\"Service\"][\"recovering\"] = Effect.fn(\n \"SqliteSubscriptionStore.recovering\",\n )(function* (nowMillis, after, limit) {\n const rows = yield* query(\n sql<Record<string, unknown>>`\n SELECT owner_id, subscription_id, ordinal FROM effect_agent_subscriptions\n WHERE tenant_id=${partition.tenantId} AND source_address=${partition.address} AND state='active'\n AND recovery_at_millis IS NOT NULL AND recovery_at_millis<=${nowMillis} AND ordinal>${after}\n ORDER BY ordinal LIMIT ${limit}\n `,\n \"recovering subscriptions\",\n );\n\n const rowSchema = Schema.Struct({\n owner_id: Schema.String,\n subscription_id: Schema.String,\n ordinal: Schema.Natural,\n });\n\n return yield* decodeRows(rowSchema, rows, \"recovering subscription keys\").pipe(\n Effect.map((items) =>\n items.map((item) => ({\n key: { partition, ownerId: item.owner_id, subscriptionId: item.subscription_id },\n ordinal: item.ordinal,\n })),\n ),\n );\n });\n\n const deferRecovery: SubscriptionStore[\"Service\"][\"deferRecovery\"] = Effect.fn(\n \"SqliteSubscriptionStore.deferRecovery\",\n )(function* (input, recovery) {\n const key = yield* requireKey(input, \"defer-recovery-key\");\n\n yield* transact(\n Effect.gen(function* () {\n const record = yield* readRegistration(key, \"defer recovery\");\n\n if (record === null) return yield* error(\"not-found\", \"subscription\");\n yield* failpoint.hit(\"subscription:defer-recovery:before\");\n yield* writeRegistration({\n ...record,\n recovery: record.state === \"active\" ? recovery : null,\n });\n }),\n );\n yield* failpoint.hit(\"subscription:defer-recovery:after\");\n });\n\n const readScanCursors: SubscriptionStore[\"Service\"][\"readScanCursors\"] = Effect.gen(function* () {\n const rows = yield* query(\n sql<Record<string, unknown>>`\n SELECT event_scan_cursor, delivery_scan_cursor, recovery_scan_cursor\n FROM effect_agent_subscription_sequences\n WHERE tenant_id=${partition.tenantId} AND source_address=${partition.address}\n `,\n \"read subscription scan cursors\",\n );\n\n const decoded = yield* decodeRows(ScanRow, rows, \"read subscription scan cursors\");\n\n if (decoded.length !== 1) return yield* corrupt(\"subscription scan cursors\");\n\n return {\n events: decoded[0].event_scan_cursor,\n deliveries: decoded[0].delivery_scan_cursor,\n recovery: decoded[0].recovery_scan_cursor,\n };\n });\n\n const advanceScanCursors: SubscriptionStore[\"Service\"][\"advanceScanCursors\"] = Effect.fn(\n \"SqliteSubscriptionStore.advanceScanCursors\",\n )(function* (input) {\n const cursors = yield* validate(SubscriptionScanCursors, input, \"scan-cursors\");\n\n yield* transact(\n Effect.gen(function* () {\n yield* failpoint.hit(\"subscription:advance-scan-cursors:before\");\n yield* query(\n sql<Record<string, unknown>>`\n UPDATE effect_agent_subscription_sequences\n SET event_scan_cursor=${cursors.events}, delivery_scan_cursor=${cursors.deliveries}, recovery_scan_cursor=${cursors.recovery}\n WHERE tenant_id=${partition.tenantId} AND source_address=${partition.address}\n `,\n \"advance subscription scan cursors\",\n );\n }),\n );\n yield* failpoint.hit(\"subscription:advance-scan-cursors:after\");\n });\n\n const indexedDeadline = query(\n sql<Record<string, unknown>>`\n SELECT MIN(deadline) AS deadline FROM (\n SELECT next_attempt_at_millis AS deadline FROM effect_agent_subscription_events\n WHERE tenant_id=${partition.tenantId} AND source_address=${partition.address} AND routing_complete=0\n UNION ALL SELECT next_attempt_at_millis FROM effect_agent_subscription_deliveries\n WHERE tenant_id=${partition.tenantId} AND source_address=${partition.address} AND state NOT IN ('delivered','refused')\n UNION ALL SELECT recovery_at_millis FROM effect_agent_subscriptions\n WHERE tenant_id=${partition.tenantId} AND source_address=${partition.address} AND state='active' AND recovery_at_millis IS NOT NULL\n )\n `,\n \"next subscription deadline\",\n ).pipe(\n Effect.flatMap((rows) =>\n decodeRows(\n Schema.Struct({ deadline: Schema.NullOr(Schema.Number) }),\n rows,\n \"next subscription deadline\",\n ),\n ),\n Effect.flatMap((rows) =>\n rows.length === 1\n ? Effect.succeed(rows[0].deadline)\n : Effect.fail(corrupt(\"next subscription deadline\")),\n ),\n );\n\n const nextDeadline = Effect.gen(function* () {\n const cursors = yield* readScanCursors;\n\n if (cursors.events !== \"\" || cursors.deliveries !== \"\" || cursors.recovery !== 0) return 0;\n\n return yield* indexedDeadline;\n });\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 subscriptionStoreLayer = (\n partition: SourcePartition,\n): Layer.Layer<\n SubscriptionStore,\n SqliteStorageInitializationError | SubscriptionError,\n SqliteStorageConfig | SqliteStorageFailpoint | SqlClientService.SqlClient\n> => Layer.effect(SubscriptionStore, makeSubscriptionStore(partition));\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SqliteSubscriptionStore.mjs","names":[],"sources":["../src/SqliteSubscriptionStore.ts"],"sourcesContent":["import {\n makeSqlSubscriptionStore,\n SqlSubscriptionTransaction,\n} from \"@effect-agent/thread/SqlSubscriptionStore\";\nimport {\n SourcePartition,\n SubscriptionError,\n SubscriptionStore,\n} from \"@effect-agent/thread/Subscription\";\nimport { Effect, Layer, Schema } from \"effect\";\nimport * as SqlClientService from \"effect/unstable/sql/SqlClient\";\n\nimport { initializeSqliteJournal } from \"./internal/sqlite-journal.ts\";\nimport type { SqliteStorageConfig } from \"./SqliteStorageConfig.ts\";\nimport type { SqliteStorageFailpoint } from \"./SqliteStorageFailpoint.ts\";\nimport type { SqliteStorageInitializationError } from \"./SqliteThreadStore.ts\";\n\nconst transactionLayer = Layer.effect(\n SqlSubscriptionTransaction,\n Effect.gen(function* () {\n const sql = yield* SqlClientService.SqlClient;\n\n return SqlSubscriptionTransaction.of({\n run: (body) =>\n sql\n .withTransaction(body)\n .pipe(\n Effect.catchTag(\"SqlError\", () =>\n Effect.fail(SubscriptionError.make({ reason: \"storage\", code: \"transaction\" })),\n ),\n ),\n });\n }),\n);\n\nconst makeSubscriptionStore = Effect.fn(\"SqliteSubscriptionStore.make\")(function* (\n owned: SourcePartition,\n) {\n const partition = yield* Schema.decodeUnknownEffect(SourcePartition)(owned).pipe(\n Effect.mapError(() => SubscriptionError.make({ reason: \"validation\", code: \"partition\" })),\n );\n\n yield* initializeSqliteJournal();\n\n return yield* makeSqlSubscriptionStore(partition, {\n maxStoredJsonLength: 16 * 1024 * 1024,\n });\n});\n\nexport const subscriptionStoreLayer = (\n partition: SourcePartition,\n): Layer.Layer<\n SubscriptionStore,\n SqliteStorageInitializationError | SubscriptionError,\n SqliteStorageConfig | SqliteStorageFailpoint | SqlClientService.SqlClient\n> =>\n Layer.effect(SubscriptionStore, makeSubscriptionStore(partition)).pipe(\n Layer.provide(transactionLayer),\n );\n"],"mappings":";;;;;;;;AAiBA,MAAM,mBAAmB,MAAM,OAC7B,4BACA,OAAO,IAAI,aAAa;CACtB,MAAM,MAAM,OAAO,iBAAiB;CAEpC,OAAO,2BAA2B,GAAG,EACnC,MAAM,SACJ,IACG,gBAAgB,IAAI,CAAC,CACrB,KACC,OAAO,SAAS,kBACd,OAAO,KAAK,kBAAkB,KAAK;EAAE,QAAQ;EAAW,MAAM;CAAc,CAAC,CAAC,CAChF,CACF,EACN,CAAC;AACH,CAAC,CACH;AAEA,MAAM,wBAAwB,OAAO,GAAG,8BAA8B,CAAC,CAAC,WACtE,OACA;CACA,MAAM,YAAY,OAAO,OAAO,oBAAoB,eAAe,CAAC,CAAC,KAAK,CAAC,CAAC,KAC1E,OAAO,eAAe,kBAAkB,KAAK;EAAE,QAAQ;EAAc,MAAM;CAAY,CAAC,CAAC,CAC3F;CAEA,OAAO,wBAAwB;CAE/B,OAAO,OAAO,yBAAyB,WAAW,EAChD,qBAAqB,SACvB,CAAC;AACH,CAAC;AAED,MAAa,0BACX,cAMA,MAAM,OAAO,mBAAmB,sBAAsB,SAAS,CAAC,CAAC,CAAC,KAChE,MAAM,QAAQ,gBAAgB,CAChC"}
|
|
@@ -2,7 +2,7 @@ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
|
|
|
2
2
|
import { SqliteStorageConfig, SqliteStorageConfigValue } from "./SqliteStorageConfig.mjs";
|
|
3
3
|
import { SqliteAppendConflict, SqliteCheckpointConflict, SqliteFenceRejected, SqliteStorageCorruptionError, SqliteStorageError } from "./SqliteStorageError.mjs";
|
|
4
4
|
import { SqliteStorageFailpoint } from "./SqliteStorageFailpoint.mjs";
|
|
5
|
-
import { a as initializeSqliteJournal, n as RawCheckpoint, r as RawReadRequest, t as RawAppendRequest } from "./sqlite-journal-
|
|
5
|
+
import { a as initializeSqliteJournal, n as RawCheckpoint, r as RawReadRequest, t as RawAppendRequest } from "./sqlite-journal-BxBxOUEI.mjs";
|
|
6
6
|
import { CanonicalBatch, CanonicalRecord, CanonicalRecordEnvelope, CanonicalSequence, Digest, ObservationOffset } from "@effect-agent/thread/Records";
|
|
7
7
|
import { Clock, Context, Crypto, Duration, Effect, Layer, Option, Ref, Schema, Stream } from "effect";
|
|
8
8
|
import { SqliteClient } from "@effect/sql-sqlite-node";
|
|
@@ -79,8 +79,6 @@ var RawCheckpoint = class extends Schema.Class("@effect-agent/storage-sqlite/Raw
|
|
|
79
79
|
throughSequence: CanonicalSequence
|
|
80
80
|
}) {};
|
|
81
81
|
var RawThreadExport = class extends Schema.Class("@effect-agent/storage-sqlite/RawThreadExport")({
|
|
82
|
-
batches: Schema.Array(BatchRow),
|
|
83
|
-
checkpoints: Schema.Array(CheckpointRow),
|
|
84
82
|
thread: ThreadRow,
|
|
85
83
|
records: Schema.Array(RecordRow)
|
|
86
84
|
}) {};
|
|
@@ -458,19 +456,6 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
|
|
|
458
456
|
`.pipe(Effect.mapError(storageError("export thread")));
|
|
459
457
|
const thread = yield* decodeSingleRow(Schema.Array(ThreadRow), "effect_agent_threads", threadId, threadRows);
|
|
460
458
|
yield* failpoint("export:after-thread-read");
|
|
461
|
-
const batchRows = yield* sql`
|
|
462
|
-
SELECT
|
|
463
|
-
thread_id,
|
|
464
|
-
batch_id,
|
|
465
|
-
first_sequence,
|
|
466
|
-
last_sequence,
|
|
467
|
-
batch_digest,
|
|
468
|
-
tail_digest,
|
|
469
|
-
batch_json
|
|
470
|
-
FROM effect_agent_canonical_batches
|
|
471
|
-
WHERE thread_id = ${threadId}
|
|
472
|
-
ORDER BY first_sequence
|
|
473
|
-
`.pipe(Effect.mapError(storageError("export canonical batches")));
|
|
474
459
|
const recordRows = yield* sql`
|
|
475
460
|
SELECT
|
|
476
461
|
thread_id,
|
|
@@ -482,21 +467,9 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
|
|
|
482
467
|
WHERE thread_id = ${threadId}
|
|
483
468
|
ORDER BY sequence
|
|
484
469
|
`.pipe(Effect.mapError(storageError("export canonical records")));
|
|
485
|
-
const checkpointRows = yield* sql`
|
|
486
|
-
SELECT
|
|
487
|
-
thread_id,
|
|
488
|
-
through_sequence,
|
|
489
|
-
tail_digest,
|
|
490
|
-
checkpoint_json
|
|
491
|
-
FROM effect_agent_checkpoints
|
|
492
|
-
WHERE thread_id = ${threadId}
|
|
493
|
-
ORDER BY through_sequence
|
|
494
|
-
`.pipe(Effect.mapError(storageError("export checkpoints")));
|
|
495
470
|
return RawThreadExport.make({
|
|
496
471
|
thread,
|
|
497
|
-
|
|
498
|
-
records: yield* decodeRows(Schema.Array(RecordRow), "effect_agent_canonical_records", threadId, recordRows),
|
|
499
|
-
checkpoints: yield* decodeRows(Schema.Array(CheckpointRow), "effect_agent_checkpoints", threadId, checkpointRows)
|
|
472
|
+
records: yield* decodeRows(Schema.Array(RecordRow), "effect_agent_canonical_records", threadId, recordRows)
|
|
500
473
|
});
|
|
501
474
|
}));
|
|
502
475
|
});
|
|
@@ -653,4 +626,4 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
|
|
|
653
626
|
//#endregion
|
|
654
627
|
export { initializeSqliteJournal as a, decodeRows as i, RawCheckpoint as n, RawReadRequest as r, RawAppendRequest as t };
|
|
655
628
|
|
|
656
|
-
//# sourceMappingURL=sqlite-journal-
|
|
629
|
+
//# sourceMappingURL=sqlite-journal-BxBxOUEI.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite-journal-BxBxOUEI.mjs","names":[],"sources":["../src/internal/sqlite-journal.ts"],"sourcesContent":["import { CanonicalSequence, ProducerEpoch } from \"@effect-agent/thread/Records\";\nimport { SqliteMigrator } from \"@effect/sql-sqlite-node\";\nimport { Effect, Exit, Schema } from \"effect\";\nimport * as SqlClient from \"effect/unstable/sql/SqlClient\";\nimport type { SqlError } from \"effect/unstable/sql/SqlError\";\n\nimport { SqliteStorageConfig } from \"../SqliteStorageConfig.ts\";\nimport type { SqliteStorageFailpointError } from \"../SqliteStorageError.ts\";\nimport {\n SqliteAppendConflict,\n SqliteCheckpointConflict,\n SqliteFenceRejected,\n SqliteStorageCompatibilityError,\n SqliteStorageCorruptionError,\n SqliteStorageError,\n SqliteWriteContention,\n} from \"../SqliteStorageError.ts\";\nimport { SqliteStorageFailpoint } from \"../SqliteStorageFailpoint.ts\";\nimport { CurrentSqliteStorageVersion, sqliteMigrations } from \"./migrations.ts\";\n\nconst BoundedStoredText = Schema.String.check(Schema.isMaxLength(16 * 1024 * 1024));\nconst BoundedIdentifier = Schema.NonEmptyString.check(Schema.isMaxLength(1024));\nconst NonNegativeInt = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0));\nconst MAX_RECORDS_PER_THREAD = 65_536;\nconst MAX_STORED_TEXT_BYTES = 16 * 1024 * 1024;\nconst MAX_IDENTIFIER_LENGTH = 1_024;\n\nconst storedTextBytes = (value: string): number => new TextEncoder().encode(value).byteLength;\n\nclass SqliteVersionRow extends Schema.Class<SqliteVersionRow>(\"SqliteVersionRow\")({\n user_version: NonNegativeInt,\n}) {}\n\nclass SqliteJournalModeRow extends Schema.Class<SqliteJournalModeRow>(\"SqliteJournalModeRow\")({\n journal_mode: Schema.NonEmptyString.check(Schema.isMaxLength(32)),\n}) {}\n\nclass SqliteNameRow extends Schema.Class<SqliteNameRow>(\"SqliteNameRow\")({\n name: BoundedIdentifier,\n}) {}\n\nclass ThreadRow extends Schema.Class<ThreadRow>(\"ThreadRow\")({\n thread_id: BoundedIdentifier,\n created_at: Schema.NonEmptyString.check(Schema.isMaxLength(128)),\n producer_epoch: ProducerEpoch,\n tail_digest: BoundedStoredText,\n tail_sequence: CanonicalSequence,\n}) {}\n\nclass BatchRow extends Schema.Class<BatchRow>(\"BatchRow\")({\n batch_digest: BoundedStoredText,\n batch_id: BoundedIdentifier,\n batch_json: BoundedStoredText,\n thread_id: BoundedIdentifier,\n first_sequence: CanonicalSequence,\n last_sequence: CanonicalSequence,\n tail_digest: BoundedStoredText,\n}) {}\n\nclass RecordRow extends Schema.Class<RecordRow>(\"RecordRow\")({\n batch_id: BoundedIdentifier,\n thread_id: BoundedIdentifier,\n record_id: BoundedIdentifier,\n record_json: BoundedStoredText,\n sequence: CanonicalSequence,\n}) {}\n\nclass CheckpointRow extends Schema.Class<CheckpointRow>(\"CheckpointRow\")({\n checkpoint_json: BoundedStoredText,\n thread_id: BoundedIdentifier,\n tail_digest: BoundedStoredText,\n through_sequence: CanonicalSequence,\n}) {}\n\nexport class RawRecord extends Schema.Class<RawRecord>(\"@effect-agent/storage-sqlite/RawRecord\")({\n recordId: BoundedIdentifier,\n recordJson: BoundedStoredText,\n}) {}\n\nexport class RawAppendRequest extends Schema.Class<RawAppendRequest>(\n \"@effect-agent/storage-sqlite/RawAppendRequest\",\n)({\n batchDigest: BoundedStoredText,\n batchId: BoundedIdentifier,\n batchJson: BoundedStoredText,\n threadId: BoundedIdentifier,\n expectedTailDigest: BoundedStoredText,\n expectedTailSequence: CanonicalSequence,\n producerEpoch: ProducerEpoch,\n records: Schema.NonEmptyArray(RawRecord).check(Schema.isMaxLength(256)),\n tailDigest: BoundedStoredText,\n}) {}\n\nexport class RawAppendResult extends Schema.Class<RawAppendResult>(\n \"@effect-agent/storage-sqlite/RawAppendResult\",\n)({\n firstSequence: CanonicalSequence,\n lastSequence: CanonicalSequence,\n replayed: Schema.Boolean,\n tailDigest: BoundedStoredText,\n}) {}\n\nexport class RawReadRequest extends Schema.Class<RawReadRequest>(\n \"@effect-agent/storage-sqlite/RawReadRequest\",\n)({\n threadId: BoundedIdentifier,\n fromSequenceExclusive: CanonicalSequence,\n limit: Schema.Int.check(Schema.isGreaterThan(0), Schema.isLessThanOrEqualTo(1_024)),\n}) {}\n\nexport class RawCheckpoint extends Schema.Class<RawCheckpoint>(\n \"@effect-agent/storage-sqlite/RawCheckpoint\",\n)({\n checkpointJson: BoundedStoredText,\n threadId: BoundedIdentifier,\n tailDigest: BoundedStoredText,\n throughSequence: CanonicalSequence,\n}) {}\n\nexport class RawThreadExport extends Schema.Class<RawThreadExport>(\n \"@effect-agent/storage-sqlite/RawThreadExport\",\n)({\n thread: ThreadRow,\n records: Schema.Array(RecordRow),\n}) {}\n\ntype AppendError =\n | SqliteAppendConflict\n | SqliteFenceRejected\n | SqliteStorageCorruptionError\n | SqliteStorageError\n | SqliteStorageFailpointError\n | SqliteWriteContention;\n\ntype CheckpointError =\n | SqliteCheckpointConflict\n | SqliteStorageCorruptionError\n | SqliteStorageError\n | SqliteWriteContention;\n\nconst storageError =\n (operation: string) =>\n (error: SqlError): SqliteStorageError =>\n SqliteStorageError.make({\n cause: error,\n operation,\n message: error.message,\n });\n\n/** Decode raw SQLite rows against a Schema, reporting failures as typed corruption. */\nexport const decodeRows = Effect.fn(\"SqliteJournal.decodeRows\")(\n <A, I>(\n schema: Schema.Codec<ReadonlyArray<A>, ReadonlyArray<I>>,\n table: string,\n rowKey: string,\n rows: unknown,\n ): Effect.Effect<ReadonlyArray<A>, SqliteStorageCorruptionError> =>\n Schema.decodeUnknownEffect(schema)(rows).pipe(\n Effect.mapError((error) =>\n SqliteStorageCorruptionError.make({\n table,\n rowKey,\n message: String(error),\n }),\n ),\n ),\n);\n\n/** Decode exactly one raw SQLite row against a Schema, reporting failures as typed corruption. */\nexport const decodeSingleRow = Effect.fn(\"SqliteJournal.decodeSingleRow\")(\n <A, I>(\n schema: Schema.Codec<ReadonlyArray<A>, ReadonlyArray<I>>,\n table: string,\n rowKey: string,\n rows: unknown,\n ): Effect.Effect<A, SqliteStorageCorruptionError> =>\n decodeRows(schema, table, rowKey, rows).pipe(\n Effect.flatMap((decoded) =>\n decoded.length === 1\n ? Effect.succeed(decoded[0])\n : Effect.fail(\n SqliteStorageCorruptionError.make({\n table,\n rowKey,\n message: `Expected exactly one row but found ${decoded.length}.`,\n }),\n ),\n ),\n ),\n);\n\nexport const initializeSqliteJournal = Effect.fn(\"SqliteJournal.initialize\")(function* () {\n const sql = yield* SqlClient.SqlClient;\n const { hit: failpoint } = yield* SqliteStorageFailpoint;\n const { busyTimeout } = yield* SqliteStorageConfig;\n\n yield* sql`PRAGMA foreign_keys = ON`.pipe(Effect.mapError(storageError(\"enable foreign keys\")));\n // PRAGMA statements do not accept bound parameters; the value is a schema-validated\n // non-negative integer, never caller-controlled text.\n yield* sql\n .unsafe(`PRAGMA busy_timeout = ${busyTimeout}`)\n .pipe(Effect.mapError(storageError(\"configure busy timeout\")));\n\n const journalModeRows = yield* sql<Record<string, unknown>>`PRAGMA journal_mode`.pipe(\n Effect.mapError(storageError(\"read journal mode\")),\n );\n\n const journalMode = yield* decodeSingleRow(\n Schema.Array(SqliteJournalModeRow),\n \"pragma_journal_mode\",\n \"singleton\",\n journalModeRows,\n );\n\n if (journalMode.journal_mode.toLowerCase() !== \"wal\") {\n return yield* SqliteStorageCompatibilityError.make({\n actualVersion: 0,\n supportedVersion: CurrentSqliteStorageVersion,\n message: `SQLite WAL mode is required; the database reported ${journalMode.journal_mode}.`,\n });\n }\n\n const versionRows = yield* sql<Record<string, unknown>>`PRAGMA user_version`.pipe(\n Effect.mapError(storageError(\"read storage version\")),\n );\n\n const version = yield* decodeSingleRow(\n Schema.Array(SqliteVersionRow),\n \"pragma_user_version\",\n \"singleton\",\n versionRows,\n );\n\n // D7: the storage version must match EXACTLY (or be 0 for a fresh file). Older\n // private-development versions fail closed with reset guidance rather than being\n // migrated, and newer versions fail closed rather than being decoded incorrectly.\n if (version.user_version !== 0 && version.user_version !== CurrentSqliteStorageVersion) {\n return yield* SqliteStorageCompatibilityError.make({\n actualVersion: version.user_version,\n supportedVersion: CurrentSqliteStorageVersion,\n message:\n `The SQLite file uses private-development storage version ${version.user_version}; ` +\n `this build supports exactly version ${CurrentSqliteStorageVersion}. ` +\n \"Reset the database file explicitly; automatic stored-data migrations are not provided during private development.\",\n });\n }\n\n if (version.user_version === 0) {\n const existingRows = yield* sql<Record<string, unknown>>`\n SELECT name\n FROM sqlite_master\n WHERE type = 'table'\n AND name LIKE 'effect_agent_%'\n ORDER BY name\n `.pipe(Effect.mapError(storageError(\"inspect unversioned storage\")));\n\n const existing = yield* decodeRows(\n Schema.Array(SqliteNameRow),\n \"sqlite_master\",\n \"effect_agent_%\",\n existingRows,\n );\n\n if (existing.length > 0) {\n return yield* SqliteStorageCompatibilityError.make({\n actualVersion: 0,\n supportedVersion: CurrentSqliteStorageVersion,\n message:\n \"The SQLite file contains unversioned Effect Agent tables. Reset it explicitly; refusing to mutate ambiguous stored data.\",\n });\n }\n\n yield* SqliteMigrator.run({ loader: sqliteMigrations }).pipe(\n Effect.mapError((error) =>\n SqliteStorageError.make({\n cause: error,\n operation: \"initialize current storage\",\n message: error.message,\n }),\n ),\n );\n }\n\n const requiredRows = yield* sql<Record<string, unknown>>`\n SELECT name\n FROM sqlite_master\n WHERE type = 'table'\n AND name IN (\n 'effect_agent_threads',\n 'effect_agent_canonical_batches',\n 'effect_agent_canonical_records',\n 'effect_agent_checkpoints',\n 'effect_agent_submissions',\n 'effect_agent_submission_ownership',\n 'effect_agent_attempts',\n 'effect_agent_settlement_reservations',\n 'effect_agent_abort_intents',\n 'effect_agent_approval_decisions',\n 'effect_agent_unknown_resolutions',\n 'effect_agent_schedules'\n )\n ORDER BY name\n `.pipe(Effect.mapError(storageError(\"verify storage tables\")));\n\n const required = yield* decodeRows(\n Schema.Array(SqliteNameRow),\n \"sqlite_master\",\n \"required_tables\",\n requiredRows,\n );\n\n if (required.length !== 12) {\n return yield* SqliteStorageCompatibilityError.make({\n actualVersion: CurrentSqliteStorageVersion,\n supportedVersion: CurrentSqliteStorageVersion,\n message:\n \"The SQLite file claims the current format but is missing required tables. Reset the corrupt private-development data.\",\n });\n }\n\n const classifyWriteFailure =\n (operation: string) =>\n (error: SqlError): SqliteStorageError | SqliteWriteContention =>\n error.reason._tag === \"LockTimeoutError\"\n ? SqliteWriteContention.make({\n cause: error,\n operation,\n message: `Another producer holds the SQLite write lock; ${operation} is safe to retry.`,\n })\n : storageError(operation)(error);\n\n /**\n * Runs one journal write transaction under `BEGIN IMMEDIATE`. SQLite's deferred `BEGIN`\n * would let a read-then-write transaction start as a reader and fail with\n * SQLITE_BUSY_SNAPSHOT on upgrade, which `busy_timeout` never retries. Taking the write\n * lock up front keeps cross-owner contention inside the bounded busy retry; a lock\n * timeout is classified as the retryable SqliteWriteContention. A failed `BEGIN` leaves\n * no transaction, so no rollback is attempted for it.\n *\n * Journal write transactions are always top level. Nesting one inside another would\n * deadlock the single-connection client, so new journal operations must not wrap this\n * helper inside another transaction.\n */\n const withWriteTransaction =\n (operation: string) =>\n <A, E>(\n effect: Effect.Effect<A, E>,\n ): Effect.Effect<A, E | SqliteStorageError | SqliteWriteContention> =>\n Effect.uninterruptibleMask((restore) =>\n Effect.scoped(\n Effect.gen(function* () {\n const connection = yield* sql.reserve.pipe(\n Effect.mapError(classifyWriteFailure(operation)),\n );\n\n yield* connection\n .executeUnprepared(\"BEGIN IMMEDIATE\", [], undefined)\n .pipe(Effect.mapError(classifyWriteFailure(operation)));\n\n const exit = yield* restore(\n Effect.provideService(effect, sql.transactionService, [connection, 0] as const),\n ).pipe(Effect.exit);\n\n if (Exit.isSuccess(exit)) {\n yield* connection\n .executeUnprepared(\"COMMIT\", [], undefined)\n .pipe(Effect.mapError(classifyWriteFailure(operation)));\n\n return exit.value;\n }\n yield* Effect.orDie(connection.executeUnprepared(\"ROLLBACK\", [], undefined));\n\n return yield* exit;\n }),\n ).pipe(\n Effect.withSpan(\"SqliteJournal.withWriteTransaction\", { attributes: { operation } }),\n ),\n );\n\n /**\n * Runs a read-only snapshot under a deferred transaction. Effect's SQLite client now\n * starts every writable-client `withTransaction` with `BEGIN IMMEDIATE`, which is the\n * right default for mutations but would make exports take the write lock and block a\n * concurrent append. Reserving the connection and beginning explicitly preserves the\n * adapter's snapshot-with-concurrent-writer contract. As with the write helper, a failed\n * `BEGIN` is reported directly because there is no transaction to roll back.\n */\n const withReadTransaction =\n (operation: string) =>\n <A, E>(effect: Effect.Effect<A, E>): Effect.Effect<A, E | SqliteStorageError> =>\n Effect.uninterruptibleMask((restore) =>\n Effect.scoped(\n Effect.gen(function* () {\n const connection = yield* sql.reserve.pipe(Effect.mapError(storageError(operation)));\n\n yield* connection\n .executeUnprepared(\"BEGIN\", [], undefined)\n .pipe(Effect.mapError(storageError(operation)));\n\n const exit = yield* restore(\n Effect.provideService(effect, sql.transactionService, [connection, 0] as const),\n ).pipe(Effect.exit);\n\n if (Exit.isSuccess(exit)) {\n yield* connection\n .executeUnprepared(\"COMMIT\", [], undefined)\n .pipe(Effect.mapError(storageError(operation)));\n\n return exit.value;\n }\n yield* Effect.orDie(connection.executeUnprepared(\"ROLLBACK\", [], undefined));\n\n return yield* exit;\n }),\n ).pipe(Effect.withSpan(\"SqliteJournal.withReadTransaction\", { attributes: { operation } })),\n );\n\n const materialize = Effect.fn(\"SqliteJournal.materialize\")(function* (\n threadId: string,\n createdAt: string,\n emptyTailDigest: string,\n producerEpoch: ProducerEpoch,\n ): Effect.fn.Return<\n void,\n SqliteFenceRejected | SqliteStorageCorruptionError | SqliteStorageError | SqliteWriteContention\n > {\n if (\n threadId.length > MAX_IDENTIFIER_LENGTH ||\n storedTextBytes(emptyTailDigest) > MAX_STORED_TEXT_BYTES\n ) {\n return yield* SqliteStorageError.make({\n operation: \"materialize thread\",\n message: \"Thread identity or initial digest exceeds the SQLite storage bounds.\",\n });\n }\n yield* withWriteTransaction(\"materialize transaction\")(\n Effect.gen(function* () {\n const existingRows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n created_at,\n tail_sequence,\n tail_digest,\n producer_epoch\n FROM effect_agent_threads\n WHERE thread_id = ${threadId}\n `.pipe(Effect.mapError(storageError(\"read materialized thread\")));\n\n const existing = yield* decodeRows(\n Schema.Array(ThreadRow),\n \"effect_agent_threads\",\n threadId,\n existingRows,\n );\n\n if (existing.length > 1) {\n return yield* SqliteStorageCorruptionError.make({\n table: \"effect_agent_threads\",\n rowKey: threadId,\n message: \"A thread primary key returned more than one row.\",\n });\n }\n if (existing.length === 0) {\n yield* sql`\n INSERT INTO effect_agent_threads (\n thread_id,\n created_at,\n tail_sequence,\n tail_digest,\n producer_epoch\n ) VALUES (\n ${threadId},\n ${createdAt},\n 0,\n ${emptyTailDigest},\n ${producerEpoch}\n )\n `.pipe(Effect.mapError(storageError(\"materialize thread\")));\n\n return;\n }\n if (producerEpoch < existing[0].producer_epoch) {\n return yield* SqliteFenceRejected.make({\n producerEpoch,\n actualEpoch: existing[0].producer_epoch,\n message: `Producer epoch ${producerEpoch} is stale; current epoch is ${existing[0].producer_epoch}.`,\n });\n }\n if (producerEpoch > existing[0].producer_epoch) {\n yield* sql`\n UPDATE effect_agent_threads\n SET producer_epoch = ${producerEpoch}\n WHERE thread_id = ${threadId}\n `.pipe(Effect.mapError(storageError(\"advance materialization epoch\")));\n }\n }),\n );\n });\n\n const getThread = Effect.fn(\"SqliteJournal.getThread\")(function* (threadId: string) {\n const rows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n created_at,\n tail_sequence,\n tail_digest,\n producer_epoch\n FROM effect_agent_threads\n WHERE thread_id = ${threadId}\n `.pipe(Effect.mapError(storageError(\"read thread\")));\n\n return yield* decodeRows(Schema.Array(ThreadRow), \"effect_agent_threads\", threadId, rows);\n });\n\n const append = Effect.fn(\"SqliteJournal.append\")(function* (\n request: RawAppendRequest,\n ): Effect.fn.Return<RawAppendResult, AppendError> {\n if (\n request.threadId.length > MAX_IDENTIFIER_LENGTH ||\n request.batchId.length > MAX_IDENTIFIER_LENGTH ||\n storedTextBytes(request.batchJson) > MAX_STORED_TEXT_BYTES ||\n storedTextBytes(request.batchDigest) > MAX_STORED_TEXT_BYTES ||\n storedTextBytes(request.tailDigest) > MAX_STORED_TEXT_BYTES ||\n request.records.some(\n (record) =>\n record.recordId.length > MAX_IDENTIFIER_LENGTH ||\n storedTextBytes(record.recordJson) > MAX_STORED_TEXT_BYTES,\n )\n ) {\n return yield* SqliteStorageError.make({\n operation: \"append canonical batch\",\n message: \"Canonical identifiers or encoded JSON exceed the SQLite storage bounds.\",\n });\n }\n\n return yield* withWriteTransaction(\"append transaction\")(\n Effect.gen(function* () {\n const recordIds = request.records.map((record) => record.recordId);\n\n if (new Set(recordIds).size !== recordIds.length) {\n return yield* SqliteAppendConflict.make({\n message: `Batch ${request.batchId} contains duplicate canonical record IDs.`,\n reason: \"record-identity\",\n });\n }\n\n const threadRows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n created_at,\n tail_sequence,\n tail_digest,\n producer_epoch\n FROM effect_agent_threads\n WHERE thread_id = ${request.threadId}\n `.pipe(Effect.mapError(storageError(\"read append tail\")));\n\n const thread = yield* decodeSingleRow(\n Schema.Array(ThreadRow),\n \"effect_agent_threads\",\n request.threadId,\n threadRows,\n );\n\n if (request.producerEpoch !== thread.producer_epoch) {\n return yield* SqliteFenceRejected.make({\n producerEpoch: request.producerEpoch,\n actualEpoch: thread.producer_epoch,\n message: `Producer epoch ${request.producerEpoch} is not the current epoch ${thread.producer_epoch}.`,\n });\n }\n\n const batchRows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n batch_id,\n first_sequence,\n last_sequence,\n batch_digest,\n tail_digest,\n batch_json\n FROM effect_agent_canonical_batches\n WHERE thread_id = ${request.threadId}\n AND batch_id = ${request.batchId}\n `.pipe(Effect.mapError(storageError(\"read idempotent batch\")));\n\n const batches = yield* decodeRows(\n Schema.Array(BatchRow),\n \"effect_agent_canonical_batches\",\n `${request.threadId}/${request.batchId}`,\n batchRows,\n );\n\n if (batches.length > 1) {\n return yield* SqliteStorageCorruptionError.make({\n table: \"effect_agent_canonical_batches\",\n rowKey: `${request.threadId}/${request.batchId}`,\n message: \"A canonical batch primary key returned more than one row.\",\n });\n }\n if (batches.length === 1) {\n const existing = batches[0];\n\n if (existing.batch_digest !== request.batchDigest) {\n return yield* SqliteAppendConflict.make({\n message: `Batch ${request.batchId} already exists with different canonical content.`,\n reason: \"batch-digest\",\n });\n }\n\n return RawAppendResult.make({\n firstSequence: existing.first_sequence,\n lastSequence: existing.last_sequence,\n replayed: true,\n tailDigest: existing.tail_digest,\n });\n }\n\n if (\n request.expectedTailSequence !== thread.tail_sequence ||\n request.expectedTailDigest !== thread.tail_digest\n ) {\n return yield* SqliteAppendConflict.make({\n message:\n `Expected tail ${request.expectedTailSequence}/${request.expectedTailDigest} ` +\n `but found ${thread.tail_sequence}/${thread.tail_digest}.`,\n reason: \"tail\",\n actualTailSequence: thread.tail_sequence,\n actualTailDigest: thread.tail_digest,\n });\n }\n if (thread.tail_sequence + request.records.length > MAX_RECORDS_PER_THREAD) {\n return yield* SqliteStorageError.make({\n operation: \"append canonical batch\",\n message: `Thread record limit ${MAX_RECORDS_PER_THREAD} would be exceeded.`,\n });\n }\n\n const existingRecordRows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n sequence,\n record_id,\n batch_id,\n record_json\n FROM effect_agent_canonical_records\n WHERE thread_id = ${request.threadId}\n AND record_id IN ${sql.in(recordIds)}\n ORDER BY sequence\n `.pipe(Effect.mapError(storageError(\"check canonical record identities\")));\n\n const existingRecords = yield* decodeRows(\n Schema.Array(RecordRow),\n \"effect_agent_canonical_records\",\n `${request.threadId}/record_ids`,\n existingRecordRows,\n );\n\n if (existingRecords.length > 0) {\n return yield* SqliteAppendConflict.make({\n message: `Canonical record ID ${existingRecords[0].record_id} already exists.`,\n reason: \"record-identity\",\n });\n }\n\n const firstSequence = yield* Schema.decodeUnknownEffect(CanonicalSequence)(\n thread.tail_sequence + 1,\n ).pipe(\n Effect.mapError((error) =>\n SqliteStorageError.make({\n cause: error,\n operation: \"append canonical batch\",\n message: error.message,\n }),\n ),\n );\n\n const lastSequence = yield* Schema.decodeUnknownEffect(CanonicalSequence)(\n firstSequence + request.records.length - 1,\n ).pipe(\n Effect.mapError((error) =>\n SqliteStorageError.make({\n cause: error,\n operation: \"append canonical batch\",\n message: error.message,\n }),\n ),\n );\n\n yield* sql`\n INSERT INTO effect_agent_canonical_batches (\n thread_id,\n batch_id,\n first_sequence,\n last_sequence,\n batch_digest,\n tail_digest,\n batch_json\n ) VALUES (\n ${request.threadId},\n ${request.batchId},\n ${firstSequence},\n ${lastSequence},\n ${request.batchDigest},\n ${request.tailDigest},\n ${request.batchJson}\n )\n `.pipe(Effect.mapError(storageError(\"insert canonical batch\")));\n yield* failpoint(\"append:after-batch-insert\");\n\n yield* Effect.forEach(\n request.records,\n (record, index) =>\n Effect.gen(function* () {\n yield* sql`\n INSERT INTO effect_agent_canonical_records (\n thread_id,\n sequence,\n record_id,\n batch_id,\n record_json\n ) VALUES (\n ${request.threadId},\n ${firstSequence + index},\n ${record.recordId},\n ${request.batchId},\n ${record.recordJson}\n )\n `.pipe(Effect.mapError(storageError(\"insert canonical record\")));\n yield* failpoint(\"append:after-record-insert\");\n }),\n { discard: true },\n );\n\n yield* sql`\n UPDATE effect_agent_threads\n SET\n tail_sequence = ${lastSequence},\n tail_digest = ${request.tailDigest},\n producer_epoch = ${request.producerEpoch}\n WHERE thread_id = ${request.threadId}\n `.pipe(Effect.mapError(storageError(\"advance thread tail\")));\n yield* failpoint(\"append:after-tail-update\");\n\n return RawAppendResult.make({\n firstSequence,\n lastSequence,\n replayed: false,\n tailDigest: request.tailDigest,\n });\n }),\n );\n });\n\n const read = Effect.fn(\"SqliteJournal.read\")(function* (request: RawReadRequest) {\n const rows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n sequence,\n record_id,\n batch_id,\n record_json\n FROM effect_agent_canonical_records\n WHERE thread_id = ${request.threadId}\n AND sequence > ${request.fromSequenceExclusive}\n ORDER BY sequence\n LIMIT ${request.limit}\n `.pipe(Effect.mapError(storageError(\"read canonical records\")));\n\n return yield* decodeRows(\n Schema.Array(RecordRow),\n \"effect_agent_canonical_records\",\n `${request.threadId}>${request.fromSequenceExclusive}`,\n rows,\n );\n });\n\n const exportThread = Effect.fn(\"SqliteJournal.exportThread\")(function* (threadId: string) {\n return yield* withReadTransaction(\"export transaction\")(\n Effect.gen(function* () {\n const threadRows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n created_at,\n tail_sequence,\n tail_digest,\n producer_epoch\n FROM effect_agent_threads\n WHERE thread_id = ${threadId}\n `.pipe(Effect.mapError(storageError(\"export thread\")));\n\n const thread = yield* decodeSingleRow(\n Schema.Array(ThreadRow),\n \"effect_agent_threads\",\n threadId,\n threadRows,\n );\n\n yield* failpoint(\"export:after-thread-read\");\n\n const recordRows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n sequence,\n record_id,\n batch_id,\n record_json\n FROM effect_agent_canonical_records\n WHERE thread_id = ${threadId}\n ORDER BY sequence\n `.pipe(Effect.mapError(storageError(\"export canonical records\")));\n\n return RawThreadExport.make({\n thread,\n records: yield* decodeRows(\n Schema.Array(RecordRow),\n \"effect_agent_canonical_records\",\n threadId,\n recordRows,\n ),\n });\n }),\n );\n });\n\n const saveCheckpoint = Effect.fn(\"SqliteJournal.saveCheckpoint\")(function* (\n checkpoint: RawCheckpoint,\n ): Effect.fn.Return<void, CheckpointError> {\n if (\n checkpoint.threadId.length > MAX_IDENTIFIER_LENGTH ||\n storedTextBytes(checkpoint.checkpointJson) > MAX_STORED_TEXT_BYTES\n ) {\n return yield* SqliteStorageError.make({\n operation: \"save checkpoint\",\n message: \"Checkpoint identity or encoded JSON exceeds the SQLite storage bounds.\",\n });\n }\n yield* withWriteTransaction(\"checkpoint transaction\")(\n Effect.gen(function* () {\n const threadRows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n created_at,\n tail_sequence,\n tail_digest,\n producer_epoch\n FROM effect_agent_threads\n WHERE thread_id = ${checkpoint.threadId}\n `.pipe(Effect.mapError(storageError(\"read checkpoint tail\")));\n\n const thread = yield* decodeSingleRow(\n Schema.Array(ThreadRow),\n \"effect_agent_threads\",\n checkpoint.threadId,\n threadRows,\n );\n\n if (checkpoint.throughSequence > thread.tail_sequence) {\n return yield* SqliteCheckpointConflict.make({\n message:\n `Checkpoint sequence ${checkpoint.throughSequence} is after canonical tail ` +\n `${thread.tail_sequence}.`,\n });\n }\n\n const checkpointRows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n through_sequence,\n tail_digest,\n checkpoint_json\n FROM effect_agent_checkpoints\n WHERE thread_id = ${checkpoint.threadId}\n AND through_sequence = ${checkpoint.throughSequence}\n `.pipe(Effect.mapError(storageError(\"read idempotent checkpoint\")));\n\n const existing = yield* decodeRows(\n Schema.Array(CheckpointRow),\n \"effect_agent_checkpoints\",\n `${checkpoint.threadId}/${checkpoint.throughSequence}`,\n checkpointRows,\n );\n\n if (existing.length > 1) {\n return yield* SqliteStorageCorruptionError.make({\n table: \"effect_agent_checkpoints\",\n rowKey: `${checkpoint.threadId}/${checkpoint.throughSequence}`,\n message: \"A checkpoint primary key returned more than one row.\",\n });\n }\n if (existing.length === 1) {\n if (\n existing[0].tail_digest !== checkpoint.tailDigest ||\n existing[0].checkpoint_json !== checkpoint.checkpointJson\n ) {\n return yield* SqliteCheckpointConflict.make({\n message: \"A different checkpoint already exists at this canonical sequence.\",\n });\n }\n\n return;\n }\n\n yield* sql`\n INSERT INTO effect_agent_checkpoints (\n thread_id,\n through_sequence,\n tail_digest,\n checkpoint_json\n ) VALUES (\n ${checkpoint.threadId},\n ${checkpoint.throughSequence},\n ${checkpoint.tailDigest},\n ${checkpoint.checkpointJson}\n )\n `.pipe(Effect.mapError(storageError(\"insert checkpoint\")));\n }),\n );\n });\n\n const loadCheckpoint = Effect.fn(\"SqliteJournal.loadCheckpoint\")(function* (\n threadId: string,\n atOrBeforeSequence: CanonicalSequence,\n ) {\n const rows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n through_sequence,\n tail_digest,\n checkpoint_json\n FROM effect_agent_checkpoints\n WHERE thread_id = ${threadId}\n AND through_sequence <= ${atOrBeforeSequence}\n ORDER BY through_sequence DESC\n LIMIT 1\n `.pipe(Effect.mapError(storageError(\"load checkpoint\")));\n\n return yield* decodeRows(\n Schema.Array(CheckpointRow),\n \"effect_agent_checkpoints\",\n `${threadId}<=${atOrBeforeSequence}`,\n rows,\n );\n });\n\n const getTailDigestAt = Effect.fn(\"SqliteJournal.getTailDigestAt\")(function* (\n threadId: string,\n sequence: CanonicalSequence,\n ) {\n if (sequence === 0) {\n const threads = yield* getThread(threadId);\n\n return threads.length === 0\n ? []\n : [threads[0].tail_sequence === 0 ? threads[0].tail_digest : undefined].filter(\n (value): value is string => value !== undefined,\n );\n }\n\n const rows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n batch_id,\n first_sequence,\n last_sequence,\n batch_digest,\n tail_digest,\n batch_json\n FROM effect_agent_canonical_batches\n WHERE thread_id = ${threadId}\n AND last_sequence = ${sequence}\n `.pipe(Effect.mapError(storageError(\"read canonical digest at sequence\")));\n\n const batches = yield* decodeRows(\n Schema.Array(BatchRow),\n \"effect_agent_canonical_batches\",\n `${threadId}/${sequence}`,\n rows,\n );\n\n return batches.map((batch) => batch.tail_digest);\n });\n\n const scanStoredPayloads = Effect.fn(\"SqliteJournal.scanStoredPayloads\")(function* () {\n return yield* withReadTransaction(\"startup scan transaction\")(\n Effect.gen(function* () {\n const threads = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n created_at,\n tail_sequence,\n tail_digest,\n producer_epoch\n FROM effect_agent_threads\n ORDER BY thread_id\n `.pipe(Effect.mapError(storageError(\"scan threads\")));\n\n const batches = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n batch_id,\n first_sequence,\n last_sequence,\n batch_digest,\n tail_digest,\n batch_json\n FROM effect_agent_canonical_batches\n ORDER BY thread_id, first_sequence\n `.pipe(Effect.mapError(storageError(\"scan canonical batches\")));\n\n const records = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n sequence,\n record_id,\n batch_id,\n record_json\n FROM effect_agent_canonical_records\n ORDER BY thread_id, sequence\n `.pipe(Effect.mapError(storageError(\"scan canonical records\")));\n\n const checkpoints = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n through_sequence,\n tail_digest,\n checkpoint_json\n FROM effect_agent_checkpoints\n ORDER BY thread_id, through_sequence\n `.pipe(Effect.mapError(storageError(\"scan checkpoints\")));\n\n return {\n threads: yield* decodeRows(\n Schema.Array(ThreadRow),\n \"effect_agent_threads\",\n \"startup_scan\",\n threads,\n ),\n batches: yield* decodeRows(\n Schema.Array(BatchRow),\n \"effect_agent_canonical_batches\",\n \"startup_scan\",\n batches,\n ),\n records: yield* decodeRows(\n Schema.Array(RecordRow),\n \"effect_agent_canonical_records\",\n \"startup_scan\",\n records,\n ),\n checkpoints: yield* decodeRows(\n Schema.Array(CheckpointRow),\n \"effect_agent_checkpoints\",\n \"startup_scan\",\n checkpoints,\n ),\n };\n }),\n );\n });\n\n return {\n append,\n exportThread,\n getThread,\n getTailDigestAt,\n loadCheckpoint,\n materialize,\n read,\n saveCheckpoint,\n scanStoredPayloads,\n withWriteTransaction,\n } as const;\n});\n\nexport type SqliteJournal = Effect.Success<ReturnType<typeof initializeSqliteJournal>>;\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@effect-agent/storage-sqlite","version":"0.1.0-beta.
|
|
1
|
+
{"name":"@effect-agent/storage-sqlite","version":"0.1.0-beta.50","dependencies":{"@effect-agent/core":"0.1.0-beta.50","@effect-agent/thread":"0.1.0-beta.50","@effect/platform-node":"4.0.0-rc.112","@effect/sql-sqlite-node":"4.0.0-rc.112"},"devDependencies":{"@effect/vitest":"4.0.0-rc.112","effect":"4.0.0-rc.112","typescript":"7.0.2","vite-plus":"0.3.0"},"peerDependencies":{"effect":"^4.0.0-rc.112"},"exports":{".":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"./SqliteActivityStore":{"types":"./dist/SqliteActivityStore.d.mts","default":"./dist/SqliteActivityStore.mjs"},"./SqliteScheduleStore":{"types":"./dist/SqliteScheduleStore.d.mts","default":"./dist/SqliteScheduleStore.mjs"},"./SqliteStorageConfig":{"types":"./dist/SqliteStorageConfig.d.mts","default":"./dist/SqliteStorageConfig.mjs"},"./SqliteStorageError":{"types":"./dist/SqliteStorageError.d.mts","default":"./dist/SqliteStorageError.mjs"},"./SqliteStorageFailpoint":{"types":"./dist/SqliteStorageFailpoint.d.mts","default":"./dist/SqliteStorageFailpoint.mjs"},"./SqliteStorageVersion":{"types":"./dist/SqliteStorageVersion.d.mts","default":"./dist/SqliteStorageVersion.mjs"},"./SqliteSubmissionLedger":{"types":"./dist/SqliteSubmissionLedger.d.mts","default":"./dist/SqliteSubmissionLedger.mjs"},"./SqliteSubscriptionStore":{"types":"./dist/SqliteSubscriptionStore.d.mts","default":"./dist/SqliteSubscriptionStore.mjs"},"./SqliteThreadStore":{"types":"./dist/SqliteThreadStore.d.mts","default":"./dist/SqliteThreadStore.mjs"},"./testing/SqliteStorageFailpointTesting":{"types":"./dist/SqliteStorageFailpointTesting.d.mts","default":"./dist/SqliteStorageFailpointTesting.mjs"}},"description":"Node SQLite persistence adapters for the Effect Agent durable runtime and optional memory lifecycle.","license":"MIT","repository":{"type":"git","url":"git+https://github.com/danieljvdm/effect-agent.git","directory":"packages/storage-sqlite"},"files":["dist","src"],"type":"module","sideEffects":[],"publishConfig":{"access":"public"},"scripts":{"build":"vp pack","check":"tsc --noEmit -p tsconfig.json","test":"vp test --passWithNoTests"}}
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
import {
|
|
13
13
|
AbortCommand,
|
|
14
14
|
AbortIntent,
|
|
15
|
+
AbortIntentRequest,
|
|
15
16
|
AdmissionAdmitted,
|
|
16
17
|
AdmissionConflict,
|
|
17
18
|
AdmissionNotAdmitted,
|
|
@@ -204,6 +205,15 @@ class MaxQueueSequenceRow extends Schema.Class<MaxQueueSequenceRow>("MaxQueueSeq
|
|
|
204
205
|
max_queue_sequence: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),
|
|
205
206
|
}) {}
|
|
206
207
|
|
|
208
|
+
class AbortIntentLookupRow extends Schema.Class<AbortIntentLookupRow>("AbortIntentLookupRow")({
|
|
209
|
+
submission_id: BoundedIdentifier,
|
|
210
|
+
abort_submission_id: Schema.NullOr(BoundedIdentifier),
|
|
211
|
+
author: Schema.NullOr(BoundedIdentifier),
|
|
212
|
+
reason: Schema.NullOr(BoundedStoredText),
|
|
213
|
+
requested_at: Schema.NullOr(BoundedTimestamp),
|
|
214
|
+
canonical_record_id: Schema.NullOr(BoundedIdentifier),
|
|
215
|
+
}) {}
|
|
216
|
+
|
|
207
217
|
class CanonicalRecordIdRow extends Schema.Class<CanonicalRecordIdRow>("CanonicalRecordIdRow")({
|
|
208
218
|
record_id: BoundedIdentifier,
|
|
209
219
|
}) {}
|
|
@@ -2905,6 +2915,77 @@ const makeServices = Effect.fn("SqliteSubmissionLedger.makeServices")(function*
|
|
|
2905
2915
|
LedgerError
|
|
2906
2916
|
>(undefined, scanPage);
|
|
2907
2917
|
|
|
2918
|
+
const readAbortIntentForSubmission: SubmissionLedger["Service"]["readAbortIntent"] = Effect.fn(
|
|
2919
|
+
"SqliteSubmissionLedger.readAbortIntentForSubmission",
|
|
2920
|
+
)(function* (request) {
|
|
2921
|
+
const operation = "ledger read abort intent";
|
|
2922
|
+
|
|
2923
|
+
const validated = yield* Schema.decodeUnknownEffect(Schema.toType(AbortIntentRequest))(
|
|
2924
|
+
request,
|
|
2925
|
+
).pipe(Effect.mapError(internalFailure(operation)));
|
|
2926
|
+
|
|
2927
|
+
const recordId = submissionAbortRecordId(validated.submissionId);
|
|
2928
|
+
|
|
2929
|
+
const rows = yield* sql<Record<string, unknown>>`
|
|
2930
|
+
SELECT
|
|
2931
|
+
submission.submission_id,
|
|
2932
|
+
abort.submission_id AS abort_submission_id,
|
|
2933
|
+
abort.author,
|
|
2934
|
+
abort.reason,
|
|
2935
|
+
abort.requested_at,
|
|
2936
|
+
canonical.record_id AS canonical_record_id
|
|
2937
|
+
FROM effect_agent_submissions AS submission
|
|
2938
|
+
LEFT JOIN effect_agent_abort_intents AS abort
|
|
2939
|
+
ON abort.submission_id = submission.submission_id
|
|
2940
|
+
LEFT JOIN effect_agent_canonical_records AS canonical
|
|
2941
|
+
ON canonical.thread_id = submission.thread_id
|
|
2942
|
+
AND canonical.record_id = ${recordId}
|
|
2943
|
+
WHERE submission.submission_id = ${validated.submissionId}
|
|
2944
|
+
`.pipe(Effect.mapError(sqlFailure(operation)));
|
|
2945
|
+
|
|
2946
|
+
const decoded = yield* decodeRows(
|
|
2947
|
+
Schema.Array(AbortIntentLookupRow),
|
|
2948
|
+
"effect_agent_abort_intents",
|
|
2949
|
+
validated.submissionId,
|
|
2950
|
+
rows,
|
|
2951
|
+
).pipe(Effect.mapError(internalFailure(operation)));
|
|
2952
|
+
|
|
2953
|
+
if (decoded.length === 0) {
|
|
2954
|
+
return yield* LedgerError.make({
|
|
2955
|
+
operation,
|
|
2956
|
+
message: `Unknown submission ${validated.submissionId}.`,
|
|
2957
|
+
});
|
|
2958
|
+
}
|
|
2959
|
+
if (decoded.length !== 1) {
|
|
2960
|
+
return yield* corruptionFailure(
|
|
2961
|
+
operation,
|
|
2962
|
+
"effect_agent_abort_intents",
|
|
2963
|
+
validated.submissionId,
|
|
2964
|
+
"An abort intent lookup returned more than one row.",
|
|
2965
|
+
);
|
|
2966
|
+
}
|
|
2967
|
+
const row = decoded[0];
|
|
2968
|
+
|
|
2969
|
+
if (row.abort_submission_id === null) return undefined;
|
|
2970
|
+
|
|
2971
|
+
return yield* decodeAbortIntent({
|
|
2972
|
+
submissionId: row.abort_submission_id,
|
|
2973
|
+
author: row.author,
|
|
2974
|
+
reason: row.reason,
|
|
2975
|
+
requestedAt: row.requested_at,
|
|
2976
|
+
...(row.canonical_record_id === null ? {} : { canonicalRecordId: row.canonical_record_id }),
|
|
2977
|
+
}).pipe(
|
|
2978
|
+
Effect.mapError((error) =>
|
|
2979
|
+
corruptionFailure(
|
|
2980
|
+
operation,
|
|
2981
|
+
"effect_agent_abort_intents",
|
|
2982
|
+
validated.submissionId,
|
|
2983
|
+
error.message,
|
|
2984
|
+
),
|
|
2985
|
+
),
|
|
2986
|
+
);
|
|
2987
|
+
});
|
|
2988
|
+
|
|
2908
2989
|
const loadRecoverySnapshot: SubmissionLedger["Service"]["loadRecoverySnapshot"] = Effect.fn(
|
|
2909
2990
|
"SqliteSubmissionLedger.loadRecoverySnapshot",
|
|
2910
2991
|
)(function* (request: RecoverySnapshotRequest) {
|
|
@@ -3156,6 +3237,7 @@ const makeServices = Effect.fn("SqliteSubmissionLedger.makeServices")(function*
|
|
|
3156
3237
|
releaseChildBudget,
|
|
3157
3238
|
scanNonterminal,
|
|
3158
3239
|
loadRecoverySnapshot,
|
|
3240
|
+
readAbortIntent: readAbortIntentForSubmission,
|
|
3159
3241
|
}),
|
|
3160
3242
|
);
|
|
3161
3243
|
});
|