@effect-agent/storage-sqlite 0.1.0-beta.114 → 0.1.0-beta.115

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-BCyBc87Y.mjs";
2
+ import { a as initializeSqliteJournal } from "./sqlite-journal-DE4MN8uP.mjs";
3
3
  import { Effect, Layer } from "effect";
4
4
  import { MessageDeliveryError, MessageDeliveryStore } from "effect-agent/message-delivery";
5
5
  import { SqlMessageDeliveryTransaction, makeSqlMessageDeliveryStore } from "effect-agent/sql-message-delivery-store";
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
- import { a as initializeSqliteJournal } from "./sqlite-journal-BCyBc87Y.mjs";
2
+ import { a as initializeSqliteJournal } from "./sqlite-journal-DE4MN8uP.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/schedule";
@@ -2,10 +2,10 @@ import { Effect } from "effect";
2
2
  import "effect/unstable/sql/SqlClient";
3
3
  import { SqliteMigrator } from "@effect/sql-sqlite-node";
4
4
  //#region src/internal/migrations.d.ts
5
- declare const CurrentSqliteStorageVersion = 12;
5
+ declare const CurrentSqliteStorageVersion = 14;
6
6
  declare namespace SqliteStorageVersion_d_exports {
7
7
  export { CurrentSqliteStorageVersion };
8
8
  }
9
9
  //#endregion
10
10
  export { CurrentSqliteStorageVersion as n, SqliteStorageVersion_d_exports as t };
11
- //# sourceMappingURL=SqliteStorageVersion-BO6U_VHq.d.mts.map
11
+ //# sourceMappingURL=SqliteStorageVersion-BBmy73KE.d.mts.map
@@ -1,2 +1,2 @@
1
- import { n as CurrentSqliteStorageVersion } from "./SqliteStorageVersion-BO6U_VHq.mjs";
1
+ import { n as CurrentSqliteStorageVersion } from "./SqliteStorageVersion-BBmy73KE.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-BZ89iaTY.mjs";
2
+ import { t as CurrentSqliteStorageVersion } from "./migrations-BmgwzT68.mjs";
3
3
  //#region src/SqliteStorageVersion.ts
4
- var SqliteStorageVersion_exports = /* @__PURE__ */ __exportAll({ CurrentSqliteStorageVersion: () => 12 });
4
+ var SqliteStorageVersion_exports = /* @__PURE__ */ __exportAll({ CurrentSqliteStorageVersion: () => 14 });
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-BCyBc87Y.mjs";
5
+ import { a as initializeSqliteJournal, i as decodeRows } from "./sqlite-journal-DE4MN8uP.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";
@@ -11,7 +11,7 @@ import { SqliteClient } from "@effect/sql-sqlite-node";
11
11
  import { EMPTY_TAIL_DIGEST } from "effect-agent/digest";
12
12
  import { ApprovalDecision, CanonicalSequence, DefinitionDigests, Digest, PersistedJson, ProducerEpoch, RecordEnvelope, SettlementOutcome, WorkerAdmission } from "effect-agent/records";
13
13
  import { InputMessage } from "effect-agent/messaging";
