@effect-agent/storage-sqlite 0.1.0-beta.100 → 0.1.0-beta.101
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/SqliteMessageDeliveryStore.mjs +1 -1
- package/dist/SqliteScheduleStore.mjs +1 -1
- package/dist/{SqliteStorageVersion-BqmqX0CI.d.mts → SqliteStorageVersion-BO6U_VHq.d.mts} +2 -2
- package/dist/SqliteStorageVersion.d.mts +1 -1
- package/dist/SqliteStorageVersion.mjs +2 -2
- package/dist/SqliteSubmissionLedger.mjs +1 -1
- package/dist/SqliteSubscriptionStore.mjs +1 -1
- package/dist/SqliteThreadStore.mjs +7 -3
- package/dist/SqliteThreadStore.mjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/{migrations-Dy5v0HGe.mjs → migrations-BZ89iaTY.mjs} +7 -3
- package/dist/migrations-BZ89iaTY.mjs.map +1 -0
- package/dist/{sqlite-journal-CBOQDySe.mjs → sqlite-journal-BCyBc87Y.mjs} +65 -19
- package/dist/sqlite-journal-BCyBc87Y.mjs.map +1 -0
- package/package.json +1 -1
- package/src/SqliteThreadStore.ts +8 -3
- package/src/internal/migrations.ts +6 -2
- package/src/internal/sqlite-journal.ts +93 -5
- package/dist/migrations-Dy5v0HGe.mjs.map +0 -1
- package/dist/sqlite-journal-CBOQDySe.mjs.map +0 -1
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { SqliteStorageConfig } from "./SqliteStorageConfig.mjs";
|
|
2
2
|
import { SqliteAppendConflict, SqliteCheckpointConflict, SqliteFenceRejected, SqliteStorageCompatibilityError, SqliteStorageCorruptionError, SqliteStorageError, SqliteStorageFailpointLocation, SqliteWriteContention } from "./SqliteStorageError.mjs";
|
|
3
3
|
import { SqliteStorageFailpoint } from "./SqliteStorageFailpoint.mjs";
|
|
4
|
-
import { a as createMessageDeliveryTables, i as createRecoveryCheckpointTable, n as createNonterminalIndex, r as sqliteMigrations } from "./migrations-
|
|
4
|
+
import { a as createMessageDeliveryTables, i as createRecoveryCheckpointTable, n as createNonterminalIndex, r as sqliteMigrations } from "./migrations-BZ89iaTY.mjs";
|
|
5
5
|
import { Effect, Exit, Schema } from "effect";
|
|
6
|
+
import { createMessageDeliveryPendingIndex } from "effect-agent/sql-message-delivery-store";
|
|
6
7
|
import * as SqlClient from "effect/unstable/sql/SqlClient";
|
|
7
8
|
import { NodeCrypto } from "@effect/platform-node";
|
|
8
9
|
import { SqliteMigrator } from "@effect/sql-sqlite-node";
|
|
9
10
|
import { EMPTY_TAIL_DIGEST } from "effect-agent/digest";
|
|
10
|
-
import { CanonicalSequence, ProducerEpoch } from "effect-agent/records";
|
|
11
|
+
import { CanonicalRecord, CanonicalSequence, ProducerEpoch } from "effect-agent/records";
|
|
11
12
|
import { ScheduleFailpoint, ScheduleFailpointError } from "effect-agent/schedule";
|
|
12
13
|
import { checkV2ThreadLayout, upgradeV2Schedules, upgradeV2Subscriptions } from "effect-agent/sql-storage-v2-upgrade";
|
|
14
|
+
import { createNativeReadIndexes, indexCanonicalRecord, seedNativeReadIndexes } from "effect-agent/sql-thread-native-reads";
|
|
13
15
|
import { SubscriptionFailpoint, SubscriptionFailpointError } from "effect-agent/subscription";
|
|
14
16
|
import { CheckpointRejected, FenceRejected, MAX_THREAD_EXPORT_RECORDS, ThreadNotMaterialized } from "effect-agent/thread-store";
|
|
15
17
|
//#region src/internal/sqlite-journal.ts
|
|
@@ -315,7 +317,7 @@ const checkPredecessorLayout = Effect.fn("SqliteJournal.checkPredecessorLayout")
|
|
|
315
317
|
const names = new Set(expected);
|
|
316
318
|
if (columns.length !== names.size || columns.some((column) => !names.has(column.name))) return yield* SqliteStorageCompatibilityError.make({
|
|
317
319
|
actualVersion: version,
|
|
318
|
-
supportedVersion:
|
|
320
|
+
supportedVersion: 12,
|
|
319
321
|
message: `The v${version} ${table} columns do not match the supported predecessor; no upgrade was committed.`
|
|
320
322
|
});
|
|
321
323
|
}
|
|
@@ -330,22 +332,22 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
|
|
|
330
332
|
const journalMode = yield* decodeSingleRow(Schema.Array(SqliteJournalModeRow), "pragma_journal_mode", "singleton", journalModeRows);
|
|
331
333
|
if (journalMode.journal_mode.toLowerCase() !== "wal") return yield* SqliteStorageCompatibilityError.make({
|
|
332
334
|
actualVersion: 0,
|
|
333
|
-
supportedVersion:
|
|
335
|
+
supportedVersion: 12,
|
|
334
336
|
message: `SQLite WAL mode is required; the database reported ${journalMode.journal_mode}.`
|
|
335
337
|
});
|
|
336
338
|
const versionRows = yield* sql`PRAGMA user_version`.pipe(Effect.mapError(storageError("read storage version")));
|
|
337
339
|
const version = yield* decodeSingleRow(Schema.Array(SqliteVersionRow), "pragma_user_version", "singleton", versionRows);
|
|
338
|
-
if (version.user_version !== 0 && version.user_version !== 7 && version.user_version !== 8 && version.user_version !== 9 && version.user_version !== 10 && version.user_version !== 11) return yield* SqliteStorageCompatibilityError.make({
|
|
340
|
+
if (version.user_version !== 0 && version.user_version !== 7 && version.user_version !== 8 && version.user_version !== 9 && version.user_version !== 10 && version.user_version !== 11 && version.user_version !== 12) return yield* SqliteStorageCompatibilityError.make({
|
|
339
341
|
actualVersion: version.user_version,
|
|
340
|
-
supportedVersion:
|
|
341
|
-
message: `The SQLite file uses unsupported storage version ${version.user_version}; this build supports exactly version
|
|
342
|
+
supportedVersion: 12,
|
|
343
|
+
message: `The SQLite file uses unsupported storage version ${version.user_version}; this build supports exactly version 12. Only supported v7, v8, v9, v10 and v11 can be upgraded automatically. Keep the original file and use a compatible library version.`
|
|
342
344
|
});
|
|
343
345
|
if (version.user_version === 7 || version.user_version === 8 || version.user_version === 9 || version.user_version === 10) yield* sql.withTransaction(Effect.gen(function* () {
|
|
344
346
|
const current = yield* sql`PRAGMA user_version`;
|
|
345
|
-
if (current.length === 1 && current[0].user_version ===
|
|
347
|
+
if (current.length === 1 && current[0].user_version === 12) return;
|
|
346
348
|
if (current.length !== 1 || current[0].user_version !== 7 && current[0].user_version !== 8 && current[0].user_version !== 9 && current[0].user_version !== 10) return yield* SqliteStorageCompatibilityError.make({
|
|
347
349
|
actualVersion: -1,
|
|
348
|
-
supportedVersion:
|
|
350
|
+
supportedVersion: 12,
|
|
349
351
|
message: "Storage version changed while acquiring the upgrade transaction."
|
|
350
352
|
});
|
|
351
353
|
if ((yield* sql`SELECT name FROM sqlite_master WHERE type='table' AND name IN (
|
|
@@ -355,17 +357,17 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
|
|
|
355
357
|
'effect_agent_approval_decisions', 'effect_agent_unknown_resolutions', 'effect_agent_schedules'
|
|
356
358
|
)`).length !== 12) return yield* SqliteStorageCompatibilityError.make({
|
|
357
359
|
actualVersion: current[0].user_version,
|
|
358
|
-
supportedVersion:
|
|
360
|
+
supportedVersion: 12,
|
|
359
361
|
message: "The predecessor store is missing required tables; no upgrade was committed."
|
|
360
362
|
});
|
|
361
363
|
if ((yield* sql`SELECT name FROM sqlite_master WHERE type='table' AND name='effect_agent_recovery_checkpoints'`).length !== (current[0].user_version === 10 ? 1 : 0)) return yield* SqliteStorageCompatibilityError.make({
|
|
362
364
|
actualVersion: current[0].user_version,
|
|
363
|
-
supportedVersion:
|
|
365
|
+
supportedVersion: 12,
|
|
364
366
|
message: "The predecessor recovery checkpoint storage does not match its version; refusing ambiguous data without mutation."
|
|
365
367
|
});
|
|
366
368
|
if ((yield* sql`SELECT name FROM sqlite_master WHERE name='effect_agent_submissions_nonterminal'`).length !== 0) return yield* SqliteStorageCompatibilityError.make({
|
|
367
369
|
actualVersion: current[0].user_version,
|
|
368
|
-
supportedVersion:
|
|
370
|
+
supportedVersion: 12,
|
|
369
371
|
message: "The predecessor already contains the nonterminal index; refusing ambiguous storage without mutation."
|
|
370
372
|
});
|
|
371
373
|
if (current[0].user_version === 7) {
|
|
@@ -403,7 +405,14 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
|
|
|
403
405
|
yield* createNonterminalIndex;
|
|
404
406
|
yield* failpoint("upgrade:after-mutation");
|
|
405
407
|
yield* failpoint("upgrade:before-version");
|
|
406
|
-
yield*
|
|
408
|
+
yield* createNativeReadIndexes;
|
|
409
|
+
yield* createMessageDeliveryPendingIndex;
|
|
410
|
+
yield* seedNativeReadIndexes.pipe(Effect.catchTag("ThreadStoreError", (error) => SqliteStorageCorruptionError.make({
|
|
411
|
+
table: "effect_agent_canonical_records",
|
|
412
|
+
rowKey: "upgrade",
|
|
413
|
+
message: error.message
|
|
414
|
+
})));
|
|
415
|
+
yield* sql`PRAGMA user_version = 12`;
|
|
407
416
|
yield* failpoint("upgrade:after-version");
|
|
408
417
|
})).pipe(Effect.provide(NodeCrypto.layer), Effect.catchTag("SqliteStorageFailpointError", (error) => SqliteStorageError.make({
|
|
409
418
|
cause: error,
|
|
@@ -432,7 +441,7 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
|
|
|
432
441
|
`.pipe(Effect.mapError(storageError("inspect unversioned storage")));
|
|
433
442
|
if ((yield* decodeRows(Schema.Array(SqliteNameRow), "sqlite_master", "effect_agent_%", existingRows)).length > 0) return yield* SqliteStorageCompatibilityError.make({
|
|
434
443
|
actualVersion: 0,
|
|
435
|
-
supportedVersion:
|
|
444
|
+
supportedVersion: 12,
|
|
436
445
|
message: "The SQLite file contains unversioned Effect Agent tables. Refusing to mutate ambiguous stored data; retain it for inspection with its original writer."
|
|
437
446
|
});
|
|
438
447
|
yield* SqliteMigrator.run({ loader: sqliteMigrations }).pipe(Effect.mapError((error) => SqliteStorageError.make({
|
|
@@ -441,6 +450,37 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
|
|
|
441
450
|
message: error.message
|
|
442
451
|
})));
|
|
443
452
|
}
|
|
453
|
+
if (version.user_version === 11) yield* sql.withTransaction(Effect.gen(function* () {
|
|
454
|
+
const current = yield* sql`PRAGMA user_version`;
|
|
455
|
+
if (current[0]?.user_version === 12) return;
|
|
456
|
+
if (current[0]?.user_version !== 11) return yield* SqliteStorageCompatibilityError.make({
|
|
457
|
+
actualVersion: current[0]?.user_version ?? -1,
|
|
458
|
+
supportedVersion: 12,
|
|
459
|
+
message: "Storage version changed during native index upgrade"
|
|
460
|
+
});
|
|
461
|
+
yield* checkPredecessorLayout(10);
|
|
462
|
+
if ((yield* sql`SELECT name FROM sqlite_master WHERE type = 'index' AND name = 'effect_agent_submissions_nonterminal'`).length !== 1) return yield* SqliteStorageCompatibilityError.make({
|
|
463
|
+
actualVersion: 11,
|
|
464
|
+
supportedVersion: 12,
|
|
465
|
+
message: "Predecessor storage is missing its required nonterminal index"
|
|
466
|
+
});
|
|
467
|
+
yield* failpoint("upgrade:before-mutation");
|
|
468
|
+
yield* createNativeReadIndexes;
|
|
469
|
+
yield* createMessageDeliveryPendingIndex;
|
|
470
|
+
yield* seedNativeReadIndexes.pipe(Effect.catchTag("ThreadStoreError", (error) => SqliteStorageCorruptionError.make({
|
|
471
|
+
table: "effect_agent_canonical_records",
|
|
472
|
+
rowKey: "upgrade",
|
|
473
|
+
message: error.message
|
|
474
|
+
})));
|
|
475
|
+
yield* failpoint("upgrade:after-mutation");
|
|
476
|
+
yield* failpoint("upgrade:before-version");
|
|
477
|
+
yield* sql`PRAGMA user_version = 12`;
|
|
478
|
+
yield* failpoint("upgrade:after-version");
|
|
479
|
+
})).pipe(Effect.mapError((error) => SqliteStorageError.make({
|
|
480
|
+
operation: "upgrade native indexes",
|
|
481
|
+
message: error.message,
|
|
482
|
+
cause: error
|
|
483
|
+
})));
|
|
444
484
|
const requiredRows = yield* sql`
|
|
445
485
|
SELECT name
|
|
446
486
|
FROM sqlite_master
|
|
@@ -460,12 +500,12 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
|
|
|
460
500
|
'effect_agent_schedules',
|
|
461
501
|
'effect_agent_message_deliveries',
|
|
462
502
|
'effect_agent_recovery_checkpoints'
|
|
463
|
-
)) OR (type = 'index' AND name
|
|
503
|
+
)) OR (type = 'index' AND name IN ('effect_agent_submissions_nonterminal', 'effect_agent_records_subtree', 'effect_agent_message_deliveries_pending', 'effect_agent_records_outstanding', 'effect_agent_records_call', 'effect_agent_records_run_input', 'effect_agent_records_worker_input'))
|
|
464
504
|
ORDER BY name
|
|
465
505
|
`.pipe(Effect.mapError(storageError("verify storage tables")));
|
|
466
|
-
if ((yield* decodeRows(Schema.Array(SqliteNameRow), "sqlite_master", "required_tables", requiredRows)).length !==
|
|
467
|
-
actualVersion:
|
|
468
|
-
supportedVersion:
|
|
506
|
+
if ((yield* decodeRows(Schema.Array(SqliteNameRow), "sqlite_master", "required_tables", requiredRows)).length !== 21) return yield* SqliteStorageCompatibilityError.make({
|
|
507
|
+
actualVersion: 12,
|
|
508
|
+
supportedVersion: 12,
|
|
469
509
|
message: "The SQLite file claims the current format but is missing required tables or its nonterminal index. Retain the original store for inspection."
|
|
470
510
|
});
|
|
471
511
|
const classifyWriteFailure = (operation) => (error) => error.reason._tag === "LockTimeoutError" ? SqliteWriteContention.make({
|
|
@@ -712,6 +752,12 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
|
|
|
712
752
|
${record.recordJson}
|
|
713
753
|
)
|
|
714
754
|
`.pipe(Effect.mapError(storageError("insert canonical record")));
|
|
755
|
+
const canonical = yield* Schema.decodeEffect(Schema.fromJsonString(CanonicalRecord))(record.recordJson).pipe(Effect.mapError((error) => SqliteStorageCorruptionError.make({
|
|
756
|
+
table: "effect_agent_canonical_records",
|
|
757
|
+
rowKey: record.recordId,
|
|
758
|
+
message: error.message
|
|
759
|
+
})));
|
|
760
|
+
yield* indexCanonicalRecord(request.threadId, canonical).pipe(Effect.provideService(SqlClient.SqlClient, sql), Effect.mapError(storageError("index canonical record")));
|
|
715
761
|
yield* failpoint("append:after-record-insert");
|
|
716
762
|
}), { discard: true });
|
|
717
763
|
yield* sql`
|
|
@@ -995,4 +1041,4 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
|
|
|
995
1041
|
//#endregion
|
|
996
1042
|
export { initializeSqliteJournal as a, decodeRows as i, RawCheckpoint as n, RawReadRequest as r, RawAppendRequest as t };
|
|
997
1043
|
|
|
998
|
-
//# sourceMappingURL=sqlite-journal-
|
|
1044
|
+
//# sourceMappingURL=sqlite-journal-BCyBc87Y.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite-journal-BCyBc87Y.mjs","names":[],"sources":["../src/internal/sqlite-journal.ts"],"sourcesContent":["import { NodeCrypto } from \"@effect/platform-node\";\nimport { SqliteMigrator } from \"@effect/sql-sqlite-node\";\nimport { Effect, Exit, Schema } from \"effect\";\nimport { EMPTY_TAIL_DIGEST } from \"effect-agent/digest\";\nimport { CanonicalRecord, CanonicalSequence, ProducerEpoch } from \"effect-agent/records\";\nimport { ScheduleFailpoint, ScheduleFailpointError } from \"effect-agent/schedule\";\nimport { createMessageDeliveryPendingIndex } from \"effect-agent/sql-message-delivery-store\";\nimport {\n checkV2ThreadLayout,\n upgradeV2Schedules,\n upgradeV2Subscriptions,\n} from \"effect-agent/sql-storage-v2-upgrade\";\nimport {\n createNativeReadIndexes,\n seedNativeReadIndexes,\n indexCanonicalRecord,\n} from \"effect-agent/sql-thread-native-reads\";\nimport { SubscriptionFailpoint, SubscriptionFailpointError } from \"effect-agent/subscription\";\nimport {\n MAX_THREAD_EXPORT_RECORDS,\n CheckpointRejected,\n FenceRejected,\n ThreadNotMaterialized,\n type SaveRecoveryCheckpointRequest,\n} from \"effect-agent/thread-store\";\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 SqliteStorageFailpointLocation,\n SqliteStorageCorruptionError,\n SqliteStorageError,\n SqliteWriteContention,\n} from \"../SqliteStorageError.ts\";\nimport { SqliteStorageFailpoint } from \"../SqliteStorageFailpoint.ts\";\nimport { createMessageDeliveryTables } from \"./message-delivery-schema.ts\";\nimport {\n CurrentSqliteStorageVersion,\n createNonterminalIndex,\n sqliteMigrations,\n} from \"./migrations.ts\";\nimport { createRecoveryCheckpointTable } from \"./recovery-checkpoint-schema.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 = MAX_THREAD_EXPORT_RECORDS;\nconst ZERO_SEQUENCE = Schema.decodeSync(CanonicalSequence)(0);\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\n/** Column inventory of the supported v8 predecessor, independent of physical column order. */\nconst predecessorColumns = {\n effect_agent_threads: [\n \"thread_id\",\n \"created_at\",\n \"tail_sequence\",\n \"tail_digest\",\n \"producer_epoch\",\n ],\n 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 ],\n effect_agent_canonical_records: [\"thread_id\", \"sequence\", \"record_id\", \"batch_id\", \"record_json\"],\n effect_agent_checkpoints: [\"thread_id\", \"through_sequence\", \"tail_digest\", \"checkpoint_json\"],\n effect_agent_submissions: [\n \"submission_id\",\n \"thread_id\",\n \"queue_sequence\",\n \"principal\",\n \"idempotency_key\",\n \"agent_id\",\n \"agent_digests_json\",\n \"deployment_id\",\n \"input_json\",\n \"input_digest\",\n \"receipt_id\",\n \"state\",\n \"settled_outcome\",\n \"created_at\",\n \"ready_at\",\n \"input_applied_record_id\",\n \"input_applied_sequence\",\n \"joined_host_submission_id\",\n \"suspended_reason_json\",\n \"suspended_at\",\n \"unknown_reason\",\n \"unknown_tool_call_ids_json\",\n \"parent_submission_id\",\n \"parent_tool_call_id\",\n \"admission_group\",\n \"admission_fence_json\",\n ],\n effect_agent_submission_ownership: [\n \"submission_id\",\n \"attempt_id\",\n \"ownership_token\",\n \"producer_epoch\",\n \"owner_producer_id\",\n \"lease_expires_at\",\n ],\n effect_agent_attempts: [\n \"attempt_id\",\n \"submission_id\",\n \"thread_id\",\n \"owner_producer_id\",\n \"producer_epoch\",\n \"claimed_at\",\n ],\n effect_agent_settlement_reservations: [\n \"submission_id\",\n \"settlement_id\",\n \"outcome\",\n \"record_id\",\n \"record_json\",\n \"record_digest\",\n \"reserved_at\",\n \"finalized_at\",\n ],\n effect_agent_abort_intents: [\n \"submission_id\",\n \"author\",\n \"reason\",\n \"requested_at\",\n \"canonical_record_id\",\n ],\n effect_agent_approval_decisions: [\n \"submission_id\",\n \"tool_call_id\",\n \"decision\",\n \"resolver\",\n \"reason\",\n \"decided_at\",\n ],\n effect_agent_unknown_resolutions: [\n \"submission_id\",\n \"tool_call_id\",\n \"author\",\n \"reason\",\n \"resolution_json\",\n \"resolved_at\",\n ],\n effect_agent_child_reservations: [\n \"reservation_id\",\n \"parent_submission_id\",\n \"parent_tool_call_id\",\n \"child_submission_id\",\n \"status\",\n \"allocation_json\",\n \"allocation_digest\",\n \"accounting_json\",\n \"reserved_at\",\n \"release_began_at\",\n \"released_at\",\n ],\n effect_agent_schedules: [\n \"tenant_id\",\n \"owner_id\",\n \"schedule_id\",\n \"deadline_at_millis\",\n \"record_json\",\n ],\n effect_agent_subscription_sequences: [\n \"tenant_id\",\n \"source_address\",\n \"sequence\",\n \"event_scan_cursor\",\n \"delivery_scan_cursor\",\n \"recovery_scan_cursor\",\n ],\n effect_agent_subscriptions: [\n \"tenant_id\",\n \"source_address\",\n \"owner_id\",\n \"subscription_id\",\n \"ordinal\",\n \"source_name\",\n \"source_version\",\n \"matching_key\",\n \"state\",\n \"expires_at_millis\",\n \"recovery_at_millis\",\n \"recovery_present\",\n \"record_json\",\n ],\n effect_agent_subscription_events: [\n \"tenant_id\",\n \"source_address\",\n \"event_id\",\n \"source_name\",\n \"source_version\",\n \"matching_key\",\n \"payload_digest\",\n \"cutoff\",\n \"cursor\",\n \"routing_complete\",\n \"next_attempt_at_millis\",\n \"record_json\",\n \"tombstone\",\n ],\n effect_agent_subscription_deliveries: [\n \"tenant_id\",\n \"source_address\",\n \"owner_id\",\n \"subscription_id\",\n \"event_id\",\n \"delivery_key\",\n \"state\",\n \"next_attempt_at_millis\",\n \"record_json\",\n ],\n} as const;\n\nconst checkPredecessorLayout = Effect.fn(\"SqliteJournal.checkPredecessorLayout\")(function* (\n version: 8 | 9 | 10,\n) {\n const sql = yield* SqlClient.SqlClient;\n\n const messageColumns =\n version === 8\n ? predecessorColumns\n : {\n ...predecessorColumns,\n effect_agent_submissions: [\n ...predecessorColumns.effect_agent_submissions,\n \"worker_admission_json\",\n \"message_admission_json\",\n ],\n effect_agent_message_deliveries: [\n \"owner_thread_id\",\n \"message_id\",\n \"version\",\n \"state\",\n \"deadline_at_millis\",\n \"record_json\",\n ],\n };\n\n const expectedColumns = {\n ...messageColumns,\n ...(version === 10\n ? {\n effect_agent_recovery_checkpoints: [\n \"thread_id\",\n \"through_sequence\",\n \"tail_digest\",\n \"checkpoint_json\",\n ],\n }\n : {}),\n };\n\n for (const [table, expected] of Object.entries(expectedColumns)) {\n const columns = yield* decodeRows(\n Schema.Array(Schema.Struct({ name: BoundedIdentifier })),\n table,\n \"schema\",\n yield* sql.unsafe(`PRAGMA table_info(${table})`),\n );\n\n const names = new Set<string>(expected);\n\n if (columns.length !== names.size || columns.some((column) => !names.has(column.name)))\n return yield* SqliteStorageCompatibilityError.make({\n actualVersion: version,\n supportedVersion: CurrentSqliteStorageVersion,\n message: `The v${version} ${table} columns do not match the supported predecessor; no upgrade was committed.`,\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 // Support the known beta49/beta50 and immediate predecessor formats atomically.\n if (\n version.user_version !== 0 &&\n version.user_version !== 7 &&\n version.user_version !== 8 &&\n version.user_version !== 9 &&\n version.user_version !== 10 &&\n version.user_version !== 11 &&\n version.user_version !== CurrentSqliteStorageVersion\n ) {\n return yield* SqliteStorageCompatibilityError.make({\n actualVersion: version.user_version,\n supportedVersion: CurrentSqliteStorageVersion,\n message:\n `The SQLite file uses unsupported storage version ${version.user_version}; ` +\n `this build supports exactly version ${CurrentSqliteStorageVersion}. ` +\n \"Only supported v7, v8, v9, v10 and v11 can be upgraded automatically. Keep the original file and use a compatible library version.\",\n });\n }\n\n if (\n version.user_version === 7 ||\n version.user_version === 8 ||\n version.user_version === 9 ||\n version.user_version === 10\n ) {\n yield* sql\n .withTransaction(\n Effect.gen(function* () {\n const current = yield* sql<{ user_version: number }>`PRAGMA user_version`;\n\n if (current.length === 1 && current[0].user_version === CurrentSqliteStorageVersion)\n return;\n if (\n current.length !== 1 ||\n (current[0].user_version !== 7 &&\n current[0].user_version !== 8 &&\n current[0].user_version !== 9 &&\n current[0].user_version !== 10)\n )\n return yield* SqliteStorageCompatibilityError.make({\n actualVersion: -1,\n supportedVersion: CurrentSqliteStorageVersion,\n message: \"Storage version changed while acquiring the upgrade transaction.\",\n });\n\n const required = yield* sql<{\n name: string;\n }>`SELECT name FROM sqlite_master WHERE type='table' AND name IN (\n 'effect_agent_threads', 'effect_agent_canonical_batches', 'effect_agent_canonical_records',\n 'effect_agent_checkpoints', 'effect_agent_submissions', 'effect_agent_submission_ownership',\n 'effect_agent_attempts', 'effect_agent_settlement_reservations', 'effect_agent_abort_intents',\n 'effect_agent_approval_decisions', 'effect_agent_unknown_resolutions', 'effect_agent_schedules'\n )`;\n\n if (required.length !== 12)\n return yield* SqliteStorageCompatibilityError.make({\n actualVersion: current[0].user_version,\n supportedVersion: CurrentSqliteStorageVersion,\n message:\n \"The predecessor store is missing required tables; no upgrade was committed.\",\n });\n\n const recoveryTables =\n yield* sql`SELECT name FROM sqlite_master WHERE type='table' AND name='effect_agent_recovery_checkpoints'`;\n\n if (recoveryTables.length !== (current[0].user_version === 10 ? 1 : 0))\n return yield* SqliteStorageCompatibilityError.make({\n actualVersion: current[0].user_version,\n supportedVersion: CurrentSqliteStorageVersion,\n message:\n \"The predecessor recovery checkpoint storage does not match its version; refusing ambiguous data without mutation.\",\n });\n\n const indexes =\n yield* sql`SELECT name FROM sqlite_master WHERE name='effect_agent_submissions_nonterminal'`;\n\n if (indexes.length !== 0)\n return yield* SqliteStorageCompatibilityError.make({\n actualVersion: current[0].user_version,\n supportedVersion: CurrentSqliteStorageVersion,\n message:\n \"The predecessor already contains the nonterminal index; refusing ambiguous storage without mutation.\",\n });\n if (current[0].user_version === 7) {\n yield* checkV2ThreadLayout();\n for (const statement of [\n sql`ALTER TABLE effect_agent_submissions ADD COLUMN admission_group TEXT`,\n sql`ALTER TABLE effect_agent_submissions ADD COLUMN admission_fence_json TEXT`,\n sql`CREATE INDEX effect_agent_submissions_group ON effect_agent_submissions (thread_id, admission_group, state)`,\n ]) {\n yield* failpoint(\"upgrade:before-mutation\");\n yield* statement;\n yield* failpoint(\"upgrade:after-mutation\");\n }\n yield* upgradeV2Schedules(16 * 1024 * 1024).pipe(\n Effect.provideService(ScheduleFailpoint, {\n hit: (point) =>\n Schema.decodeUnknownEffect(SqliteStorageFailpointLocation)(point).pipe(\n Effect.flatMap(failpoint),\n Effect.mapError(() => ScheduleFailpointError.make({ point })),\n ),\n }),\n );\n yield* upgradeV2Subscriptions(16 * 1024 * 1024).pipe(\n Effect.provideService(SubscriptionFailpoint, {\n hit: (point) =>\n Schema.decodeUnknownEffect(SqliteStorageFailpointLocation)(point).pipe(\n Effect.flatMap(failpoint),\n Effect.mapError(() => SubscriptionFailpointError.make({ point })),\n ),\n }),\n );\n }\n if (\n current[0].user_version === 8 ||\n current[0].user_version === 9 ||\n current[0].user_version === 10\n )\n yield* checkPredecessorLayout(current[0].user_version);\n if (current[0].user_version === 7 || current[0].user_version === 8) {\n yield* failpoint(\"upgrade:before-mutation\");\n yield* sql`ALTER TABLE effect_agent_submissions ADD COLUMN worker_admission_json TEXT`;\n yield* failpoint(\"upgrade:after-mutation\");\n yield* failpoint(\"upgrade:before-mutation\");\n yield* sql`ALTER TABLE effect_agent_submissions ADD COLUMN message_admission_json TEXT`;\n yield* failpoint(\"upgrade:after-mutation\");\n yield* failpoint(\"upgrade:before-mutation\");\n yield* createMessageDeliveryTables;\n yield* failpoint(\"upgrade:after-mutation\");\n }\n if (current[0].user_version !== 10) {\n yield* failpoint(\"upgrade:before-mutation\");\n yield* createRecoveryCheckpointTable;\n yield* failpoint(\"upgrade:after-mutation\");\n }\n yield* failpoint(\"upgrade:before-mutation\");\n yield* createNonterminalIndex;\n yield* failpoint(\"upgrade:after-mutation\");\n yield* failpoint(\"upgrade:before-version\");\n yield* createNativeReadIndexes;\n yield* createMessageDeliveryPendingIndex;\n yield* seedNativeReadIndexes.pipe(\n Effect.catchTag(\"ThreadStoreError\", (error) =>\n SqliteStorageCorruptionError.make({\n table: \"effect_agent_canonical_records\",\n rowKey: \"upgrade\",\n message: error.message,\n }),\n ),\n );\n yield* sql`PRAGMA user_version = 12`;\n yield* failpoint(\"upgrade:after-version\");\n }),\n )\n .pipe(\n Effect.provide(NodeCrypto.layer),\n Effect.catchTag(\"SqliteStorageFailpointError\", (error) =>\n SqliteStorageError.make({\n cause: error,\n operation: \"upgrade storage\",\n message: error.message,\n }),\n ),\n Effect.catchTag([\"ScheduleFailpointError\", \"SubscriptionFailpointError\"], (error) =>\n SqliteStorageError.make({\n cause: error,\n operation: \"upgrade storage\",\n message: \"Injected storage upgrade failure\",\n }),\n ),\n Effect.catchTag(\"StorageUpgradeError\", (error) =>\n SqliteStorageCorruptionError.make({\n table: error.table,\n rowKey: error.rowKey,\n message: error.message,\n }),\n ),\n Effect.catchTag(\"SqlError\", storageError(\"upgrade supported storage\")),\n Effect.catchTag(\"SchemaError\", (error) =>\n SqliteStorageCorruptionError.make({\n table: \"upgrade\",\n rowKey: \"v7\",\n message: error.message,\n }),\n ),\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. Refusing to mutate ambiguous stored data; retain it for inspection with its original writer.\",\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 if (version.user_version === 11) {\n yield* sql\n .withTransaction(\n Effect.gen(function* () {\n const current = yield* sql<{ user_version: number }>`PRAGMA user_version`;\n\n if (current[0]?.user_version === 12) return;\n if (current[0]?.user_version !== 11)\n return yield* SqliteStorageCompatibilityError.make({\n actualVersion: current[0]?.user_version ?? -1,\n supportedVersion: 12,\n message: \"Storage version changed during native index upgrade\",\n });\n yield* checkPredecessorLayout(10);\n\n const requiredIndex =\n yield* sql`SELECT name FROM sqlite_master WHERE type = 'index' AND name = 'effect_agent_submissions_nonterminal'`;\n\n if (requiredIndex.length !== 1)\n return yield* SqliteStorageCompatibilityError.make({\n actualVersion: 11,\n supportedVersion: 12,\n message: \"Predecessor storage is missing its required nonterminal index\",\n });\n yield* failpoint(\"upgrade:before-mutation\");\n yield* createNativeReadIndexes;\n yield* createMessageDeliveryPendingIndex;\n yield* seedNativeReadIndexes.pipe(\n Effect.catchTag(\"ThreadStoreError\", (error) =>\n SqliteStorageCorruptionError.make({\n table: \"effect_agent_canonical_records\",\n rowKey: \"upgrade\",\n message: error.message,\n }),\n ),\n );\n yield* failpoint(\"upgrade:after-mutation\");\n yield* failpoint(\"upgrade:before-version\");\n yield* sql`PRAGMA user_version = 12`;\n yield* failpoint(\"upgrade:after-version\");\n }),\n )\n .pipe(\n Effect.mapError((error) =>\n SqliteStorageError.make({\n operation: \"upgrade native indexes\",\n message: error.message,\n cause: error,\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 'effect_agent_message_deliveries',\n 'effect_agent_recovery_checkpoints'\n )) OR (type = 'index' AND name IN ('effect_agent_submissions_nonterminal', 'effect_agent_records_subtree', 'effect_agent_message_deliveries_pending', 'effect_agent_records_outstanding', 'effect_agent_records_call', 'effect_agent_records_run_input', 'effect_agent_records_worker_input'))\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 !== 21) {\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 or its nonterminal index. Retain the original store for inspection.\",\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.decodeEffect(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.decodeEffect(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\n const canonical = yield* Schema.decodeEffect(Schema.fromJsonString(CanonicalRecord))(\n record.recordJson,\n ).pipe(\n Effect.mapError((error) =>\n SqliteStorageCorruptionError.make({\n table: \"effect_agent_canonical_records\",\n rowKey: record.recordId,\n message: error.message,\n }),\n ),\n );\n\n yield* indexCanonicalRecord(request.threadId, canonical).pipe(\n Effect.provideService(SqlClient.SqlClient, sql),\n Effect.mapError(storageError(\"index canonical record\")),\n );\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 if (thread.tail_sequence > MAX_RECORDS_PER_THREAD)\n return yield* SqliteStorageError.make({\n operation: \"export thread\",\n message: \"The thread exceeds the current export record limit.\",\n });\n const records: Array<RecordRow> = [];\n let afterSequence = ZERO_SEQUENCE;\n\n while (afterSequence < thread.tail_sequence) {\n const limit = Math.min(1_024, thread.tail_sequence - afterSequence);\n\n const request = RawReadRequest.make({\n threadId,\n fromSequenceExclusive: afterSequence,\n limit,\n });\n\n const page = yield* read(request);\n\n if (\n page.length !== limit ||\n page.some((record, index) => record.sequence !== afterSequence + index + 1)\n ) {\n return yield* SqliteStorageCorruptionError.make({\n table: \"effect_agent_canonical_records\",\n rowKey: threadId,\n message: \"The exported canonical prefix is not contiguous through its captured tail.\",\n });\n }\n records.push(...page);\n afterSequence = page[page.length - 1].sequence;\n }\n\n const beyondTail =\n yield* sql`SELECT sequence FROM effect_agent_canonical_records WHERE thread_id=${threadId} AND sequence > ${thread.tail_sequence} LIMIT 1`.pipe(\n Effect.mapError(storageError(\"verify export tail\")),\n );\n\n if (beyondTail.length !== 0)\n return yield* SqliteStorageCorruptionError.make({\n table: \"effect_agent_canonical_records\",\n rowKey: threadId,\n message: \"Canonical records exist beyond the captured thread tail.\",\n });\n\n return RawThreadExport.make({ thread, records });\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 saveRecoveryCheckpoint = Effect.fn(\"SqliteJournal.saveRecoveryCheckpoint\")(function* (\n request: SaveRecoveryCheckpointRequest,\n checkpointJson: string,\n ) {\n const { checkpoint } = request;\n\n if (\n checkpoint.threadId.length > MAX_IDENTIFIER_LENGTH ||\n storedTextBytes(checkpointJson) > MAX_STORED_TEXT_BYTES\n ) {\n return yield* SqliteStorageError.make({\n operation: \"save recovery checkpoint\",\n message: \"Checkpoint identity or encoded JSON exceeds the SQLite storage bounds.\",\n });\n }\n yield* withWriteTransaction(\"recovery checkpoint transaction\")(\n Effect.gen(function* () {\n const threads = yield* getThread(checkpoint.threadId);\n const thread = threads[0];\n\n if (thread === undefined)\n return yield* ThreadNotMaterialized.make({ threadId: checkpoint.threadId });\n if (request.producerEpoch !== thread.producer_epoch)\n return yield* FenceRejected.make({\n threadId: checkpoint.threadId,\n actualEpoch: thread.producer_epoch,\n attemptedEpoch: request.producerEpoch,\n });\n if (checkpoint.throughSequence > thread.tail_sequence)\n return yield* CheckpointRejected.make({\n threadId: checkpoint.threadId,\n reason: \"ahead-of-tail\",\n });\n\n const digests =\n checkpoint.throughSequence === 0\n ? [EMPTY_TAIL_DIGEST]\n : yield* getTailDigestAt(checkpoint.threadId, checkpoint.throughSequence);\n\n if (digests.length !== 1 || digests[0] !== checkpoint.tailDigest)\n return yield* CheckpointRejected.make({\n threadId: checkpoint.threadId,\n reason: \"digest-mismatch\",\n });\n\n yield* failpoint(\"save-recovery-checkpoint:before\");\n yield* sql`\n INSERT INTO effect_agent_recovery_checkpoints (thread_id, through_sequence, tail_digest, checkpoint_json)\n VALUES (${checkpoint.threadId}, ${checkpoint.throughSequence}, ${checkpoint.tailDigest}, ${checkpointJson})\n ON CONFLICT (thread_id) DO UPDATE SET\n through_sequence = excluded.through_sequence,\n tail_digest = excluded.tail_digest,\n checkpoint_json = excluded.checkpoint_json\n WHERE excluded.through_sequence >= effect_agent_recovery_checkpoints.through_sequence\n `.pipe(Effect.mapError(storageError(\"save recovery checkpoint\")));\n }),\n );\n yield* failpoint(\"save-recovery-checkpoint:after\");\n });\n\n const loadRecoveryCheckpoint = Effect.fn(\"SqliteJournal.loadRecoveryCheckpoint\")(function* (\n threadId: string,\n ) {\n const rows = yield* sql<Record<string, unknown>>`\n SELECT thread_id, through_sequence, tail_digest, checkpoint_json\n FROM effect_agent_recovery_checkpoints\n WHERE thread_id = ${threadId}\n `.pipe(Effect.mapError(storageError(\"load recovery checkpoint\")));\n\n return yield* decodeRows(\n Schema.Array(CheckpointRow),\n \"effect_agent_recovery_checkpoints\",\n threadId,\n rows,\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 loadRecoveryCheckpoint,\n saveRecoveryCheckpoint,\n materialize,\n read,\n saveCheckpoint,\n scanStoredPayloads,\n withWriteTransaction,\n withReadTransaction,\n } as const;\n});\n\nexport type SqliteJournal = Effect.Success<ReturnType<typeof initializeSqliteJournal>>;\n"],"mappings":"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AC,KACtC,OAAO,SAAS,YACd,QAAQ,WAAW,IACf,OAAO,QAAQ,QAAQ,EAAE,IACzB,OAAO,KACL,6BAA6B,KAAK;CAChC;CACA;CACA,SAAS,sCAAsC,QAAQ,OAAO;AAChE,CAAC,CACH,CACN,CACF,CACJ;;AAGA,MAAM,qBAAqB;CACzB,sBAAsB;EACpB;EACA;EACA;EACA;EACA;CACF;CACA,gCAAgC;EAC9B;EACA;EACA;EACA;EACA;EACA;EACA;CACF;CACA,gCAAgC;EAAC;EAAa;EAAY;EAAa;EAAY;CAAa;CAChG,0BAA0B;EAAC;EAAa;EAAoB;EAAe;CAAiB;CAC5F,0BAA0B;EACxB;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;CACA,mCAAmC;EACjC;EACA;EACA;EACA;EACA;EACA;CACF;CACA,uBAAuB;EACrB;EACA;EACA;EACA;EACA;EACA;CACF;CACA,sCAAsC;EACpC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;CACA,4BAA4B;EAC1B;EACA;EACA;EACA;EACA;CACF;CACA,iCAAiC;EAC/B;EACA;EACA;EACA;EACA;EACA;CACF;CACA,kCAAkC;EAChC;EACA;EACA;EACA;EACA;EACA;CACF;CACA,iCAAiC;EAC/B;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;CACA,wBAAwB;EACtB;EACA;EACA;EACA;EACA;CACF;CACA,qCAAqC;EACnC;EACA;EACA;EACA;EACA;EACA;CACF;CACA,4BAA4B;EAC1B;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;CACA,kCAAkC;EAChC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;CACA,sCAAsC;EACpC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;AACF;AAEA,MA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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.101","dependencies":{"@effect/platform-node":"4.0.0-rc.115","@effect/sql-sqlite-node":"4.0.0-rc.115","effect-agent":"0.1.0-beta.101"},"devDependencies":{"@effect/vitest":"4.0.0-rc.115","effect":"4.0.0-rc.115","typescript":"7.0.2","vite-plus":"0.3.2"},"peerDependencies":{"effect":"^4.0.0-rc.115"},"exports":{".":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"./sqlite-activity-store":{"types":"./dist/SqliteActivityStore.d.mts","default":"./dist/SqliteActivityStore.mjs"},"./sqlite-schedule-store":{"types":"./dist/SqliteScheduleStore.d.mts","default":"./dist/SqliteScheduleStore.mjs"},"./sqlite-storage-config":{"types":"./dist/SqliteStorageConfig.d.mts","default":"./dist/SqliteStorageConfig.mjs"},"./sqlite-storage-error":{"types":"./dist/SqliteStorageError.d.mts","default":"./dist/SqliteStorageError.mjs"},"./sqlite-storage-failpoint":{"types":"./dist/SqliteStorageFailpoint.d.mts","default":"./dist/SqliteStorageFailpoint.mjs"},"./sqlite-storage-version":{"types":"./dist/SqliteStorageVersion.d.mts","default":"./dist/SqliteStorageVersion.mjs"},"./sqlite-submission-ledger":{"types":"./dist/SqliteSubmissionLedger.d.mts","default":"./dist/SqliteSubmissionLedger.mjs"},"./sqlite-subscription-store":{"types":"./dist/SqliteSubscriptionStore.d.mts","default":"./dist/SqliteSubscriptionStore.mjs"},"./sqlite-thread-store":{"types":"./dist/SqliteThreadStore.d.mts","default":"./dist/SqliteThreadStore.mjs"},"./testing/sqlite-storage-failpoint-testing":{"types":"./dist/SqliteStorageFailpointTesting.d.mts","default":"./dist/SqliteStorageFailpointTesting.mjs"},"./sqlite-message-delivery-store":{"types":"./dist/SqliteMessageDeliveryStore.d.mts","default":"./dist/SqliteMessageDeliveryStore.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"}}
|
package/src/SqliteThreadStore.ts
CHANGED
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
Digest,
|
|
22
22
|
ObservationOffset,
|
|
23
23
|
} from "effect-agent/records";
|
|
24
|
+
import { makeSelectedReads } from "effect-agent/sql-thread-native-reads";
|
|
24
25
|
import { DEFAULT_OWNERSHIP_LEASE_DURATION } from "effect-agent/submission-ledger";
|
|
25
26
|
import {
|
|
26
27
|
AppendConflict,
|
|
@@ -32,7 +33,7 @@ import {
|
|
|
32
33
|
ThreadMaterialization,
|
|
33
34
|
ThreadNotMaterialized,
|
|
34
35
|
ThreadObservation,
|
|
35
|
-
|
|
36
|
+
ThreadReadRequest,
|
|
36
37
|
ThreadStore,
|
|
37
38
|
type ThreadCheckpoints,
|
|
38
39
|
ThreadStoreError,
|
|
@@ -618,11 +619,12 @@ const makeServices = Effect.fn("SqliteThreadStore.makeServices")(function* () {
|
|
|
618
619
|
return yield* Effect.forEach(rows, decodeEnvelope);
|
|
619
620
|
});
|
|
620
621
|
|
|
621
|
-
const readEffect = Effect.fn("SqliteThreadStore.read")(function* (request:
|
|
622
|
-
const validated = yield* Schema.decodeEffect(Schema.toType(
|
|
622
|
+
const readEffect = Effect.fn("SqliteThreadStore.read")(function* (request: ThreadReadRequest) {
|
|
623
|
+
const validated = yield* Schema.decodeEffect(Schema.toType(ThreadReadRequest))(request).pipe(
|
|
623
624
|
Effect.mapError((error) => schemaStoreError("validate thread read", error)),
|
|
624
625
|
);
|
|
625
626
|
|
|
627
|
+
if ("selection" in validated) return Stream.fromIterable(yield* selectedReads.read(validated));
|
|
626
628
|
yield* requireThread(journal, validated.threadId);
|
|
627
629
|
|
|
628
630
|
const records = yield* loadRecords(
|
|
@@ -918,7 +920,10 @@ const makeServices = Effect.fn("SqliteThreadStore.makeServices")(function* () {
|
|
|
918
920
|
return Option.some(checkpoint);
|
|
919
921
|
});
|
|
920
922
|
|
|
923
|
+
const selectedReads = yield* makeSelectedReads(decodeEnvelope);
|
|
924
|
+
|
|
921
925
|
const threadStore = ThreadStore.of({
|
|
926
|
+
countPeerMessages: selectedReads.countPeerMessages,
|
|
922
927
|
append,
|
|
923
928
|
export: exportThread,
|
|
924
929
|
inspectTail,
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { SqliteMigrator } from "@effect/sql-sqlite-node";
|
|
2
2
|
import { Effect } from "effect";
|
|
3
|
+
import { createMessageDeliveryPendingIndex } from "effect-agent/sql-message-delivery-store";
|
|
4
|
+
import { createNativeReadIndexes } from "effect-agent/sql-thread-native-reads";
|
|
3
5
|
import * as SqlClient from "effect/unstable/sql/SqlClient";
|
|
4
6
|
|
|
5
7
|
import { createMessageDeliveryTables } from "./message-delivery-schema.ts";
|
|
6
8
|
import { createRecoveryCheckpointTable } from "./recovery-checkpoint-schema.ts";
|
|
7
9
|
|
|
8
|
-
export const CurrentSqliteStorageVersion =
|
|
10
|
+
export const CurrentSqliteStorageVersion = 12;
|
|
9
11
|
|
|
10
12
|
/** Index only outstanding obligations, ordered by the recovery scan's stable cursor. */
|
|
11
13
|
export const createNonterminalIndex = Effect.gen(function* () {
|
|
@@ -344,9 +346,11 @@ export const sqliteMigrations = SqliteMigrator.fromRecord({
|
|
|
344
346
|
.withoutTransform;
|
|
345
347
|
yield* sql`CREATE INDEX effect_agent_subscription_deliveries_registration ON effect_agent_subscription_deliveries (tenant_id, source_address, owner_id, subscription_id, delivery_key)`
|
|
346
348
|
.withoutTransform;
|
|
349
|
+
yield* createNativeReadIndexes;
|
|
347
350
|
yield* createNonterminalIndex;
|
|
348
351
|
yield* createMessageDeliveryTables;
|
|
352
|
+
yield* createMessageDeliveryPendingIndex;
|
|
349
353
|
yield* createRecoveryCheckpointTable;
|
|
350
|
-
yield* sql`PRAGMA user_version =
|
|
354
|
+
yield* sql`PRAGMA user_version = 12`.withoutTransform;
|
|
351
355
|
}),
|
|
352
356
|
});
|
|
@@ -2,13 +2,19 @@ import { NodeCrypto } from "@effect/platform-node";
|
|
|
2
2
|
import { SqliteMigrator } from "@effect/sql-sqlite-node";
|
|
3
3
|
import { Effect, Exit, Schema } from "effect";
|
|
4
4
|
import { EMPTY_TAIL_DIGEST } from "effect-agent/digest";
|
|
5
|
-
import { CanonicalSequence, ProducerEpoch } from "effect-agent/records";
|
|
5
|
+
import { CanonicalRecord, CanonicalSequence, ProducerEpoch } from "effect-agent/records";
|
|
6
6
|
import { ScheduleFailpoint, ScheduleFailpointError } from "effect-agent/schedule";
|
|
7
|
+
import { createMessageDeliveryPendingIndex } from "effect-agent/sql-message-delivery-store";
|
|
7
8
|
import {
|
|
8
9
|
checkV2ThreadLayout,
|
|
9
10
|
upgradeV2Schedules,
|
|
10
11
|
upgradeV2Subscriptions,
|
|
11
12
|
} from "effect-agent/sql-storage-v2-upgrade";
|
|
13
|
+
import {
|
|
14
|
+
createNativeReadIndexes,
|
|
15
|
+
seedNativeReadIndexes,
|
|
16
|
+
indexCanonicalRecord,
|
|
17
|
+
} from "effect-agent/sql-thread-native-reads";
|
|
12
18
|
import { SubscriptionFailpoint, SubscriptionFailpointError } from "effect-agent/subscription";
|
|
13
19
|
import {
|
|
14
20
|
MAX_THREAD_EXPORT_RECORDS,
|
|
@@ -488,6 +494,7 @@ export const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(fun
|
|
|
488
494
|
version.user_version !== 8 &&
|
|
489
495
|
version.user_version !== 9 &&
|
|
490
496
|
version.user_version !== 10 &&
|
|
497
|
+
version.user_version !== 11 &&
|
|
491
498
|
version.user_version !== CurrentSqliteStorageVersion
|
|
492
499
|
) {
|
|
493
500
|
return yield* SqliteStorageCompatibilityError.make({
|
|
@@ -496,7 +503,7 @@ export const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(fun
|
|
|
496
503
|
message:
|
|
497
504
|
`The SQLite file uses unsupported storage version ${version.user_version}; ` +
|
|
498
505
|
`this build supports exactly version ${CurrentSqliteStorageVersion}. ` +
|
|
499
|
-
"Only supported v7, v8, v9 and
|
|
506
|
+
"Only supported v7, v8, v9, v10 and v11 can be upgraded automatically. Keep the original file and use a compatible library version.",
|
|
500
507
|
});
|
|
501
508
|
}
|
|
502
509
|
|
|
@@ -620,7 +627,18 @@ export const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(fun
|
|
|
620
627
|
yield* createNonterminalIndex;
|
|
621
628
|
yield* failpoint("upgrade:after-mutation");
|
|
622
629
|
yield* failpoint("upgrade:before-version");
|
|
623
|
-
yield*
|
|
630
|
+
yield* createNativeReadIndexes;
|
|
631
|
+
yield* createMessageDeliveryPendingIndex;
|
|
632
|
+
yield* seedNativeReadIndexes.pipe(
|
|
633
|
+
Effect.catchTag("ThreadStoreError", (error) =>
|
|
634
|
+
SqliteStorageCorruptionError.make({
|
|
635
|
+
table: "effect_agent_canonical_records",
|
|
636
|
+
rowKey: "upgrade",
|
|
637
|
+
message: error.message,
|
|
638
|
+
}),
|
|
639
|
+
),
|
|
640
|
+
);
|
|
641
|
+
yield* sql`PRAGMA user_version = 12`;
|
|
624
642
|
yield* failpoint("upgrade:after-version");
|
|
625
643
|
}),
|
|
626
644
|
)
|
|
@@ -694,6 +712,59 @@ export const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(fun
|
|
|
694
712
|
);
|
|
695
713
|
}
|
|
696
714
|
|
|
715
|
+
if (version.user_version === 11) {
|
|
716
|
+
yield* sql
|
|
717
|
+
.withTransaction(
|
|
718
|
+
Effect.gen(function* () {
|
|
719
|
+
const current = yield* sql<{ user_version: number }>`PRAGMA user_version`;
|
|
720
|
+
|
|
721
|
+
if (current[0]?.user_version === 12) return;
|
|
722
|
+
if (current[0]?.user_version !== 11)
|
|
723
|
+
return yield* SqliteStorageCompatibilityError.make({
|
|
724
|
+
actualVersion: current[0]?.user_version ?? -1,
|
|
725
|
+
supportedVersion: 12,
|
|
726
|
+
message: "Storage version changed during native index upgrade",
|
|
727
|
+
});
|
|
728
|
+
yield* checkPredecessorLayout(10);
|
|
729
|
+
|
|
730
|
+
const requiredIndex =
|
|
731
|
+
yield* sql`SELECT name FROM sqlite_master WHERE type = 'index' AND name = 'effect_agent_submissions_nonterminal'`;
|
|
732
|
+
|
|
733
|
+
if (requiredIndex.length !== 1)
|
|
734
|
+
return yield* SqliteStorageCompatibilityError.make({
|
|
735
|
+
actualVersion: 11,
|
|
736
|
+
supportedVersion: 12,
|
|
737
|
+
message: "Predecessor storage is missing its required nonterminal index",
|
|
738
|
+
});
|
|
739
|
+
yield* failpoint("upgrade:before-mutation");
|
|
740
|
+
yield* createNativeReadIndexes;
|
|
741
|
+
yield* createMessageDeliveryPendingIndex;
|
|
742
|
+
yield* seedNativeReadIndexes.pipe(
|
|
743
|
+
Effect.catchTag("ThreadStoreError", (error) =>
|
|
744
|
+
SqliteStorageCorruptionError.make({
|
|
745
|
+
table: "effect_agent_canonical_records",
|
|
746
|
+
rowKey: "upgrade",
|
|
747
|
+
message: error.message,
|
|
748
|
+
}),
|
|
749
|
+
),
|
|
750
|
+
);
|
|
751
|
+
yield* failpoint("upgrade:after-mutation");
|
|
752
|
+
yield* failpoint("upgrade:before-version");
|
|
753
|
+
yield* sql`PRAGMA user_version = 12`;
|
|
754
|
+
yield* failpoint("upgrade:after-version");
|
|
755
|
+
}),
|
|
756
|
+
)
|
|
757
|
+
.pipe(
|
|
758
|
+
Effect.mapError((error) =>
|
|
759
|
+
SqliteStorageError.make({
|
|
760
|
+
operation: "upgrade native indexes",
|
|
761
|
+
message: error.message,
|
|
762
|
+
cause: error,
|
|
763
|
+
}),
|
|
764
|
+
),
|
|
765
|
+
);
|
|
766
|
+
}
|
|
767
|
+
|
|
697
768
|
const requiredRows = yield* sql<Record<string, unknown>>`
|
|
698
769
|
SELECT name
|
|
699
770
|
FROM sqlite_master
|
|
@@ -713,7 +784,7 @@ export const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(fun
|
|
|
713
784
|
'effect_agent_schedules',
|
|
714
785
|
'effect_agent_message_deliveries',
|
|
715
786
|
'effect_agent_recovery_checkpoints'
|
|
716
|
-
)) OR (type = 'index' AND name
|
|
787
|
+
)) OR (type = 'index' AND name IN ('effect_agent_submissions_nonterminal', 'effect_agent_records_subtree', 'effect_agent_message_deliveries_pending', 'effect_agent_records_outstanding', 'effect_agent_records_call', 'effect_agent_records_run_input', 'effect_agent_records_worker_input'))
|
|
717
788
|
ORDER BY name
|
|
718
789
|
`.pipe(Effect.mapError(storageError("verify storage tables")));
|
|
719
790
|
|
|
@@ -724,7 +795,7 @@ export const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(fun
|
|
|
724
795
|
requiredRows,
|
|
725
796
|
);
|
|
726
797
|
|
|
727
|
-
if (required.length !==
|
|
798
|
+
if (required.length !== 21) {
|
|
728
799
|
return yield* SqliteStorageCompatibilityError.make({
|
|
729
800
|
actualVersion: CurrentSqliteStorageVersion,
|
|
730
801
|
supportedVersion: CurrentSqliteStorageVersion,
|
|
@@ -1142,6 +1213,23 @@ export const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(fun
|
|
|
1142
1213
|
${record.recordJson}
|
|
1143
1214
|
)
|
|
1144
1215
|
`.pipe(Effect.mapError(storageError("insert canonical record")));
|
|
1216
|
+
|
|
1217
|
+
const canonical = yield* Schema.decodeEffect(Schema.fromJsonString(CanonicalRecord))(
|
|
1218
|
+
record.recordJson,
|
|
1219
|
+
).pipe(
|
|
1220
|
+
Effect.mapError((error) =>
|
|
1221
|
+
SqliteStorageCorruptionError.make({
|
|
1222
|
+
table: "effect_agent_canonical_records",
|
|
1223
|
+
rowKey: record.recordId,
|
|
1224
|
+
message: error.message,
|
|
1225
|
+
}),
|
|
1226
|
+
),
|
|
1227
|
+
);
|
|
1228
|
+
|
|
1229
|
+
yield* indexCanonicalRecord(request.threadId, canonical).pipe(
|
|
1230
|
+
Effect.provideService(SqlClient.SqlClient, sql),
|
|
1231
|
+
Effect.mapError(storageError("index canonical record")),
|
|
1232
|
+
);
|
|
1145
1233
|
yield* failpoint("append:after-record-insert");
|
|
1146
1234
|
}),
|
|
1147
1235
|
{ discard: true },
|