@effect-agent/storage-cloudflare 0.1.0-beta.39 → 0.1.0-beta.40

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.d.mts CHANGED
@@ -4,12 +4,7 @@ import { Context, Crypto, Effect, Layer, Schema } from "effect";
4
4
  import { SqliteMigrator } from "@effect/sql-sqlite-do";
5
5
  import * as SqlClientService from "effect/unstable/sql/SqlClient";
6
6
  //#region src/migrations.d.ts
7
- /**
8
- * The exact-or-fresh storage version recorded in `effect_agent_meta`. Cloudflare is a fresh
9
- * platform, so there is exactly ONE migration carrying the complete current schema — no
10
- * v1→v4 history to replay (deployment spec §9: no rolling data-version promise during
11
- * private development).
12
- */
7
+ /** The current storage version recorded in `effect_agent_meta`. */
13
8
  declare const CurrentDoStorageVersion = 2;
14
9
  //#endregion
15
10
  //#region src/do-storage-config.d.ts
package/dist/index.mjs CHANGED
@@ -146,18 +146,11 @@ var DoStorageFailpointError = class extends Schema.TaggedError()("DoStorageFailp
146
146
  };
147
147
  //#endregion
148
148
  //#region src/migrations.ts
149
- /**
150
- * The exact-or-fresh storage version recorded in `effect_agent_meta`. Cloudflare is a fresh
151
- * platform, so there is exactly ONE migration carrying the complete current schema — no
152
- * v1→v4 history to replay (deployment spec §9: no rolling data-version promise during
153
- * private development).
154
- */
149
+ /** The current storage version recorded in `effect_agent_meta`. */
155
150
  const CurrentDoStorageVersion = 2;
156
151
  /**
157
- * The Thread Durable Object schema. Table names and columns mirror the Node/SQLite v4
158
- * schema byte-for-byte (`packages/storage-sqlite/src/migrations.ts`, migrations 1–4 collapsed
159
- * into their final shape) so the shared conformance suites and crash-matrix rows address
160
- * identical durable state. Two DC-specific additions:
152
+ * The Thread Durable Object schema shares its thread and ledger tables with Node/SQLite.
153
+ * Schedules and subscriptions use separate Durable Objects. Two DC-specific additions:
161
154
  *
162
155
  * 1. `effect_agent_meta` replaces `PRAGMA user_version` as the exact-or-fresh version gate —
163
156
  * a meta table is portable regardless of which PRAGMAs Durable Object SQL storage allows.
@@ -393,8 +386,6 @@ const BoundedStoredText$1 = Schema.String.check(Schema.isMaxLength(2e6));
393
386
  const BoundedIdentifier$1 = Schema.NonEmptyString.check(Schema.isMaxLength(1024));
394
387
  const MAX_RECORDS_PER_THREAD = 65536;
395
388
  const MAX_IDENTIFIER_LENGTH$1 = 1024;
396
- /** Durable Object SQL storage allows at most 100 bound parameters per statement. */
397
- const MAX_BOUND_PARAMETERS = 100;
398
389
  const isSqlError = Schema.is(SqlError);
399
390
  const storedTextBytes = (value) => new TextEncoder().encode(value).byteLength;
400
391
  const chunked = (values, size) => {
@@ -730,7 +721,7 @@ const makeJournal = (sql, failpoint, maxStoredValueBytes) => {
730
721
  message: `Thread record limit ${MAX_RECORDS_PER_THREAD} would be exceeded.`
731
722
  });
732
723
  const existingRecords = [];