14
- import { AbortCommand, AbortIntent, AbortIntentRequest, AdmissionAdmitted, AdmissionConflict, AdmissionFence, AdmissionGroup, AdmissionNotAdmitted, AdmissionPolicyError, AdmissionRequest, AdmissionResult, ApprovalConflict, ApprovalDecisionCommand, ApprovalDecisionIntent, AttachChildToReservationRequest, BeginChildBudgetReleaseRequest, ChildAttachmentSnapshot, ChildBudgetReservationRequest, ChildBudgetReservationSnapshot, ChildReservationConflict, ChildReservationStatus, ChildSettledNotification, Claim, ClaimJoiningRequest, ClaimRequest, InputAppliedMarker, JoinSnapshot, JoinedToHost, JoiningClaim, LedgerCapabilities, LedgerError, MarkInputAppliedRequest, MarkJoinedRequest, MarkReadyRequest, MarkUnknownRequest, OwnershipLost, OwnershipRenewal, OwnershipSnapshot, ParentLinkage, QueueSequence, RecoverySnapshot, RecoverySnapshotRequest, ReleaseChildBudgetRequest, ReleaseOwnershipRequest, RenewOwnershipRequest, ReservedChildBudget, ReservedSettlement, RevertJoiningRequest, Settlement, SettlementConflict, SettlementFinalization, SettlementReservation, SettlementReservationSnapshot, SubmissionAdmissionFence, SubmissionLedger, SubmissionLookup, SubmissionLookupByKey, SubmissionSnapshot, SubmissionState, SubmissionWorkItem, SuspendRequest, SuspensionReason, SuspensionSnapshot, UnknownResolution, UnknownResolutionCommand, UnknownResolutionConflict, UnknownResolutionIntent, settlementFailureFromRecord, submissionAbortRecordId } from "effect-agent/submission-ledger";
14
+ import { AbortCommand, AbortIntent, AbortIntentRequest, AdmissionAdmitted, AdmissionConflict, AdmissionFence, AdmissionGroup, AdmissionNotAdmitted, AdmissionPolicyError, AdmissionRequest, AdmissionResult, ApprovalConflict, ApprovalDecisionCommand, ApprovalDecisionIntent, AttachChildToReservationRequest, BeginChildBudgetReleaseRequest, ChildAttachmentSnapshot, ChildBudgetReservationRequest, ChildBudgetReservationSnapshot, ChildReservationConflict, ChildReservationStatus, ChildSettledNotification, Claim, ClaimJoiningRequest, ClaimRequest, InputAppliedMarker, JoinSnapshot, JoinedToHost, JoiningClaim, LedgerCapabilities, LedgerError, MarkInputAppliedRequest, MarkJoinedRequest, MarkReadyRequest, MarkUnknownRequest, OwnershipLost, OwnershipRenewal, OwnershipSnapshot, ParentLinkage, QueueSequence, RecoverySnapshot, RecoverySnapshotRequest, ReleaseChildBudgetRequest, ReleaseOwnershipRequest, RenewOwnershipRequest, ReservedChildBudget, ReservedSettlement, RevertJoiningRequest, Settlement, SettlementConflict, SettlementFinalization, SettlementReservation, SettlementReservationSnapshot, SubmissionAdmissionFence, SubmissionLedger, SubmissionLookup, SubmissionLookupByKey, SubmissionSnapshot, SubmissionState, SubmissionWorkItem, SuspendRequest, SuspensionReason, SuspensionSnapshot, UnknownResolution, UnknownResolutionCommand, UnknownResolutionConflict, UnknownResolutionIntent, WorkerLedgerState, WorkerStopCommand, settlementFailureFromRecord, submissionAbortRecordId, workerTerminalFromRecord } from "effect-agent/submission-ledger";
15
15
  //#region src/SqliteSubmissionLedger.ts
16
16
  var SqliteSubmissionLedger_exports = /* @__PURE__ */ __exportAll({
17
17
  ledgerLayer: () => ledgerLayer,
@@ -540,6 +540,10 @@ const makeServices = Effect.fn("SqliteSubmissionLedger.makeServices")(function*
540
540
  replayed: true
541
541
  }).pipe(Effect.mapError(internalFailure(operation)));
542
542
  }
