@effect-agent/storage-sqlite 0.1.0-beta.69 → 0.1.0-beta.71

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.
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
- import { a as initializeSqliteJournal } from "./sqlite-journal-CC4oPmgO.mjs";
2
+ import { a as initializeSqliteJournal } from "./sqlite-journal-D9xFxCw-.mjs";
3
3
  import { MessageDeliveryError, MessageDeliveryStore } from "@effect-agent/thread/MessageDelivery";
4
4
  import { SqlMessageDeliveryTransaction, makeSqlMessageDeliveryStore } from "@effect-agent/thread/SqlMessageDeliveryStore";
5
5
  import { Effect, Layer } from "effect";
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
- import { a as initializeSqliteJournal } from "./sqlite-journal-CC4oPmgO.mjs";
2
+ import { a as initializeSqliteJournal } from "./sqlite-journal-D9xFxCw-.mjs";
3
3
  import { Effect, Layer, Result, Schema } from "effect";
4
4
  import * as SqlClientService from "effect/unstable/sql/SqlClient";
5
5
  import { ScheduleCapacityError, ScheduleChange, ScheduleConflict, ScheduleDueCursor, ScheduleFailpoint, ScheduleId, ScheduleInstant, ScheduleKey, ScheduleNotFound, ScheduleOwner, SchedulePageRequest, ScheduleRecord, ScheduleStorageError, ScheduleStore, defaultSchedulingLimits } from "@effect-agent/thread/Schedule";
@@ -1,9 +1,11 @@
1
+ import { Effect } from "effect";
2
+ import "effect/unstable/sql/SqlClient";
1
3
  import { SqliteMigrator } from "@effect/sql-sqlite-node";
2
4
  //#region src/internal/migrations.d.ts
3
- declare const CurrentSqliteStorageVersion = 10;
5
+ declare const CurrentSqliteStorageVersion = 11;
4
6
  declare namespace SqliteStorageVersion_d_exports {
5
7
  export { CurrentSqliteStorageVersion };
6
8
  }
7
9
  //#endregion
8
10
  export { CurrentSqliteStorageVersion as n, SqliteStorageVersion_d_exports as t };
9
- //# sourceMappingURL=SqliteStorageVersion-GivCOblh.d.mts.map
11
+ //# sourceMappingURL=SqliteStorageVersion-BqmqX0CI.d.mts.map
@@ -1,2 +1,2 @@
1
- import { n as CurrentSqliteStorageVersion } from "./SqliteStorageVersion-GivCOblh.mjs";
1
+ import { n as CurrentSqliteStorageVersion } from "./SqliteStorageVersion-BqmqX0CI.mjs";
2
2
  export { CurrentSqliteStorageVersion };
@@ -1,7 +1,7 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
- import { t as CurrentSqliteStorageVersion } from "./migrations-NWxfq43W.mjs";
2
+ import { t as CurrentSqliteStorageVersion } from "./migrations-Dy5v0HGe.mjs";
3
3
  //#region src/SqliteStorageVersion.ts
4
- var SqliteStorageVersion_exports = /* @__PURE__ */ __exportAll({ CurrentSqliteStorageVersion: () => 10 });
4
+ var SqliteStorageVersion_exports = /* @__PURE__ */ __exportAll({ CurrentSqliteStorageVersion: () => 11 });
5
5
  //#endregion
6
6
  export { CurrentSqliteStorageVersion, SqliteStorageVersion_exports as t };
7
7
 
@@ -2,7 +2,7 @@ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
2
  import { SqliteStorageConfig } from "./SqliteStorageConfig.mjs";
3
3
  import { SqliteLedgerError, SqliteStorageCorruptionError, SqliteStorageError, SqliteWriteContention } from "./SqliteStorageError.mjs";
4
4
  import { SqliteStorageFailpoint } from "./SqliteStorageFailpoint.mjs";
5
- import { a as initializeSqliteJournal, i as decodeRows } from "./sqlite-journal-CC4oPmgO.mjs";
5
+ import { a as initializeSqliteJournal, i as decodeRows } from "./sqlite-journal-D9xFxCw-.mjs";
6
6
  import { storageConfigLayer, storageFailpointLayer } from "./SqliteThreadStore.mjs";
7
7
  import { Clock, Context, Crypto, DateTime, Effect, Layer, Option, Schema, Stream } from "effect";
