@effect-agent/storage-sqlite 0.1.0-beta.39 → 0.1.0-beta.41
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 +10 -2
- package/dist/index.mjs +350 -94
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -4
- package/src/index.ts +2 -0
- package/src/migrations.ts +9 -68
- package/src/sqlite-activity-store.ts +503 -0
- package/src/sqlite-memory-store.ts +7 -0
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { t as SqliteStorageFailpoint } from "./sqlite-storage-failpoint-DIwWk5dw.mjs";
|
|
2
|
-
import { AbortCommand, AbortIntent, AcceptedEvent, AdmissionAdmitted, AdmissionConflict, AdmissionNotAdmitted, AdmissionRequest, AdmissionResult, AppendConflict, AppendResult, ApprovalConflict, ApprovalDecision, ApprovalDecisionCommand, ApprovalDecisionIntent, AttachChildToReservationRequest, BeginChildBudgetReleaseRequest, CanonicalBatch, CanonicalRecord, CanonicalRecordEnvelope, CanonicalSequence, CheckpointRejected, ChildAttachmentSnapshot, ChildBudgetReservationRequest, ChildBudgetReservationSnapshot, ChildReservationConflict, ChildReservationStatus, ChildSettledNotification, Claim, ClaimJoiningRequest, ClaimRequest, DEFAULT_OWNERSHIP_LEASE_DURATION, DefinitionDigests, DeliveryChange, Digest, EMPTY_TAIL_DIGEST, FenceRejected, FencedAppendRequest, InputAppliedMarker, JoinSnapshot, JoinedToHost, JoiningClaim, LedgerCapabilities, LedgerError, LoadCheckpointRequest, MarkInputAppliedRequest, MarkJoinedRequest, MarkReadyRequest, MarkUnknownRequest, ObservationOffset, OwnershipLost, OwnershipRenewal, OwnershipSnapshot, ParentLinkage, PersistedJson, ProducerEpoch, QueueSequence, RecordEnvelope, RecoverySnapshot, RecoverySnapshotRequest, ReleaseChildBudgetRequest, ReleaseOwnershipRequest, RenewOwnershipRequest, ReservedChildBudget, ReservedSettlement, RevertJoiningRequest, SaveCheckpointRequest, ScheduleCapacityError, ScheduleChange, ScheduleConflict, ScheduleDueCursor, ScheduleFailpoint, ScheduleId, ScheduleInstant, ScheduleKey, ScheduleNotFound, ScheduleOwner, SchedulePageRequest, ScheduleRecord, ScheduleStorageError, ScheduleStore, Settlement, SettlementConflict, SettlementFinalization, SettlementOutcome, SettlementReservation, SettlementReservationSnapshot, SourcePartition, SubmissionLedger, SubmissionLookup, SubmissionLookupByKey, SubmissionSnapshot, SubmissionState, SubscriptionDelivery, SubscriptionDeliveryKey, SubscriptionError, SubscriptionFailpoint, SubscriptionKey, SubscriptionLimits, SubscriptionName, SubscriptionRecord, SubscriptionScanCursors, SubscriptionStore, SuspendRequest, SuspensionReason, SuspensionSnapshot, ThreadCheckpoint, ThreadExport, ThreadExportRequest, ThreadMaterialization, ThreadNotMaterialized, ThreadObservation, ThreadRead, ThreadStore, ThreadStoreError, ThreadTail, ThreadTailRequest, UnknownResolution, UnknownResolutionCommand, UnknownResolutionConflict, UnknownResolutionIntent, applyScheduleChange, applySubscriptionDeliveryChange, defaultSchedulingLimits, digestCanonicalBatch, sameAcceptedEventIdentity, sameSourcePartition, scheduleDeadline, scheduleUsesCapacity, settlementFailureFromRecord, submissionAbortRecordId, subscriptionCanSelect, subscriptionDeliveryCanSelect, subscriptionDeliveryKeyString } from "@effect-agent/thread";
|
|
2
|
+
import { AbortCommand, AbortIntent, AcceptedEvent, ActivityBusy, ActivityClaim, ActivityClaimRequest, ActivityMutationFailpoint, ActivityOwnershipLost, ActivityProcessorKey, ActivityProcessorStore, ActivityProgress, ActivityStoreError, ActivityWorkConflict, AdmissionAdmitted, AdmissionConflict, AdmissionNotAdmitted, AdmissionRequest, AdmissionResult, AppendConflict, AppendResult, ApprovalConflict, ApprovalDecision, ApprovalDecisionCommand, ApprovalDecisionIntent, AttachChildToReservationRequest, BeginChildBudgetReleaseRequest, CanonicalBatch, CanonicalRecord, CanonicalRecordEnvelope, CanonicalSequence, CheckpointRejected, ChildAttachmentSnapshot, ChildBudgetReservationRequest, ChildBudgetReservationSnapshot, ChildReservationConflict, ChildReservationStatus, ChildSettledNotification, Claim, ClaimJoiningRequest, ClaimRequest, DEFAULT_OWNERSHIP_LEASE_DURATION, DefinitionDigests, DeliveryChange, Digest, EMPTY_TAIL_DIGEST, FenceRejected, FencedAppendRequest, InputAppliedMarker, JoinSnapshot, JoinedToHost, JoiningClaim, LedgerCapabilities, LedgerError, LoadCheckpointRequest, MarkInputAppliedRequest, MarkJoinedRequest, MarkReadyRequest, MarkUnknownRequest, ObservationOffset, OwnershipLost, OwnershipRenewal, OwnershipSnapshot, ParentLinkage, PersistedJson, PreparedActivity, ProducerEpoch, QueueSequence, RecordEnvelope, RecoverySnapshot, RecoverySnapshotRequest, ReleaseChildBudgetRequest, ReleaseOwnershipRequest, RenewOwnershipRequest, ReservedChildBudget, ReservedSettlement, RevertJoiningRequest, SaveCheckpointRequest, ScheduleCapacityError, ScheduleChange, ScheduleConflict, ScheduleDueCursor, ScheduleFailpoint, ScheduleId, ScheduleInstant, ScheduleKey, ScheduleNotFound, ScheduleOwner, SchedulePageRequest, ScheduleRecord, ScheduleStorageError, ScheduleStore, Settlement, SettlementConflict, SettlementFinalization, SettlementOutcome, SettlementReservation, SettlementReservationSnapshot, SourcePartition, SubmissionLedger, SubmissionLookup, SubmissionLookupByKey, SubmissionSnapshot, SubmissionState, SubscriptionDelivery, SubscriptionDeliveryKey, SubscriptionError, SubscriptionFailpoint, SubscriptionKey, SubscriptionLimits, SubscriptionName, SubscriptionRecord, SubscriptionScanCursors, SubscriptionStore, SuspendRequest, SuspensionReason, SuspensionSnapshot, ThreadCheckpoint, ThreadExport, ThreadExportRequest, ThreadMaterialization, ThreadNotMaterialized, ThreadObservation, ThreadRead, ThreadStore, ThreadStoreError, ThreadTail, ThreadTailRequest, UnknownResolution, UnknownResolutionCommand, UnknownResolutionConflict, UnknownResolutionIntent, applyScheduleChange, applySubscriptionDeliveryChange, defaultSchedulingLimits, digestCanonicalBatch, sameAcceptedEventIdentity, sameSourcePartition, scheduleDeadline, scheduleUsesCapacity, settlementFailureFromRecord, submissionAbortRecordId, subscriptionCanSelect, subscriptionDeliveryCanSelect, subscriptionDeliveryKeyString } from "@effect-agent/thread";
|
|
3
3
|
import { Clock, Context, Crypto, DateTime, Duration, Effect, Exit, Layer, Option, Ref, Result, Schema, Stream } from "effect";
|
|
4
4
|
import { SqliteClient, SqliteMigrator } from "@effect/sql-sqlite-node";
|
|
5
5
|
import * as SqlClient from "effect/unstable/sql/SqlClient";
|
|
6
6
|
import { NodeCrypto } from "@effect/platform-node";
|
|
7
|
+
import { memoryReaderLayer, memoryStoreLayer, memoryStoreLayerWithFailpoints } from "@effect-agent/thread/sql-memory";
|
|
7
8
|
//#region src/errors.ts
|
|
8
9
|
/** The SQLite file uses a private-development format this adapter cannot read. */
|
|
9
10
|
var SqliteStorageCompatibilityError = class extends Schema.TaggedError()("SqliteStorageCompatibilityError", {
|
|
@@ -132,10 +133,10 @@ var SqliteStorageFailpointError = class extends Schema.TaggedError()("SqliteStor
|
|
|
132
133
|
//#endregion
|
|
133
134
|
//#region src/migrations.ts
|
|
134
135
|
const CurrentSqliteStorageVersion = 7;
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
136
|
+
/** Initialize empty storage with the complete current schema. */
|
|
137
|
+
const sqliteMigrations = SqliteMigrator.fromRecord({ "1_current_thread_storage": Effect.gen(function* () {
|
|
138
|
+
const sql = yield* SqlClient.SqlClient;
|
|
139
|
+
yield* sql`
|
|
139
140
|
CREATE TABLE effect_agent_threads (
|
|
140
141
|
thread_id TEXT PRIMARY KEY NOT NULL,
|
|
141
142
|
created_at TEXT NOT NULL,
|
|
@@ -144,7 +145,7 @@ const sqliteMigrations = SqliteMigrator.fromRecord({
|
|
|
144
145
|
producer_epoch INTEGER NOT NULL
|
|
145
146
|
)
|
|
146
147
|
`.withoutTransform;
|
|
147
|
-
|
|
148
|
+
yield* sql`
|
|
148
149
|
CREATE TABLE effect_agent_canonical_batches (
|
|
149
150
|
thread_id TEXT NOT NULL,
|
|
150
151
|
batch_id TEXT NOT NULL,
|
|
@@ -159,7 +160,7 @@ const sqliteMigrations = SqliteMigrator.fromRecord({
|
|
|
159
160
|
ON DELETE RESTRICT
|
|
160
161
|
)
|
|
161
162
|
`.withoutTransform;
|
|
162
|
-
|
|
163
|
+
yield* sql`
|
|
163
164
|
CREATE TABLE effect_agent_canonical_records (
|
|
164
165
|
thread_id TEXT NOT NULL,
|
|
165
166
|
sequence INTEGER NOT NULL,
|
|
@@ -173,11 +174,11 @@ const sqliteMigrations = SqliteMigrator.fromRecord({
|
|
|
173
174
|
ON DELETE RESTRICT
|
|
174
175
|
)
|
|
175
176
|
`.withoutTransform;
|
|
176
|
-
|
|
177
|
+
yield* sql`
|
|
177
178
|
CREATE INDEX effect_agent_canonical_records_batch
|
|
178
179
|
ON effect_agent_canonical_records (thread_id, batch_id, sequence)
|
|
179
180
|
`.withoutTransform;
|
|
180
|
-
|
|
181
|
+
yield* sql`
|
|
181
182
|
CREATE TABLE effect_agent_checkpoints (
|
|
182
183
|
thread_id TEXT NOT NULL,
|
|
183
184
|
through_sequence INTEGER NOT NULL,
|
|
@@ -189,11 +190,7 @@ const sqliteMigrations = SqliteMigrator.fromRecord({
|
|
|
189
190
|
ON DELETE RESTRICT
|
|
190
191
|
)
|
|
191
192
|
`.withoutTransform;
|
|
192
|
-
|
|
193
|
-
}),
|
|
194
|
-
"2_durable_submission_ledger": Effect.gen(function* () {
|
|
195
|
-
const sql = yield* SqlClient.SqlClient;
|
|
196
|
-
yield* sql`
|
|
193
|
+
yield* sql`
|
|
197
194
|
CREATE TABLE effect_agent_submissions (
|
|
198
195
|
submission_id TEXT PRIMARY KEY NOT NULL,
|
|
199
196
|
thread_id TEXT NOT NULL,
|
|
@@ -212,11 +209,18 @@ const sqliteMigrations = SqliteMigrator.fromRecord({
|
|
|
212
209
|
ready_at TEXT,
|
|
213
210
|
input_applied_record_id TEXT,
|
|
214
211
|
input_applied_sequence INTEGER,
|
|
212
|
+
joined_host_submission_id TEXT,
|
|
213
|
+
suspended_reason_json TEXT,
|
|
214
|
+
suspended_at TEXT,
|
|
215
|
+
unknown_reason TEXT,
|
|
216
|
+
unknown_tool_call_ids_json TEXT,
|
|
217
|
+
parent_submission_id TEXT,
|
|
218
|
+
parent_tool_call_id TEXT,
|
|
215
219
|
UNIQUE (thread_id, principal, idempotency_key),
|
|
216
220
|
UNIQUE (thread_id, queue_sequence)
|
|
217
221
|
)
|
|
218
222
|
`.withoutTransform;
|
|
219
|
-
|
|
223
|
+
yield* sql`
|
|
220
224
|
CREATE TABLE effect_agent_submission_ownership (
|
|
221
225
|
submission_id TEXT PRIMARY KEY NOT NULL,
|
|
222
226
|
attempt_id TEXT NOT NULL,
|
|
@@ -229,7 +233,7 @@ const sqliteMigrations = SqliteMigrator.fromRecord({
|
|
|
229
233
|
ON DELETE RESTRICT
|
|
230
234
|
)
|
|
231
235
|
`.withoutTransform;
|
|
232
|
-
|
|
236
|
+
yield* sql`
|
|
233
237
|
CREATE TABLE effect_agent_attempts (
|
|
234
238
|
attempt_id TEXT PRIMARY KEY NOT NULL,
|
|
235
239
|
submission_id TEXT NOT NULL,
|
|
@@ -242,7 +246,7 @@ const sqliteMigrations = SqliteMigrator.fromRecord({
|
|
|
242
246
|
ON DELETE RESTRICT
|
|
243
247
|
)
|
|
244
248
|
`.withoutTransform;
|
|
245
|
-
|
|
249
|
+
yield* sql`
|
|
246
250
|
CREATE TABLE effect_agent_settlement_reservations (
|
|
247
251
|
submission_id TEXT PRIMARY KEY NOT NULL,
|
|
248
252
|
settlement_id TEXT NOT NULL,
|
|
@@ -257,7 +261,7 @@ const sqliteMigrations = SqliteMigrator.fromRecord({
|
|
|
257
261
|
ON DELETE RESTRICT
|
|
258
262
|
)
|
|
259
263
|
`.withoutTransform;
|
|
260
|
-
|
|
264
|
+
yield* sql`
|
|
261
265
|
CREATE TABLE effect_agent_abort_intents (
|
|
262
266
|
submission_id TEXT PRIMARY KEY NOT NULL,
|
|
263
267
|
author TEXT NOT NULL,
|
|
@@ -269,35 +273,11 @@ const sqliteMigrations = SqliteMigrator.fromRecord({
|
|
|
269
273
|
ON DELETE RESTRICT
|
|
270
274
|
)
|
|
271
275
|
`.withoutTransform;
|
|
272
|
-
|
|
273
|
-
}),
|
|
274
|
-
"3_durable_tools_and_joined_input": Effect.gen(function* () {
|
|
275
|
-
const sql = yield* SqlClient.SqlClient;
|
|
276
|
-
yield* sql`
|
|
277
|
-
ALTER TABLE effect_agent_submissions
|
|
278
|
-
ADD COLUMN joined_host_submission_id TEXT
|
|
279
|
-
`.withoutTransform;
|
|
280
|
-
yield* sql`
|
|
281
|
-
ALTER TABLE effect_agent_submissions
|
|
282
|
-
ADD COLUMN suspended_reason_json TEXT
|
|
283
|
-
`.withoutTransform;
|
|
284
|
-
yield* sql`
|
|
285
|
-
ALTER TABLE effect_agent_submissions
|
|
286
|
-
ADD COLUMN suspended_at TEXT
|
|
287
|
-
`.withoutTransform;
|
|
288
|
-
yield* sql`
|
|
289
|
-
ALTER TABLE effect_agent_submissions
|
|
290
|
-
ADD COLUMN unknown_reason TEXT
|
|
291
|
-
`.withoutTransform;
|
|
292
|
-
yield* sql`
|
|
293
|
-
ALTER TABLE effect_agent_submissions
|
|
294
|
-
ADD COLUMN unknown_tool_call_ids_json TEXT
|
|
295
|
-
`.withoutTransform;
|
|
296
|
-
yield* sql`
|
|
276
|
+
yield* sql`
|
|
297
277
|
CREATE INDEX effect_agent_submissions_joined_host
|
|
298
278
|
ON effect_agent_submissions (joined_host_submission_id)
|
|
299
279
|
`.withoutTransform;
|
|
300
|
-
|
|
280
|
+
yield* sql`
|
|
301
281
|
CREATE TABLE effect_agent_approval_decisions (
|
|
302
282
|
submission_id TEXT NOT NULL,
|
|
303
283
|
tool_call_id TEXT NOT NULL,
|
|
@@ -311,7 +291,7 @@ const sqliteMigrations = SqliteMigrator.fromRecord({
|
|
|
311
291
|
ON DELETE RESTRICT
|
|
312
292
|
)
|
|
313
293
|
`.withoutTransform;
|
|
314
|
-
|
|
294
|
+
yield* sql`
|
|
315
295
|
CREATE TABLE effect_agent_unknown_resolutions (
|
|
316
296
|
submission_id TEXT NOT NULL,
|
|
317
297
|
tool_call_id TEXT NOT NULL,
|
|
@@ -325,23 +305,11 @@ const sqliteMigrations = SqliteMigrator.fromRecord({
|
|
|
325
305
|
ON DELETE RESTRICT
|
|
326
306
|
)
|
|
327
307
|
`.withoutTransform;
|
|
328
|
-
|
|
329
|
-
}),
|
|
330
|
-
"4_durable_subagents": Effect.gen(function* () {
|
|
331
|
-
const sql = yield* SqlClient.SqlClient;
|
|
332
|
-
yield* sql`
|
|
333
|
-
ALTER TABLE effect_agent_submissions
|
|
334
|
-
ADD COLUMN parent_submission_id TEXT
|
|
335
|
-
`.withoutTransform;
|
|
336
|
-
yield* sql`
|
|
337
|
-
ALTER TABLE effect_agent_submissions
|
|
338
|
-
ADD COLUMN parent_tool_call_id TEXT
|
|
339
|
-
`.withoutTransform;
|
|
340
|
-
yield* sql`
|
|
308
|
+
yield* sql`
|
|
341
309
|
CREATE INDEX effect_agent_submissions_parent
|
|
342
310
|
ON effect_agent_submissions (parent_submission_id)
|
|
343
311
|
`.withoutTransform;
|
|
344
|
-
|
|
312
|
+
yield* sql`
|
|
345
313
|
CREATE TABLE effect_agent_child_reservations (
|
|
346
314
|
reservation_id TEXT PRIMARY KEY NOT NULL,
|
|
347
315
|
parent_submission_id TEXT NOT NULL,
|
|
@@ -360,11 +328,7 @@ const sqliteMigrations = SqliteMigrator.fromRecord({
|
|
|
360
328
|
ON DELETE RESTRICT
|
|
361
329
|
)
|
|
362
330
|
`.withoutTransform;
|
|
363
|
-
|
|
364
|
-
}),
|
|
365
|
-
"5_durable_schedules": Effect.gen(function* () {
|
|
366
|
-
const sql = yield* SqlClient.SqlClient;
|
|
367
|
-
yield* sql`
|
|
331
|
+
yield* sql`
|
|
368
332
|
CREATE TABLE effect_agent_schedules (
|
|
369
333
|
tenant_id TEXT NOT NULL,
|
|
370
334
|
owner_id TEXT NOT NULL,
|
|
@@ -374,21 +338,17 @@ const sqliteMigrations = SqliteMigrator.fromRecord({
|
|
|
374
338
|
PRIMARY KEY (tenant_id, owner_id, schedule_id)
|
|
375
339
|
)
|
|
376
340
|
`.withoutTransform;
|
|
377
|
-
|
|
341
|
+
yield* sql`
|
|
378
342
|
CREATE INDEX effect_agent_schedules_deadline
|
|
379
343
|
ON effect_agent_schedules (deadline_at_millis, tenant_id, owner_id, schedule_id)
|
|
380
344
|
WHERE deadline_at_millis IS NOT NULL
|
|
381
345
|
`.withoutTransform;
|
|
382
|
-
|
|
346
|
+
yield* sql`
|
|
383
347
|
CREATE INDEX effect_agent_schedules_owner_deadline
|
|
384
348
|
ON effect_agent_schedules (tenant_id, owner_id, deadline_at_millis, schedule_id)
|
|
385
349
|
WHERE deadline_at_millis IS NOT NULL
|
|
386
350
|
`.withoutTransform;
|
|
387
|
-
|
|
388
|
-
}),
|
|
389
|
-
"6_durable_subscriptions": Effect.gen(function* () {
|
|
390
|
-
const sql = yield* SqlClient.SqlClient;
|
|
391
|
-
yield* sql`
|
|
351
|
+
yield* sql`
|
|
392
352
|
CREATE TABLE effect_agent_subscription_sequences (
|
|
393
353
|
tenant_id TEXT NOT NULL,
|
|
394
354
|
source_address TEXT NOT NULL,
|
|
@@ -399,7 +359,7 @@ const sqliteMigrations = SqliteMigrator.fromRecord({
|
|
|
399
359
|
PRIMARY KEY (tenant_id, source_address)
|
|
400
360
|
)
|
|
401
361
|
`.withoutTransform;
|
|
402
|
-
|
|
362
|
+
yield* sql`
|
|
403
363
|
CREATE TABLE effect_agent_subscriptions (
|
|
404
364
|
tenant_id TEXT NOT NULL,
|
|
405
365
|
source_address TEXT NOT NULL,
|
|
@@ -417,10 +377,10 @@ const sqliteMigrations = SqliteMigrator.fromRecord({
|
|
|
417
377
|
UNIQUE (tenant_id, source_address, ordinal)
|
|
418
378
|
)
|
|
419
379
|
`.withoutTransform;
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
380
|
+
yield* sql`CREATE INDEX effect_agent_subscriptions_owner ON effect_agent_subscriptions (tenant_id, source_address, owner_id, ordinal)`.withoutTransform;
|
|
381
|
+
yield* sql`CREATE INDEX effect_agent_subscriptions_candidates ON effect_agent_subscriptions (tenant_id, source_address, source_name, source_version, matching_key, ordinal)`.withoutTransform;
|
|
382
|
+
yield* sql`CREATE INDEX effect_agent_subscriptions_recovery ON effect_agent_subscriptions (tenant_id, source_address, recovery_at_millis, ordinal) WHERE recovery_at_millis IS NOT NULL`.withoutTransform;
|
|
383
|
+
yield* sql`
|
|
424
384
|
CREATE TABLE effect_agent_subscription_events (
|
|
425
385
|
tenant_id TEXT NOT NULL,
|
|
426
386
|
source_address TEXT NOT NULL,
|
|
@@ -437,8 +397,8 @@ const sqliteMigrations = SqliteMigrator.fromRecord({
|
|
|
437
397
|
PRIMARY KEY (tenant_id, source_address, event_id)
|
|
438
398
|
)
|
|
439
399
|
`.withoutTransform;
|
|
440
|
-
|
|
441
|
-
|
|
400
|
+
yield* sql`CREATE INDEX effect_agent_subscription_events_pending ON effect_agent_subscription_events (tenant_id, source_address, routing_complete, next_attempt_at_millis, event_id)`.withoutTransform;
|
|
401
|
+
yield* sql`
|
|
442
402
|
CREATE TABLE effect_agent_subscription_deliveries (
|
|
443
403
|
tenant_id TEXT NOT NULL,
|
|
444
404
|
source_address TEXT NOT NULL,
|
|
@@ -453,14 +413,308 @@ const sqliteMigrations = SqliteMigrator.fromRecord({
|
|
|
453
413
|
UNIQUE (tenant_id, source_address, delivery_key)
|
|
454
414
|
)
|
|
455
415
|
`.withoutTransform;
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
416
|
+
yield* sql`CREATE INDEX effect_agent_subscription_deliveries_pending ON effect_agent_subscription_deliveries (tenant_id, source_address, state, next_attempt_at_millis, delivery_key)`.withoutTransform;
|
|
417
|
+
yield* sql`CREATE INDEX effect_agent_subscription_deliveries_registration ON effect_agent_subscription_deliveries (tenant_id, source_address, owner_id, subscription_id, delivery_key)`.withoutTransform;
|
|
418
|
+
yield* sql`PRAGMA user_version = 7`.withoutTransform;
|
|
419
|
+
}) });
|
|
420
|
+
//#endregion
|
|
421
|
+
//#region src/sqlite-activity-store.ts
|
|
422
|
+
const STORAGE_VERSION = 1;
|
|
423
|
+
const METADATA_COMPONENT = "activity";
|
|
424
|
+
const STATE_TABLE = "effect_agent_activity_processor_state_v1";
|
|
425
|
+
const StoredJson$1 = Schema.String.check(Schema.isMaxLength(16777216));
|
|
426
|
+
const sameKey = Schema.toEquivalence(ActivityProcessorKey);
|
|
427
|
+
const sameWork = Schema.toEquivalence(PreparedActivity);
|
|
428
|
+
var ActivityMetadataRow = class extends Schema.Class("@effect-agent/storage-sqlite/ActivityMetadataRow")({ version: Schema.Int }) {};
|
|
429
|
+
var ActivityTableRow = class extends Schema.Class("@effect-agent/storage-sqlite/ActivityTableRow")({ name: Schema.NonEmptyString }) {};
|
|
430
|
+
var ActivityStateRow = class extends Schema.Class("@effect-agent/storage-sqlite/ActivityStateRow")({
|
|
431
|
+
processor_id: ActivityProcessorKey.fields.processorId,
|
|
432
|
+
processor_version: ActivityProcessorKey.fields.processorVersion,
|
|
433
|
+
thread_id: ActivityProcessorKey.fields.threadId,
|
|
434
|
+
format_version: Schema.Int,
|
|
435
|
+
through_sequence: ActivityProgress.fields.throughSequence,
|
|
436
|
+
epoch: ActivityProgress.fields.epoch,
|
|
437
|
+
owner: ActivityProgress.fields.owner,
|
|
438
|
+
lease_expires_at: ActivityProgress.fields.leaseExpiresAt,
|
|
439
|
+
progress_json: StoredJson$1
|
|
440
|
+
}) {};
|
|
441
|
+
var ActivityChangeCountRow = class extends Schema.Class("@effect-agent/storage-sqlite/ActivityChangeCountRow")({ changed: Schema.Int }) {};
|
|
442
|
+
const StoredVersionHeader = Schema.Struct({ version: Schema.Int });
|
|
443
|
+
const storeError$1 = (operation, reason = "unavailable") => ActivityStoreError.make({
|
|
444
|
+
operation,
|
|
445
|
+
reason
|
|
446
|
+
});
|
|
447
|
+
const query = (effect, operation) => effect.pipe(Effect.mapError(() => storeError$1(operation)));
|
|
448
|
+
const decodeRows$3 = Effect.fn("SqliteActivityStore.decodeRows")(function* (schema, rows, operation) {
|
|
449
|
+
return yield* Schema.decodeUnknownEffect(Schema.Array(schema))(rows).pipe(Effect.mapError(() => storeError$1(operation, "corrupt")));
|
|
450
|
+
});
|
|
451
|
+
const decodeInput$1 = Effect.fn("SqliteActivityStore.decodeInput")(function* (schema, value, operation) {
|
|
452
|
+
return yield* Schema.decodeUnknownEffect(schema)(value).pipe(Effect.mapError(() => storeError$1(operation, "invalid-input")));
|
|
453
|
+
});
|
|
454
|
+
const encodeProgress = Effect.fn("SqliteActivityStore.encodeProgress")(function* (progress, operation) {
|
|
455
|
+
return yield* Schema.encodeEffect(Schema.fromJsonString(ActivityProgress))(progress).pipe(Effect.mapError(() => storeError$1(operation, "corrupt")), Effect.flatMap((encoded) => Schema.decodeEffect(StoredJson$1)(encoded).pipe(Effect.mapError(() => storeError$1(operation, "invalid-input")))));
|
|
463
456
|
});
|
|
457
|
+
const decodeProgress = Effect.fn("SqliteActivityStore.decodeProgress")(function* (value, operation) {
|
|
458
|
+
if ((yield* Schema.decodeEffect(Schema.fromJsonString(StoredVersionHeader))(value).pipe(Effect.mapError(() => storeError$1(operation, "corrupt")))).version !== STORAGE_VERSION) return yield* storeError$1(operation, "incompatible");
|
|
459
|
+
const progress = yield* Schema.decodeEffect(Schema.fromJsonString(ActivityProgress))(value).pipe(Effect.mapError(() => storeError$1(operation, "corrupt")));
|
|
460
|
+
if ((yield* encodeProgress(progress, operation)) !== value) return yield* storeError$1(operation, "corrupt");
|
|
461
|
+
return progress;
|
|
462
|
+
});
|
|
463
|
+
const validateProgress = Effect.fn("SqliteActivityStore.validateProgress")(function* (progress, operation) {
|
|
464
|
+
if (progress.epoch < 1 || progress.owner === null && progress.leaseExpiresAt !== 0 || progress.pending !== null && (!sameKey(progress.pending.key, progress.key) || progress.pending.sequence !== progress.throughSequence + 1)) return yield* storeError$1(operation, "corrupt");
|
|
465
|
+
return progress;
|
|
466
|
+
});
|
|
467
|
+
const makeClaim = (progress) => progress.owner === null ? null : ActivityClaim.make({
|
|
468
|
+
key: progress.key,
|
|
469
|
+
owner: progress.owner,
|
|
470
|
+
epoch: progress.epoch,
|
|
471
|
+
throughSequence: progress.throughSequence,
|
|
472
|
+
leaseExpiresAt: progress.leaseExpiresAt,
|
|
473
|
+
pending: progress.pending
|
|
474
|
+
});
|
|
475
|
+
const ownershipLost = (claim) => ActivityOwnershipLost.make({
|
|
476
|
+
key: claim.key,
|
|
477
|
+
owner: claim.owner,
|
|
478
|
+
epoch: claim.epoch
|
|
479
|
+
});
|
|
480
|
+
const makeActivityStore = Effect.fn("SqliteActivityStore.make")(function* () {
|
|
481
|
+
const sql = yield* SqlClient.SqlClient;
|
|
482
|
+
const failpoint = yield* ActivityMutationFailpoint;
|
|
483
|
+
yield* failpoint.hit("activity:initialize:before");
|
|
484
|
+
yield* sql.withTransaction(Effect.gen(function* () {
|
|
485
|
+
yield* sql`
|
|
486
|
+
CREATE TABLE IF NOT EXISTS effect_agent_activity_metadata (
|
|
487
|
+
component TEXT PRIMARY KEY NOT NULL,
|
|
488
|
+
version INTEGER NOT NULL
|
|
489
|
+
)
|
|
490
|
+
`;
|
|
491
|
+
const metadataRows = yield* sql`
|
|
492
|
+
SELECT version FROM effect_agent_activity_metadata
|
|
493
|
+
WHERE component = ${METADATA_COMPONENT}
|
|
494
|
+
`;
|
|
495
|
+
const metadata = yield* decodeRows$3(ActivityMetadataRow, metadataRows, "decode activity schema version");
|
|
496
|
+
if (metadata.length > 1) return yield* storeError$1("decode activity schema version", "corrupt");
|
|
497
|
+
const currentVersion = metadata[0]?.version;
|
|
498
|
+
if (currentVersion !== void 0 && currentVersion !== STORAGE_VERSION) return yield* storeError$1("initialize activity schema", "incompatible");
|
|
499
|
+
if (currentVersion === void 0) {
|
|
500
|
+
const tableRows = yield* sql`
|
|
501
|
+
SELECT name FROM sqlite_master
|
|
502
|
+
WHERE type = 'table' AND name = ${STATE_TABLE}
|
|
503
|
+
`;
|
|
504
|
+
if ((yield* decodeRows$3(ActivityTableRow, tableRows, "inspect activity schema")).length > 0) return yield* storeError$1("initialize activity schema", "incompatible");
|
|
505
|
+
yield* sql`
|
|
506
|
+
CREATE TABLE effect_agent_activity_processor_state_v1 (
|
|
507
|
+
processor_id TEXT NOT NULL,
|
|
508
|
+
processor_version TEXT NOT NULL,
|
|
509
|
+
thread_id TEXT NOT NULL,
|
|
510
|
+
format_version INTEGER NOT NULL,
|
|
511
|
+
through_sequence INTEGER NOT NULL,
|
|
512
|
+
epoch INTEGER NOT NULL,
|
|
513
|
+
owner TEXT,
|
|
514
|
+
lease_expires_at REAL NOT NULL,
|
|
515
|
+
progress_json TEXT NOT NULL,
|
|
516
|
+
PRIMARY KEY (processor_id, processor_version, thread_id)
|
|
517
|
+
)
|
|
518
|
+
`;
|
|
519
|
+
yield* sql`
|
|
520
|
+
INSERT INTO effect_agent_activity_metadata (component, version)
|
|
521
|
+
VALUES (${METADATA_COMPONENT}, ${STORAGE_VERSION})
|
|
522
|
+
`;
|
|
523
|
+
}
|
|
524
|
+
yield* sql`
|
|
525
|
+
SELECT processor_id, processor_version, thread_id, format_version,
|
|
526
|
+
through_sequence, epoch, owner, lease_expires_at, progress_json
|
|
527
|
+
FROM effect_agent_activity_processor_state_v1
|
|
528
|
+
LIMIT 0
|
|
529
|
+
`;
|
|
530
|
+
})).pipe(Effect.catchTag("SqlError", () => Effect.fail(storeError$1("initialize activity schema"))));
|
|
531
|
+
yield* failpoint.hit("activity:initialize:after");
|
|
532
|
+
const readProgress = Effect.fn("SqliteActivityStore.readProgress")(function* (key, operation) {
|
|
533
|
+
const rawRows = yield* query(sql`
|
|
534
|
+
SELECT processor_id, processor_version, thread_id, format_version,
|
|
535
|
+
through_sequence, epoch, owner, lease_expires_at, progress_json
|
|
536
|
+
FROM effect_agent_activity_processor_state_v1
|
|
537
|
+
WHERE processor_id = ${key.processorId}
|
|
538
|
+
AND processor_version = ${key.processorVersion}
|
|
539
|
+
AND thread_id = ${key.threadId}
|
|
540
|
+
`, operation);
|
|
541
|
+
const rows = yield* decodeRows$3(ActivityStateRow, rawRows, operation);
|
|
542
|
+
if (rows.length === 0) return null;
|
|
543
|
+
if (rows.length !== 1) return yield* storeError$1(operation, "corrupt");
|
|
544
|
+
const row = rows[0];
|
|
545
|
+
if (row.format_version !== STORAGE_VERSION) return yield* storeError$1(operation, "incompatible");
|
|
546
|
+
const progress = yield* decodeProgress(row.progress_json, operation);
|
|
547
|
+
yield* validateProgress(progress, operation);
|
|
548
|
+
if (!sameKey(progress.key, key) || row.processor_id !== key.processorId || row.processor_version !== key.processorVersion || row.thread_id !== key.threadId || row.through_sequence !== progress.throughSequence || row.epoch !== progress.epoch || row.owner !== progress.owner || row.lease_expires_at !== progress.leaseExpiresAt) return yield* storeError$1(operation, "corrupt");
|
|
549
|
+
return progress;
|
|
550
|
+
});
|
|
551
|
+
const checkChanged = Effect.fn("SqliteActivityStore.checkChanged")(function* (operation) {
|
|
552
|
+
const rawRows = yield* query(sql`SELECT changes() AS changed`, operation);
|
|
553
|
+
const rows = yield* decodeRows$3(ActivityChangeCountRow, rawRows, operation);
|
|
554
|
+
if (rows.length !== 1 || rows[0].changed !== 1) return yield* storeError$1(operation, "corrupt");
|
|
555
|
+
});
|
|
556
|
+
const insertProgress = Effect.fn("SqliteActivityStore.insertProgress")(function* (progress, operation) {
|
|
557
|
+
const progressJson = yield* encodeProgress(progress, operation);
|
|
558
|
+
yield* sql`
|
|
559
|
+
INSERT INTO effect_agent_activity_processor_state_v1 (
|
|
560
|
+
processor_id, processor_version, thread_id, format_version, through_sequence,
|
|
561
|
+
epoch, owner, lease_expires_at, progress_json
|
|
562
|
+
) VALUES (
|
|
563
|
+
${progress.key.processorId}, ${progress.key.processorVersion}, ${progress.key.threadId},
|
|
564
|
+
${STORAGE_VERSION}, ${progress.throughSequence}, ${progress.epoch}, ${progress.owner},
|
|
565
|
+
${progress.leaseExpiresAt}, ${progressJson}
|
|
566
|
+
)
|
|
567
|
+
`;
|
|
568
|
+
yield* checkChanged(operation);
|
|
569
|
+
});
|
|
570
|
+
const updateProgress = Effect.fn("SqliteActivityStore.updateProgress")(function* (current, next, operation) {
|
|
571
|
+
const progressJson = yield* encodeProgress(next, operation);
|
|
572
|
+
yield* sql`
|
|
573
|
+
UPDATE effect_agent_activity_processor_state_v1
|
|
574
|
+
SET format_version = ${STORAGE_VERSION},
|
|
575
|
+
through_sequence = ${next.throughSequence},
|
|
576
|
+
epoch = ${next.epoch},
|
|
577
|
+
owner = ${next.owner},
|
|
578
|
+
lease_expires_at = ${next.leaseExpiresAt},
|
|
579
|
+
progress_json = ${progressJson}
|
|
580
|
+
WHERE processor_id = ${current.key.processorId}
|
|
581
|
+
AND processor_version = ${current.key.processorVersion}
|
|
582
|
+
AND thread_id = ${current.key.threadId}
|
|
583
|
+
AND through_sequence = ${current.throughSequence}
|
|
584
|
+
AND epoch = ${current.epoch}
|
|
585
|
+
`;
|
|
586
|
+
yield* checkChanged(operation);
|
|
587
|
+
});
|
|
588
|
+
const requireLive = Effect.fn("SqliteActivityStore.requireLive")(function* (progress, claim, requireSequence) {
|
|
589
|
+
const now = yield* Clock.currentTimeMillis;
|
|
590
|
+
if (progress === null || !sameKey(progress.key, claim.key) || progress.owner !== claim.owner || progress.epoch !== claim.epoch || progress.leaseExpiresAt <= now || requireSequence && progress.throughSequence !== claim.throughSequence) return yield* ownershipLost(claim);
|
|
591
|
+
return progress;
|
|
592
|
+
});
|
|
593
|
+
const inspect = Effect.fn("SqliteActivityStore.inspect")(function* (key) {
|
|
594
|
+
const decodedKey = yield* decodeInput$1(ActivityProcessorKey, key, "inspect activity progress");
|
|
595
|
+
return yield* readProgress(decodedKey, "inspect activity progress");
|
|
596
|
+
});
|
|
597
|
+
const claim = Effect.fn("SqliteActivityStore.claim")(function* (request) {
|
|
598
|
+
const operation = "claim activity progress";
|
|
599
|
+
const decoded = yield* decodeInput$1(ActivityClaimRequest, request, operation);
|
|
600
|
+
yield* failpoint.hit("activity:claim:before");
|
|
601
|
+
const claimed = yield* sql.withTransaction(Effect.gen(function* () {
|
|
602
|
+
const current = yield* readProgress(decoded.key, operation);
|
|
603
|
+
const now = yield* Clock.currentTimeMillis;
|
|
604
|
+
if (current !== null && current.owner !== null && current.leaseExpiresAt > now) return yield* ActivityBusy.make({
|
|
605
|
+
key: decoded.key,
|
|
606
|
+
leaseExpiresAt: current.leaseExpiresAt
|
|
607
|
+
});
|
|
608
|
+
const next = yield* Schema.decodeUnknownEffect(ActivityProgress)({
|
|
609
|
+
version: STORAGE_VERSION,
|
|
610
|
+
key: decoded.key,
|
|
611
|
+
throughSequence: current?.throughSequence ?? 0,
|
|
612
|
+
epoch: (current?.epoch ?? 0) + 1,
|
|
613
|
+
owner: decoded.owner,
|
|
614
|
+
leaseExpiresAt: now + decoded.leaseMillis,
|
|
615
|
+
pending: current?.pending ?? null,
|
|
616
|
+
advancedAt: current?.advancedAt ?? null
|
|
617
|
+
}).pipe(Effect.mapError(() => storeError$1(operation, "corrupt")));
|
|
618
|
+
if (current === null) yield* insertProgress(next, operation);
|
|
619
|
+
else yield* updateProgress(current, next, operation);
|
|
620
|
+
yield* failpoint.hit("activity:claim:after-state");
|
|
621
|
+
const result = makeClaim(next);
|
|
622
|
+
if (result === null) return yield* storeError$1(operation, "corrupt");
|
|
623
|
+
return result;
|
|
624
|
+
})).pipe(Effect.catchTag("SqlError", () => Effect.fail(storeError$1(operation))));
|
|
625
|
+
yield* failpoint.hit("activity:claim:after");
|
|
626
|
+
return claimed;
|
|
627
|
+
});
|
|
628
|
+
const prepare = Effect.fn("SqliteActivityStore.prepare")(function* (request) {
|
|
629
|
+
const operation = "prepare activity output";
|
|
630
|
+
const claim = yield* decodeInput$1(ActivityClaim, request.claim, operation);
|
|
631
|
+
const work = yield* decodeInput$1(PreparedActivity, request.work, operation);
|
|
632
|
+
yield* failpoint.hit("activity:prepare:before");
|
|
633
|
+
const result = yield* sql.withTransaction(Effect.gen(function* () {
|
|
634
|
+
const current = yield* requireLive(yield* readProgress(claim.key, operation), claim, true);
|
|
635
|
+
if (current.pending !== null) {
|
|
636
|
+
if (sameWork(current.pending, work)) return {
|
|
637
|
+
work: current.pending,
|
|
638
|
+
changed: false
|
|
639
|
+
};
|
|
640
|
+
return yield* ActivityWorkConflict.make({
|
|
641
|
+
key: claim.key,
|
|
642
|
+
workId: work.workId
|
|
643
|
+
});
|
|
644
|
+
}
|
|
645
|
+
if (!sameKey(work.key, claim.key) || work.sequence !== current.throughSequence + 1) return yield* ActivityWorkConflict.make({
|
|
646
|
+
key: claim.key,
|
|
647
|
+
workId: work.workId
|
|
648
|
+
});
|
|
649
|
+
const next = ActivityProgress.make({
|
|
650
|
+
...current,
|
|
651
|
+
pending: work
|
|
652
|
+
});
|
|
653
|
+
yield* updateProgress(current, next, operation);
|
|
654
|
+
yield* failpoint.hit("activity:prepare:after-state");
|
|
655
|
+
return {
|
|
656
|
+
work,
|
|
657
|
+
changed: true
|
|
658
|
+
};
|
|
659
|
+
})).pipe(Effect.catchTag("SqlError", () => Effect.fail(storeError$1(operation))));
|
|
660
|
+
if (result.changed) yield* failpoint.hit("activity:prepare:after");
|
|
661
|
+
return result.work;
|
|
662
|
+
});
|
|
663
|
+
const advance = Effect.fn("SqliteActivityStore.advance")(function* (request) {
|
|
664
|
+
const operation = "advance activity progress";
|
|
665
|
+
const claim = yield* decodeInput$1(ActivityClaim, request.claim, operation);
|
|
666
|
+
const workId = yield* decodeInput$1(Digest, request.workId, operation);
|
|
667
|
+
yield* failpoint.hit("activity:advance:before");
|
|
668
|
+
const nextClaim = yield* sql.withTransaction(Effect.gen(function* () {
|
|
669
|
+
const current = yield* requireLive(yield* readProgress(claim.key, operation), claim, true);
|
|
670
|
+
if (current.pending === null || current.pending.workId !== workId) return yield* ActivityWorkConflict.make({
|
|
671
|
+
key: claim.key,
|
|
672
|
+
workId
|
|
673
|
+
});
|
|
674
|
+
const next = ActivityProgress.make({
|
|
675
|
+
...current,
|
|
676
|
+
throughSequence: current.pending.sequence,
|
|
677
|
+
pending: null,
|
|
678
|
+
advancedAt: yield* Clock.currentTimeMillis
|
|
679
|
+
});
|
|
680
|
+
yield* updateProgress(current, next, operation);
|
|
681
|
+
yield* failpoint.hit("activity:advance:after-state");
|
|
682
|
+
const result = makeClaim(next);
|
|
683
|
+
if (result === null) return yield* storeError$1(operation, "corrupt");
|
|
684
|
+
return result;
|
|
685
|
+
})).pipe(Effect.catchTag("SqlError", () => Effect.fail(storeError$1(operation))));
|
|
686
|
+
yield* failpoint.hit("activity:advance:after");
|
|
687
|
+
return nextClaim;
|
|
688
|
+
});
|
|
689
|
+
const release = Effect.fn("SqliteActivityStore.release")(function* (claim) {
|
|
690
|
+
const operation = "release activity claim";
|
|
691
|
+
const decoded = yield* decodeInput$1(ActivityClaim, claim, operation);
|
|
692
|
+
yield* failpoint.hit("activity:release:before");
|
|
693
|
+
yield* sql.withTransaction(Effect.gen(function* () {
|
|
694
|
+
const current = yield* readProgress(decoded.key, operation);
|
|
695
|
+
if (current === null || current.owner !== decoded.owner || current.epoch !== decoded.epoch) return yield* ownershipLost(decoded);
|
|
696
|
+
const next = ActivityProgress.make({
|
|
697
|
+
...current,
|
|
698
|
+
owner: null,
|
|
699
|
+
leaseExpiresAt: 0
|
|
700
|
+
});
|
|
701
|
+
yield* updateProgress(current, next, operation);
|
|
702
|
+
yield* failpoint.hit("activity:release:after-state");
|
|
703
|
+
})).pipe(Effect.catchTag("SqlError", () => Effect.fail(storeError$1(operation))));
|
|
704
|
+
yield* failpoint.hit("activity:release:after");
|
|
705
|
+
});
|
|
706
|
+
return ActivityProcessorStore.of({
|
|
707
|
+
inspect,
|
|
708
|
+
claim,
|
|
709
|
+
prepare,
|
|
710
|
+
advance,
|
|
711
|
+
release
|
|
712
|
+
});
|
|
713
|
+
});
|
|
714
|
+
/** SQLite activity progress with mutation failpoints kept injectable for recovery tests. */
|
|
715
|
+
const activityProcessorStoreLayerWithFailpoints = Layer.effect(ActivityProcessorStore, makeActivityStore());
|
|
716
|
+
/** SQLite activity progress with the production no-op mutation failpoint. */
|
|
717
|
+
const activityProcessorStoreLayer = activityProcessorStoreLayerWithFailpoints.pipe(Layer.provide(ActivityMutationFailpoint.layer));
|
|
464
718
|
//#endregion
|
|
465
719
|
//#region src/sqlite-storage-config.ts
|
|
466
720
|
const ObservationPollInterval = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0));
|
|
@@ -493,11 +747,11 @@ var SqliteStorageConfigValue = class extends Schema.Class("@effect-agent/storage
|
|
|
493
747
|
var SqliteStorageConfig = class extends Context.Service()("@effect-agent/storage-sqlite/SqliteStorageConfig") {};
|
|
494
748
|
//#endregion
|
|
495
749
|
//#region src/sqlite-journal.ts
|
|
496
|
-
const BoundedStoredText$1 = Schema.String.check(Schema.isMaxLength(
|
|
750
|
+
const BoundedStoredText$1 = Schema.String.check(Schema.isMaxLength(16777216));
|
|
497
751
|
const BoundedIdentifier$1 = Schema.NonEmptyString.check(Schema.isMaxLength(1024));
|
|
498
752
|
const NonNegativeInt = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0));
|
|
499
753
|
const MAX_RECORDS_PER_THREAD = 65536;
|
|
500
|
-
const MAX_STORED_TEXT_BYTES =
|
|
754
|
+
const MAX_STORED_TEXT_BYTES = 16777216;
|
|
501
755
|
const MAX_IDENTIFIER_LENGTH = 1024;
|
|
502
756
|
const storedTextBytes = (value) => new TextEncoder().encode(value).byteLength;
|
|
503
757
|
var SqliteVersionRow = class extends Schema.Class("SqliteVersionRow")({ user_version: NonNegativeInt }) {};
|
|
@@ -1138,7 +1392,7 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
|
|
|
1138
1392
|
});
|
|
1139
1393
|
//#endregion
|
|
1140
1394
|
//#region src/sqlite-thread-store.ts
|
|
1141
|
-
const OffsetText = Schema.String.check(Schema.isMaxLength(
|
|
1395
|
+
const OffsetText = Schema.String.check(Schema.isMaxLength(4096));
|
|
1142
1396
|
const SQLITE_OFFSET_PREFIX = "effect-agent-sqlite@1:";
|
|
1143
1397
|
const ZERO_CANONICAL_SEQUENCE = Schema.decodeSync(CanonicalSequence)(0);
|
|
1144
1398
|
const isDigest = Schema.is(Digest);
|
|
@@ -1541,7 +1795,7 @@ const layer = (options) => Layer.unwrap(Effect.map(SqliteStorageConfig, (config)
|
|
|
1541
1795
|
const observationOffsetAt = makeOffset;
|
|
1542
1796
|
//#endregion
|
|
1543
1797
|
//#region src/sqlite-ledger.ts
|
|
1544
|
-
const BoundedStoredText = Schema.String.check(Schema.isMaxLength(
|
|
1798
|
+
const BoundedStoredText = Schema.String.check(Schema.isMaxLength(16777216));
|
|
1545
1799
|
const BoundedIdentifier = Schema.NonEmptyString.check(Schema.isMaxLength(1024));
|
|
1546
1800
|
const BoundedTimestamp = Schema.NonEmptyString.check(Schema.isMaxLength(128));
|
|
1547
1801
|
const SCAN_PAGE_SIZE = 256;
|
|
@@ -2395,7 +2649,8 @@ const makeServices = Effect.fn("SqliteSubmissionLedger.makeServices")(function*
|
|
|
2395
2649
|
submissionId: validated.submissionId,
|
|
2396
2650
|
existingOutcome: reservation.value.outcome
|
|
2397
2651
|
});
|
|
2398
|
-
const
|
|
2652
|
+
const reservationRecord = yield* decodeRecordEnvelopeText(reservation.value.record_json).pipe(Effect.mapError((error) => corruptionFailure(operation, "effect_agent_settlement_reservations", validated.submissionId, error.message)));
|
|
2653
|
+
const settlementFailure = settlementFailureFromRecord(reservationRecord);
|
|
2399
2654
|
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.");
|
|
2400
2655
|
const submission = yield* requireSubmission(operation, validated.submissionId);
|
|
2401
2656
|
if (submission.state === "settled") {
|
|
@@ -3176,7 +3431,7 @@ const submissionLedgerLayer = Layer.effectContext(makeServices());
|
|
|
3176
3431
|
const ledgerLayer = (options) => Layer.unwrap(Effect.map(SqliteStorageConfig, (config) => submissionLedgerLayer.pipe(Layer.provide(Layer.mergeAll(Layer.succeed(SqliteStorageConfig)(config), storageFailpointLayer(options), SqliteClient.layer({ filename: options.filename }), NodeCrypto.layer))))).pipe(Layer.provide(storageConfigLayer(options)));
|
|
3177
3432
|
//#endregion
|
|
3178
3433
|
//#region src/sqlite-schedule-store.ts
|
|
3179
|
-
const StoredScheduleJson = Schema.String.check(Schema.isMaxLength(
|
|
3434
|
+
const StoredScheduleJson = Schema.String.check(Schema.isMaxLength(16777216));
|
|
3180
3435
|
const StoredDeadline = Schema.NullOr(ScheduleInstant);
|
|
3181
3436
|
var ScheduleRow = class extends Schema.Class("@effect-agent/storage-sqlite/ScheduleRow")({
|
|
3182
3437
|
tenant_id: ScheduleOwner.fields.tenantId,
|
|
@@ -3421,7 +3676,7 @@ const makeScheduleStore = Effect.gen(function* () {
|
|
|
3421
3676
|
const scheduleStoreLayer = Layer.effect(ScheduleStore)(makeScheduleStore);
|
|
3422
3677
|
//#endregion
|
|
3423
3678
|
//#region src/sqlite-subscription-store.ts
|
|
3424
|
-
const StoredJson = Schema.String.check(Schema.isMaxLength(
|
|
3679
|
+
const StoredJson = Schema.String.check(Schema.isMaxLength(16777216));
|
|
3425
3680
|
const CountRow = Schema.Struct({ count: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)) });
|
|
3426
3681
|
const SequenceRow = Schema.Struct({ sequence: Schema.Natural });
|
|
3427
3682
|
const ScanRow = Schema.Struct({
|
|
@@ -3814,7 +4069,8 @@ const makeSubscriptionStore = Effect.fn("SqliteSubscriptionStore.make")(function
|
|
|
3814
4069
|
return false;
|
|
3815
4070
|
}
|
|
3816
4071
|
yield* failpoint.hit("subscription:catch-up:before");
|
|
3817
|
-
|
|
4072
|
+
const effectiveNowMillis = Math.max(nowMillis, yield* Clock.currentTimeMillis);
|
|
4073
|
+
if (!subscriptionCanSelect(record, accepted, effectiveNowMillis, true)) return yield* error("conflict", "catch-up-eligibility");
|
|
3818
4074
|
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");
|
|
3819
4075
|
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");
|
|
3820
4076
|
yield* insertDelivery(delivery);
|
|
@@ -4004,6 +4260,6 @@ const makeSubscriptionStore = Effect.fn("SqliteSubscriptionStore.make")(function
|
|
|
4004
4260
|
});
|
|
4005
4261
|
const subscriptionStoreLayer = (partition) => Layer.effect(SubscriptionStore, makeSubscriptionStore(partition));
|
|
4006
4262
|
//#endregion
|
|
4007
|
-
export { CurrentSqliteStorageVersion, SqliteAppendConflict, SqliteCheckpointConflict, SqliteFenceRejected, SqliteLedgerError, SqliteStorageCompatibilityError, SqliteStorageConfig, SqliteStorageConfigValue, SqliteStorageCorruptionError, SqliteStorageError, SqliteStorageFailpoint, SqliteStorageFailpointError, SqliteStorageFailpointLocation, SqliteWriteContention, layer, ledgerLayer, observationOffsetAt, scheduleStoreLayer, storageConfigLayer, storageFailpointLayer, submissionLedgerLayer, subscriptionStoreLayer, threadStoreLayer };
|
|
4263
|
+
export { CurrentSqliteStorageVersion, SqliteAppendConflict, SqliteCheckpointConflict, SqliteFenceRejected, SqliteLedgerError, SqliteStorageCompatibilityError, SqliteStorageConfig, SqliteStorageConfigValue, SqliteStorageCorruptionError, SqliteStorageError, SqliteStorageFailpoint, SqliteStorageFailpointError, SqliteStorageFailpointLocation, SqliteWriteContention, activityProcessorStoreLayer, activityProcessorStoreLayerWithFailpoints, layer, ledgerLayer, memoryReaderLayer, memoryStoreLayer, memoryStoreLayerWithFailpoints, observationOffsetAt, scheduleStoreLayer, storageConfigLayer, storageFailpointLayer, submissionLedgerLayer, subscriptionStoreLayer, threadStoreLayer };
|
|
4008
4264
|
|
|
4009
4265
|
//# sourceMappingURL=index.mjs.map
|