@effect-agent/storage-sqlite 0.0.1-beta.4 → 0.0.1-beta.5

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/index.mjs CHANGED
@@ -5,19 +5,19 @@ import * as SqlClient from "effect/unstable/sql/SqlClient";
5
5
  import { NodeCrypto } from "@effect/platform-node";
6
6
  //#region src/errors.ts
7
7
  /** The SQLite file uses a private-development format this adapter cannot read. */
8
- var SqliteStorageCompatibilityError = class extends Schema.TaggedErrorClass()("SqliteStorageCompatibilityError", {
8
+ var SqliteStorageCompatibilityError = class extends Schema.TaggedError()("SqliteStorageCompatibilityError", {
9
9
  actualVersion: Schema.Int,
10
10
  message: Schema.String,
11
11
  supportedVersion: Schema.Int
12
12
  }) {};
13
13
  /** Stored bytes failed the current Schema and cannot be used as recovery truth. */
14
- var SqliteStorageCorruptionError = class extends Schema.TaggedErrorClass()("SqliteStorageCorruptionError", {
14
+ var SqliteStorageCorruptionError = class extends Schema.TaggedError()("SqliteStorageCorruptionError", {
15
15
  message: Schema.String,
16
16
  rowKey: Schema.String,
17
17
  table: Schema.String
18
18
  }) {};
19
19
  /** SQLite infrastructure failed while opening or operating the store. */
20
- var SqliteStorageError = class extends Schema.TaggedErrorClass()("SqliteStorageError", {
20
+ var SqliteStorageError = class extends Schema.TaggedError()("SqliteStorageError", {
21
21
  cause: Schema.optionalKey(Schema.Defect()),
22
22
  message: Schema.String,
23
23
  operation: Schema.String
@@ -27,7 +27,7 @@ var SqliteStorageError = class extends Schema.TaggedErrorClass()("SqliteStorageE
27
27
  * SubmissionLedger port as the typed `LedgerError` with this error preserved as its cause,
28
28
  * so the adapter-level tag is never erased.
29
29
  */
30
- var SqliteLedgerError = class extends Schema.TaggedErrorClass()("SqliteLedgerError", {
30
+ var SqliteLedgerError = class extends Schema.TaggedError()("SqliteLedgerError", {
31
31
  cause: Schema.optionalKey(Schema.Defect()),
32
32
  message: Schema.String,
33
33
  operation: Schema.String
@@ -36,7 +36,7 @@ var SqliteLedgerError = class extends Schema.TaggedErrorClass()("SqliteLedgerErr
36
36
  * A canonical batch retry conflicts with existing append state. Tail conflicts carry the
37
37
  * actual committed tail as a diagnostic resume hint.
38
38
  */
39
- var SqliteAppendConflict = class extends Schema.TaggedErrorClass()("SqliteAppendConflict", {
39
+ var SqliteAppendConflict = class extends Schema.TaggedError()("SqliteAppendConflict", {
40
40
  message: Schema.String,
41
41
  reason: Schema.Literals([
42
42
  "batch-digest",
@@ -51,7 +51,7 @@ var SqliteAppendConflict = class extends Schema.TaggedErrorClass()("SqliteAppend
51
51
  * require the exact registered epoch, so both older and newer unregistered epochs are fenced;
52
52
  * a newer epoch takes over by materializing first.
53
53
  */
54
- var SqliteFenceRejected = class extends Schema.TaggedErrorClass()("SqliteFenceRejected", {
54
+ var SqliteFenceRejected = class extends Schema.TaggedError()("SqliteFenceRejected", {
55
55
  actualEpoch: ProducerEpoch,
56
56
  message: Schema.String,
57
57
  producerEpoch: ProducerEpoch
@@ -61,13 +61,13 @@ var SqliteFenceRejected = class extends Schema.TaggedErrorClass()("SqliteFenceRe
61
61
  * timeout (SQLITE_BUSY / SQLITE_LOCKED). Another transiently coexisting owner is writing;
62
62
  * the operation did not mutate canonical state and is safe to retry.
63
63
  */
64
- var SqliteWriteContention = class extends Schema.TaggedErrorClass()("SqliteWriteContention", {
64
+ var SqliteWriteContention = class extends Schema.TaggedError()("SqliteWriteContention", {
65
65
  cause: Schema.optionalKey(Schema.Defect()),
66
66
  message: Schema.String,
67
67
  operation: Schema.String
68
68
  }) {};
69
69
  /** A checkpoint conflicts with a previously stored checkpoint at the same offset. */
70
- var SqliteCheckpointConflict = class extends Schema.TaggedErrorClass()("SqliteCheckpointConflict", { message: Schema.String }) {};
70
+ var SqliteCheckpointConflict = class extends Schema.TaggedError()("SqliteCheckpointConflict", { message: Schema.String }) {};
71
71
  const SqliteStorageFailpointLocation = Schema.Literals([
72
72
  "materialize:before",
73
73
  "materialize:after",
@@ -123,7 +123,7 @@ const SqliteStorageFailpointLocation = Schema.Literals([
123
123
  "ledger:child-settled:after"
124
124
  ]);
125
125
  /** Deterministic test-only fault or pause injected at a SQLite operation boundary. */
126
- var SqliteStorageFailpointError = class extends Schema.TaggedErrorClass()("SqliteStorageFailpointError", { location: SqliteStorageFailpointLocation }) {
126
+ var SqliteStorageFailpointError = class extends Schema.TaggedError()("SqliteStorageFailpointError", { location: SqliteStorageFailpointLocation }) {
127
127
  get message() {
128
128
  return `Injected SQLite storage failure at ${this.location}.`;
129
129
  }
@@ -550,6 +550,25 @@ const makeJournal = (sql, failpoint) => {
550
550
  yield* Effect.orDie(connection.executeUnprepared("ROLLBACK", [], void 0));
551
551
  return yield* exit;
552
552
  })).pipe(Effect.withSpan("SqliteJournal.withWriteTransaction", { attributes: { operation } })));
553
+ /**
554
+ * Runs a read-only snapshot under a deferred transaction. Effect's SQLite client now
555
+ * starts every writable-client `withTransaction` with `BEGIN IMMEDIATE`, which is the
556
+ * right default for mutations but would make exports take the write lock and block a
557
+ * concurrent append. Reserving the connection and beginning explicitly preserves the
558
+ * adapter's snapshot-with-concurrent-writer contract. As with the write helper, a failed
559
+ * `BEGIN` is reported directly because there is no transaction to roll back.
560
+ */
561
+ const withReadTransaction = (operation) => (effect) => Effect.uninterruptibleMask((restore) => Effect.scoped(Effect.gen(function* () {
562
+ const connection = yield* sql.reserve.pipe(Effect.mapError(storageError(operation)));
563
+ yield* connection.executeUnprepared("BEGIN", [], void 0).pipe(Effect.mapError(storageError(operation)));
564
+ const exit = yield* restore(Effect.provideService(effect, sql.transactionService, [connection, 0])).pipe(Effect.exit);
565
+ if (Exit.isSuccess(exit)) {
566
+ yield* connection.executeUnprepared("COMMIT", [], void 0).pipe(Effect.mapError(storageError(operation)));
567
+ return exit.value;
568
+ }
569
+ yield* Effect.orDie(connection.executeUnprepared("ROLLBACK", [], void 0));
570
+ return yield* exit;
571
+ })).pipe(Effect.withSpan("SqliteJournal.withReadTransaction", { attributes: { operation } })));
553
572
  const materialize = Effect.fn("SqliteJournal.materialize")(function* (conversationId, createdAt, emptyTailDigest, producerEpoch) {
554
573
  if (conversationId.length > MAX_IDENTIFIER_LENGTH || storedTextBytes(emptyTailDigest) > MAX_STORED_TEXT_BYTES) return yield* SqliteStorageError.make({
555
574
  operation: "materialize conversation",
@@ -783,7 +802,7 @@ const makeJournal = (sql, failpoint) => {
783
802
  return yield* decodeRows(Schema.Array(RecordRow), "effect_agent_canonical_records", `${request.conversationId}>${request.fromSequenceExclusive}`, rows);
784
803
  });
785
804
  const exportConversation = Effect.fn("SqliteJournal.exportConversation")(function* (conversationId) {
786
- return yield* sql.withTransaction(Effect.gen(function* () {
805
+ return yield* withReadTransaction("export transaction")(Effect.gen(function* () {
787
806
  const conversationRows = yield* sql`
788
807
  SELECT
789
808
  conversation_id,
@@ -836,7 +855,7 @@ const makeJournal = (sql, failpoint) => {
836
855
  records: yield* decodeRows(Schema.Array(RecordRow), "effect_agent_canonical_records", conversationId, recordRows),
837
856
  checkpoints: yield* decodeRows(Schema.Array(CheckpointRow), "effect_agent_checkpoints", conversationId, checkpointRows)
838
857
  });
839
- })).pipe(Effect.catchTag("SqlError", (error) => Effect.fail(storageError("export transaction")(error))));
858
+ }));
840
859
  });
841
860
  const saveCheckpoint = Effect.fn("SqliteJournal.saveCheckpoint")(function* (checkpoint) {
842
861
  if (checkpoint.conversationId.length > MAX_IDENTIFIER_LENGTH || storedTextBytes(checkpoint.checkpointJson) > MAX_STORED_TEXT_BYTES) return yield* SqliteStorageError.make({
@@ -935,7 +954,7 @@ const makeJournal = (sql, failpoint) => {
935
954
  read,
936
955
  saveCheckpoint,
937
956
  scanStoredPayloads: Effect.fn("SqliteJournal.scanStoredPayloads")(function* () {
938
- return yield* sql.withTransaction(Effect.gen(function* () {
957
+ return yield* withReadTransaction("startup scan transaction")(Effect.gen(function* () {
939
958
  const conversations = yield* sql`
940
959
  SELECT
941
960
  conversation_id,
@@ -983,7 +1002,7 @@ const makeJournal = (sql, failpoint) => {
983
1002
  records: yield* decodeRows(Schema.Array(RecordRow), "effect_agent_canonical_records", "startup_scan", records),
984
1003
  checkpoints: yield* decodeRows(Schema.Array(CheckpointRow), "effect_agent_checkpoints", "startup_scan", checkpoints)
985
1004
  };
986
- })).pipe(Effect.catchTag("SqlError", (error) => Effect.fail(storageError("startup scan transaction")(error))));
1005
+ }));
987
1006
  }),
988
1007
  withWriteTransaction
989
1008
  };