8
8
  import * as SqlClientService from "effect/unstable/sql/SqlClient";
@@ -928,39 +928,68 @@ const makeServices = Effect.fn("SqliteSubmissionLedger.makeServices")(function*
928
928
  yield* hitFailpoint("ledger:reserve-settlement:after", operation);
929
929
  return reserved;
930
930
  });
931
+ const validateFinalization = Effect.fn("SqliteSubmissionLedger.validateFinalization")(function* (validated, reservation) {
932
+ const operation = "ledger finalize settlement";
933
+ if (Option.isNone(reservation)) return yield* LedgerError.make({
934
+ operation,
935
+ message: `No settlement reservation exists for submission ${validated.submissionId}.`
936
+ });
937
+ if (reservation.value.settlement_id !== validated.settlementId) return yield* SettlementConflict.make({
938
+ submissionId: validated.submissionId,
939
+ existingOutcome: reservation.value.outcome
940
+ });
941
+ const reservationRecord = yield* decodeRecordEnvelopeText(reservation.value.record_json).pipe(Effect.mapError((error) => corruptionFailure(operation, "effect_agent_settlement_reservations", validated.submissionId, error.message)));
942
+ const settlementFailure = settlementFailureFromRecord(reservationRecord);
943
+ if (reservation.value.outcome === "failed" !== (settlementFailure !== void 0)) return yield* corruptionFailure(operation, "effect_agent_settlement_reservations", validated.submissionId, "The reserved outcome and canonical failure diagnostic disagree.");
944
+ return {
945
+ reservation: reservation.value,
946
+ settlementFailure
947
+ };
948
+ });
949
+ const replayFinalization = Effect.fn("SqliteSubmissionLedger.replayFinalization")(function* (validated, submission, { reservation, settlementFailure }) {
950
+ const operation = "ledger finalize settlement";
951
+ if (reservation.finalized_at === null) return yield* corruptionFailure(operation, "effect_agent_settlement_reservations", validated.submissionId, "A settled Submission's reservation carries no finalization timestamp.");
952
+ return yield* decodeSettlement({
953
+ submissionId: validated.submissionId,
954
+ settlementId: validated.settlementId,
955
+ receiptId: submission.receipt_id,
956
+ outcome: reservation.outcome,
957
+ ...settlementFailure === void 0 ? {} : { failure: settlementFailure },
958
+ settledAt: reservation.finalized_at
959
+ }).pipe(Effect.mapError(internalFailure(operation)));
960
+ });
931
961
  const finalizeSettlement = Effect.fn("SqliteSubmissionLedger.finalizeSettlement")(function* (request) {
932
962
  const operation = "ledger finalize settlement";
933
963
  const validated = yield* Schema.decodeUnknownEffect(Schema.toType(SettlementFinalization))(request).pipe(Effect.mapError(internalFailure(operation)));
934
964
  yield* hitFailpoint("ledger:finalize-settlement:before", operation);
965
+ const replayRows = yield* sql`
966
+ SELECT submission.*, reservation.settlement_id, reservation.outcome,
967
+ reservation.record_id, reservation.record_json, reservation.record_digest,
968
+ reservation.reserved_at, reservation.finalized_at
969
+ FROM effect_agent_submissions AS submission
970
+ INNER JOIN effect_agent_settlement_reservations AS reservation
971
+ ON reservation.submission_id = submission.submission_id
972
+ WHERE submission.submission_id = ${validated.submissionId} AND submission.state = 'settled'
973
+ `.pipe(Effect.mapError(sqlFailure(operation)));
974
+ if (replayRows.length > 1) return yield* corruptionFailure(operation, "effect_agent_submissions", validated.submissionId, "A submission primary key returned more than one row.");
975
+ const replayRow = replayRows[0];
976
+ if (replayRow !== void 0) {
977
+ const reservations = yield* decodeRows(Schema.Array(ReservationRow), "effect_agent_settlement_reservations", validated.submissionId, replayRows).pipe(Effect.mapError(internalFailure(operation)));
978
+ const state = yield* validateFinalization(validated, Option.fromUndefinedOr(reservations[0]));
979
+ const submission = yield* Schema.decodeUnknownEffect(SubmissionRow)(replayRow).pipe(Effect.mapError((error) => corruptionFailure(operation, "effect_agent_submissions", validated.submissionId, error.message)));
980
+ const settlement = yield* replayFinalization(validated, submission, state);
981
+ yield* hitFailpoint("ledger:finalize-settlement:after", operation);
982
+ return settlement;
983
+ }
935
984
  const settlement = yield* inWriteTransaction(operation, Effect.gen(function* () {
936
- const reservation = yield* readReservation(operation, validated.submissionId);
937
- if (Option.isNone(reservation)) return yield* LedgerError.make({
938
- operation,
939
- message: `No settlement reservation exists for submission ${validated.submissionId}.`
940
- });
941
- if (reservation.value.settlement_id !== validated.settlementId) return yield* SettlementConflict.make({
942
- submissionId: validated.submissionId,
943
- existingOutcome: reservation.value.outcome
944
- });
945
- const reservationRecord = yield* decodeRecordEnvelopeText(reservation.value.record_json).pipe(Effect.mapError((error) => corruptionFailure(operation, "effect_agent_settlement_reservations", validated.submissionId, error.message)));
946
- const settlementFailure = settlementFailureFromRecord(reservationRecord);
947
- if (reservation.value.outcome === "failed" !== (settlementFailure !== void 0)) return yield* corruptionFailure(operation, "effect_agent_settlement_reservations", validated.submissionId, "The reserved outcome and canonical failure diagnostic disagree.");
985
+ const state = yield* validateFinalization(validated, yield* readReservation(operation, validated.submissionId));
986
+ const { reservation, settlementFailure } = state;
948
987
  const submission = yield* requireSubmission(operation, validated.submissionId);
949
- if (submission.state === "settled") {
950
- if (reservation.value.finalized_at === null) return yield* corruptionFailure(operation, "effect_agent_settlement_reservations", validated.submissionId, "A settled Submission's reservation carries no finalization timestamp.");
951
- return yield* decodeSettlement({
952
- submissionId: validated.submissionId,
953
- settlementId: validated.settlementId,
954
- receiptId: submission.receipt_id,
955
- outcome: reservation.value.outcome,
956
- ...settlementFailure === void 0 ? {} : { failure: settlementFailure },
957
- settledAt: reservation.value.finalized_at
958
- }).pipe(Effect.mapError(internalFailure(operation)));
959
- }
988
+ if (submission.state === "settled") return yield* replayFinalization(validated, submission, state);
960
989
  const now = yield* currentInstant;
961
990
  yield* sql`
962
991
  UPDATE effect_agent_submissions
963
- SET state = 'settled', settled_outcome = ${reservation.value.outcome}
992
+ SET state = 'settled', settled_outcome = ${reservation.outcome}
964
993
  WHERE submission_id = ${validated.submissionId}
965
994
  `.pipe(Effect.mapError(sqlFailure(operation)));
966
995
  yield* sql`
@@ -976,7 +1005,7 @@ const makeServices = Effect.fn("SqliteSubmissionLedger.makeServices")(function*
976
1005
  submissionId: validated.submissionId,
977
1006
  settlementId: validated.settlementId,
978
1007
  receiptId: submission.receipt_id,
979
- outcome: reservation.value.outcome,
1008
+ outcome: reservation.outcome,
980
1009
  ...settlementFailure === void 0 ? {} : { failure: settlementFailure },
981
1010
  settledAt: now.iso
982
1011
  }).pipe(Effect.mapError(internalFailure(operation)));
@@ -1560,13 +1589,7 @@ const makeServices = Effect.fn("SqliteSubmissionLedger.makeServices")(function*
1560
1589
  SELECT ${sql.literal(SUBMISSION_COLUMNS)}
1561
1590
  FROM effect_agent_submissions
1562
1591
  WHERE state <> 'settled'
1563
- AND (
1564
- thread_id > ${cursor.threadId}
1565
- OR (
1566
- thread_id = ${cursor.threadId}
1567
- AND queue_sequence > ${cursor.queueSequence}
1568
- )
1569
- )
1592
+ AND (thread_id, queue_sequence) > (${cursor.threadId}, ${cursor.queueSequence})
1570
1593
  ORDER BY thread_id ASC, queue_sequence ASC
1571
1594
  LIMIT ${SCAN_PAGE_SIZE}
1572
1595
  `).pipe(Effect.mapError(sqlFailure(operation)));