543
+ if ((yield* sql`SELECT thread_id FROM effect_agent_worker_stops WHERE thread_id = ${validated.threadId}`.pipe(Effect.mapError(sqlFailure(operation)))).length > 0) return yield* AdmissionPolicyError.make({
544
+ reason: "refused",
545
+ code: "worker-stopped"
546
+ });
543
547
  const firstRows = yield* sql`
544
548
  SELECT worker_admission_json FROM effect_agent_submissions
545
549
  WHERE thread_id=${validated.threadId} ORDER BY queue_sequence LIMIT 1
@@ -958,6 +962,7 @@ const makeServices = Effect.fn("SqliteSubmissionLedger.makeServices")(function*
958
962
  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.");
959
963
  return {
960
964
  reservation: reservation.value,
965
+ reservationRecord,
961
966
  settlementFailure
962
967
  };
963
968
  });
@@ -998,10 +1003,27 @@ const makeServices = Effect.fn("SqliteSubmissionLedger.makeServices")(function*
998
1003
  }
999
1004
  const settlement = yield* inWriteTransaction(operation, Effect.gen(function* () {
1000
1005
  const state = yield* validateFinalization(validated, yield* readReservation(operation, validated.submissionId));
1001
- const { reservation, settlementFailure } = state;
1006
+ const { reservation, reservationRecord, settlementFailure } = state;
1002
1007
  const submission = yield* requireSubmission(operation, validated.submissionId);
1003
1008
  if (submission.state === "settled") return yield* replayFinalization(validated, submission, state);
1004
1009
  const now = yield* currentInstant;
1010
+ const terminal = submission.worker_admission_json === null ? void 0 : workerTerminalFromRecord(yield* decodeSubmissionSnapshot(operation, submission), reservationRecord);
1011
+ if (terminal !== void 0) {
1012
+ if ((terminal === "completed" ? yield* sql`SELECT submission_id FROM effect_agent_submissions
1013
+ WHERE thread_id = ${submission.thread_id} AND queue_sequence > ${submission.queue_sequence}
1014
+ AND queue_sequence = (SELECT MAX(queue_sequence) FROM effect_agent_submissions WHERE thread_id = ${submission.thread_id})
1015
+ AND (joined_host_submission_id IS NULL OR joined_host_submission_id <> ${submission.submission_id}
1016
+ OR input_applied_record_id IS NULL) LIMIT 1`.pipe(Effect.mapError(sqlFailure(operation))) : []).length === 0) {
1017
+ yield* sql`INSERT OR IGNORE INTO effect_agent_worker_stops (thread_id, terminal)
1018
+ VALUES (${submission.thread_id}, ${terminal})`.pipe(Effect.mapError(sqlFailure(operation)));
1019
+ yield* sql`INSERT OR IGNORE INTO effect_agent_abort_intents (submission_id, author, reason, requested_at)
1020
+ SELECT submission_id, ${submission.principal}, ${`Worker assignment ${terminal}`}, ${now.iso}
1021
+ FROM effect_agent_submissions WHERE thread_id = ${submission.thread_id} AND state <> 'settled'
1022
+ AND submission_id <> ${submission.submission_id}
1023
+ AND (joined_host_submission_id IS NULL OR joined_host_submission_id <> ${submission.submission_id}
1024
+ OR input_applied_record_id IS NULL)`.pipe(Effect.mapError(sqlFailure(operation)));
1025
+ }
1026
+ }
1005
1027
  yield* sql`
1006
1028
  UPDATE effect_agent_submissions
1007
1029
  SET state = 'settled', settled_outcome = ${reservation.outcome}
@@ -1028,6 +1050,41 @@ const makeServices = Effect.fn("SqliteSubmissionLedger.makeServices")(function*
1028
1050
  yield* hitFailpoint("ledger:finalize-settlement:after", operation);
1029
1051
  return settlement;
1030
1052
  });