733
- for (const chunk of chunked(recordIds, MAX_BOUND_PARAMETERS - 10)) {
724
+ for (const chunk of chunked(recordIds, 90)) {
734
725
  const existingRecordRows = yield* sql`
735
726
  SELECT
736
727
  thread_id,
@@ -1083,7 +1074,7 @@ var DoStorageConfigValue = class extends Schema.Class("@effect-agent/storage-clo
1083
1074
  var DoStorageConfig = class extends Context.Service()("@effect-agent/storage-cloudflare/DoStorageConfig") {};
1084
1075
  //#endregion
1085
1076
  //#region src/do-thread-store.ts
1086
- const OffsetText = Schema.String.check(Schema.isMaxLength(4 * 1024));
1077
+ const OffsetText = Schema.String.check(Schema.isMaxLength(4096));
1087
1078
  const DO_OFFSET_PREFIX = "effect-agent-do@1:";
1088
1079
  const ZERO_CANONICAL_SEQUENCE = Schema.decodeSync(CanonicalSequence)(0);
1089
1080
  const isDigest = Schema.is(Digest);
@@ -2385,7 +2376,8 @@ const makeServices$1 = Effect.fn("DoSubmissionLedger.makeServices")(function* ()
2385
2376
  submissionId: validated.submissionId,
2386
2377
  existingOutcome: reservation.value.outcome
2387
2378
  });
2388
- const settlementFailure = settlementFailureFromRecord(yield* decodeRecordEnvelopeText(reservation.value.record_json).pipe(Effect.mapError((error) => corruptionFailure(operation, "effect_agent_settlement_reservations", validated.submissionId, error.message))));
2379
+ const reservationRecord = yield* decodeRecordEnvelopeText(reservation.value.record_json).pipe(Effect.mapError((error) => corruptionFailure(operation, "effect_agent_settlement_reservations", validated.submissionId, error.message)));
2380
+ const settlementFailure = settlementFailureFromRecord(reservationRecord);
2389
2381
  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.");
2390
2382
  const submission = yield* requireSubmission(operation, validated.submissionId);
2391
2383
  if (submission.state === "settled") {
@@ -4042,7 +4034,8 @@ const makeSubscriptionStore = Effect.fn("SqliteSubscriptionStore.make")(function
4042
4034
  return false;
4043
4035
  }
4044
4036
  yield* failpoint.hit("subscription:catch-up:before");
4045
- if (!subscriptionCanSelect(record, accepted, Math.max(nowMillis, yield* Clock.currentTimeMillis), true)) return yield* error("conflict", "catch-up-eligibility");
4037
+ const effectiveNowMillis = Math.max(nowMillis, yield* Clock.currentTimeMillis);
4038
+ if (!subscriptionCanSelect(record, accepted, effectiveNowMillis, true)) return yield* error("conflict", "catch-up-eligibility");
4046
4039
  if ((yield* count(sql`SELECT COUNT(*) AS count FROM effect_agent_subscription_deliveries WHERE tenant_id=${partition.tenantId} AND source_address=${partition.address}`, "count deliveries")) >= limits.maxDeliveries) return yield* error("capacity", "deliveries");
4047
4040
  if ((yield* count(sql`SELECT COUNT(*) AS count FROM effect_agent_subscription_deliveries WHERE tenant_id=${partition.tenantId} AND source_address=${partition.address} AND owner_id=${record.key.ownerId}`, "count owner deliveries")) >= limits.maxDeliveriesPerOwner) return yield* error("capacity", "owner-deliveries");
4048
4041
  yield* insertDelivery(delivery);
@@ -4276,7 +4269,7 @@ const doSubscriptionStoreLayer = (partition) => Layer.effectContext(makeSubscrip
4276
4269
  const MAX_PORT_DIAGNOSTIC_LENGTH = 4096;
4277
4270
  const BoundedDiagnostic = Schema.String.check(Schema.isMaxLength(MAX_PORT_DIAGNOSTIC_LENGTH));
4278
4271
  /** Truncate a diagnostic string to the protocol's bounded diagnostic length. */
4279
- const boundPortDiagnostic = (value) => value.length > 4096 ? `${value.slice(0, MAX_PORT_DIAGNOSTIC_LENGTH - 3)}...` : value;
4272
+ const boundPortDiagnostic = (value) => value.length > 4096 ? `${value.slice(0, 4093)}...` : value;
4280
4273
  /**
4281
4274
  * The envelope itself could not be honored: the receiving Object could not decode the
4282
4275
  * request, or a response could not be encoded/decoded. It never carries port semantics —
@@ -4484,7 +4477,8 @@ const crossThreadStoreError = (operation, target) => ThreadStoreError.make({
4484
4477
  });
4485
4478
  const makeTransportCall = (transport) => Effect.fn("DoPortRouting.transportCall")(function* (target, call) {
4486
4479
  const encoded = yield* encodePortRequest(call).pipe(Effect.mapError((error) => PortProtocolError.make({ message: boundPortDiagnostic(`The port request could not be encoded: ${error.message}`) })));
4487
- return yield* decodePortResponse(yield* transport.call(target, encoded)).pipe(Effect.mapError((error) => PortProtocolError.make({ message: boundPortDiagnostic(`The port response could not be decoded: ${error.message}`) })));
4480
+ const raw = yield* transport.call(target, encoded);
4481
+ return yield* decodePortResponse(raw).pipe(Effect.mapError((error) => PortProtocolError.make({ message: boundPortDiagnostic(`The port response could not be decoded: ${error.message}`) })));
4488
4482
  });
4489
4483
  const makeRoutedLedgerServices = Effect.fn("DoPortRouting.makeRoutedLedgerServices")(function* (options) {
4490
4484
  const local = yield* SubmissionLedger;
@@ -4757,7 +4751,8 @@ const encodedProtocolFailure = (message) => ({
4757
4751
  * transport never has to interpret exceptions as protocol answers.
4758
4752
  */
4759
4753
  const handleEncodedPortRequest = Effect.fn("DoPortRouting.handleEncodedPortRequest")(function* (encoded) {
4760
- return yield* encodePortResponse(yield* decodePortRequest(encoded).pipe(Effect.flatMap(executePortRequest), Effect.catch((error) => Effect.succeed(PortFailed.make({ failure: PortProtocolError.make({ message: boundPortDiagnostic(`The port request could not be decoded: ${error.message}`) }) }))))).pipe(Effect.catch((error) => Effect.succeed(encodedProtocolFailure(`The port response could not be encoded: ${error.message}`))));
4754
+ const response = yield* decodePortRequest(encoded).pipe(Effect.flatMap(executePortRequest), Effect.catch((error) => Effect.succeed(PortFailed.make({ failure: PortProtocolError.make({ message: boundPortDiagnostic(`The port request could not be decoded: ${error.message}`) }) }))));
4755
+ return yield* encodePortResponse(response).pipe(Effect.catch((error) => Effect.succeed(encodedProtocolFailure(`The port response could not be encoded: ${error.message}`))));
4761
4756
  });
4762
4757
  //#endregion
4763
4758
  export { CurrentDoStorageVersion, DEFAULT_MAX_STORED_VALUE_BYTES, DoAppendConflict, DoCheckpointConflict, DoFenceRejected, DoLedgerError, DoScheduleAlarmControl, DoScheduleTransaction, DoStorageCompatibilityError, DoStorageConfig, DoStorageConfigValue, DoStorageCorruptionError, DoStorageError, DoStorageFailpoint, DoStorageFailpointError, DoStorageFailpointLocation, DoSubscriptionAlarmControl, DoSubscriptionTransaction, DoValueBoundExceeded, LedgerAdmitCall, LedgerAdmitResult, LedgerLookupCall, LedgerLookupResult, LedgerMarkReadyCall, LedgerMarkReadyResult, LedgerRecordChildSettledCall, LedgerRecordChildSettledResult, LedgerRequestAbortCall, LedgerRequestAbortResult, LedgerResolveAdmissionCall, LedgerResolveAdmissionResult, MAX_PORT_DIAGNOSTIC_LENGTH, PortFailed, PortFailure, PortProtocolError, PortRequest, PortResponse, PortResult, PortSucceeded, PortTransportError, StoreAppendCall, StoreAppendResult, StoreExportCall, StoreExportResult, StoreInspectTailCall, StoreInspectTailResult, StoreMaterializeCall, StoreMaterializeResult, StoreReadPageCall, StoreReadPageResult, ThreadPortTransport, boundPortDiagnostic, decodePortRequest, decodePortResponse, doSubscriptionStoreLayer, encodePortRequest, encodePortResponse, executePortRequest, handleEncodedPortRequest, layer, ledgerLayer, observationOffsetAt, portTransportFailure, routedSubmissionLedgerLayer, routedThreadStoreLayer, scheduleStoreLayer, storageConfigLayer, storageFailpointLayer, submissionLedgerLayer, threadStoreLayer };