1053
+ const inspectWorker = Effect.fn("SqliteSubmissionLedger.inspectWorker")(function* (threadId) {
1054
+ const operation = "inspect worker";
1055
+ return yield* sql.withTransaction(Effect.gen(function* () {
1056
+ const read = Effect.fnUntraced(function* (active) {
1057
+ const rows = yield* sql`SELECT ${sql.literal(SUBMISSION_COLUMNS)} FROM effect_agent_submissions
1058
+ WHERE thread_id = ${threadId} ${active ? sql`AND state <> 'settled'` : sql``}
1059
+ ORDER BY queue_sequence ${active ? sql`ASC` : sql`DESC`} LIMIT 1`.pipe(Effect.mapError(sqlFailure(operation)));
1060
+ const decoded = yield* decodeSubmissionRows(operation, threadId, rows);
1061
+ return decoded[0] === void 0 ? null : yield* decodeSubmissionSnapshot(operation, decoded[0]);
1062
+ });
1063
+ const latest = yield* read(false);
1064
+ const active = yield* read(true);
1065
+ const stops = yield* sql`SELECT terminal FROM effect_agent_worker_stops WHERE thread_id = ${threadId}`.pipe(Effect.mapError(sqlFailure(operation)));
1066
+ return yield* Schema.decodeUnknownEffect(Schema.toType(WorkerLedgerState))({
1067
+ latest,
1068
+ active,
1069
+ stopped: stops.length > 0,
1070
+ ...stops[0] === void 0 || stops[0].terminal === null ? {} : { terminal: stops[0].terminal }
1071
+ }).pipe(Effect.mapError(internalFailure(operation)));
1072
+ })).pipe(Effect.catchTag("SqlError", (cause) => sqlFailure(operation)(cause)));
1073
+ });
1074
+ const stopWorker = Effect.fn("SqliteSubmissionLedger.stopWorker")(function* (request) {
1075
+ const operation = "ledger stop worker";
1076
+ const validated = yield* Schema.decodeEffect(WorkerStopCommand)(request).pipe(Effect.mapError(internalFailure(operation)));
1077
+ return yield* inWriteTransaction(operation, Effect.gen(function* () {
1078
+ const now = yield* currentInstant;
1079
+ yield* sql`INSERT OR IGNORE INTO effect_agent_worker_stops (thread_id) VALUES (${validated.threadId})`.pipe(Effect.mapError(sqlFailure(operation)));
1080
+ yield* sql`INSERT OR IGNORE INTO effect_agent_abort_intents (submission_id, author, reason, requested_at)
1081
+ SELECT submission_id, ${validated.author}, 'Worker owner stopped the worker', ${now.iso}
1082
+ FROM effect_agent_submissions WHERE thread_id = ${validated.threadId} AND state <> 'settled'`.pipe(Effect.mapError(sqlFailure(operation)));
1083
+ return (yield* sql`SELECT o.submission_id FROM effect_agent_submission_ownership o
1084
+ JOIN effect_agent_submissions s ON s.submission_id = o.submission_id
1085
+ WHERE s.thread_id = ${validated.threadId} AND s.state <> 'settled'`.pipe(Effect.mapError(sqlFailure(operation)))).length;
1086
+ }));
1087
+ });
1031
1088
  const requestAbort = Effect.fn("SqliteSubmissionLedger.requestAbort")(function* (request) {
1032
1089
  const operation = "ledger request abort";
1033
1090
  const validated = yield* Schema.decodeEffect(Schema.toType(AbortCommand))(request).pipe(Effect.mapError(internalFailure(operation)));
@@ -1088,6 +1145,7 @@ const makeServices = Effect.fn("SqliteSubmissionLedger.makeServices")(function*
1088
1145
  message: `Host submission ${validated.hostSubmissionId} does not belong to thread ${validated.threadId}.`
1089
1146
  });
1090
1147
  yield* requireOwnership(operation, host, validated.ownershipToken);
1148
+ if ((yield* sql`SELECT thread_id FROM effect_agent_worker_stops WHERE thread_id = ${validated.threadId}`.pipe(Effect.mapError(sqlFailure(operation)))).length > 0) return [];
1091
1149
  const laterRows = yield* sql`
1092
1150
  SELECT ${sql.literal(SUBMISSION_COLUMNS)}
1093
1151
  FROM effect_agent_submissions
@@ -1772,6 +1830,8 @@ const makeServices = Effect.fn("SqliteSubmissionLedger.makeServices")(function*
1772
1830
  reserveSettlement,
1773
1831
  finalizeSettlement,
1774
1832
  requestAbort,
1833
+ stopWorker,
1834
+ inspectWorker,
1775
1835
  claimJoining,
1776
1836
  markJoined,
1777
1837
  revertJoining,