@yielded/agent-platform-cloudflare 0.1.0-beta.174 → 0.1.0-beta.176
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/{Alarm-4J9B8Fg8.mjs → Alarm-7uipp6LW.mjs} +155 -117
- package/dist/Alarm-7uipp6LW.mjs.map +1 -0
- package/dist/Alarm.d.mts +2 -0
- package/dist/Alarm.mjs +1 -1
- package/dist/CloudflareScheduling.mjs +2 -2
- package/dist/CloudflareSubscriptions.mjs +2 -2
- package/dist/{CloudflareThreadClient-lTm6baDP.d.mts → CloudflareThreadClient-HO_3rkM7.d.mts} +362 -362
- package/dist/{CloudflareThreadClient-DU548EEj.mjs → CloudflareThreadClient-bA3lGA_2.mjs} +4 -4
- package/dist/CloudflareThreadClient-bA3lGA_2.mjs.map +1 -0
- package/dist/CloudflareThreadClient.d.mts +1 -1
- package/dist/CloudflareThreadClient.mjs +1 -1
- package/dist/{ThreadObject-BLYgzcdT.d.mts → ThreadObject-CxNlhoPL.d.mts} +13 -13
- package/dist/{ThreadObject-C2LF3btz.mjs → ThreadObject-SNcCsrS2.mjs} +52 -50
- package/dist/ThreadObject-SNcCsrS2.mjs.map +1 -0
- package/dist/ThreadObject.d.mts +1 -1
- package/dist/ThreadObject.mjs +1 -1
- package/dist/WakeScheduler.mjs +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +3 -3
- package/dist/{prepared-admission-BoUPHSNQ.mjs → prepared-admission-BvMiFR41.mjs} +2 -2
- package/dist/{prepared-admission-BoUPHSNQ.mjs.map → prepared-admission-BvMiFR41.mjs.map} +1 -1
- package/package.json +1 -1
- package/src/Alarm.ts +295 -201
- package/src/CloudflareThreadClient.ts +3 -2
- package/src/ThreadObject.ts +17 -22
- package/src/internal/layers.ts +124 -82
- package/src/internal/message-delivery.ts +61 -37
- package/dist/Alarm-4J9B8Fg8.mjs.map +0 -1
- package/dist/CloudflareThreadClient-DU548EEj.mjs.map +0 -1
- package/dist/ThreadObject-C2LF3btz.mjs.map +0 -1
|
@@ -410,49 +410,48 @@ const makeAlarmOperation = Effect.gen(function* () {
|
|
|
410
410
|
const queue = make(ctx.storage);
|
|
411
411
|
const transaction = (body) => alarms.transaction((mutations) => Effect.withFiber((owner) => {
|
|
412
412
|
let active = true;
|
|
413
|
-
|
|
414
|
-
operation: "enroll maintenance source",
|
|
415
|
-
message: "Source intent requires its active transaction callback's fiber"
|
|
416
|
-
})));
|
|
417
|
-
return body.pipe(Effect.provideService(CurrentCheckpoint, {
|
|
413
|
+
return Effect.onExitPrimitive(body(owner).pipe(Effect.provideService(CurrentCheckpoint, {
|
|
418
414
|
mutations,
|
|
419
|
-
|
|
420
|
-
}),
|
|
415
|
+
isActive: (fiber) => active && fiber === owner
|
|
416
|
+
})), () => {
|
|
421
417
|
active = false;
|
|
422
|
-
})
|
|
418
|
+
});
|
|
423
419
|
}), { sqlClient: sql }).pipe(Effect.mapError((cause) => cause instanceof DurableObjectStorage.StorageOperationError ? SqlError.make({ reason: UnknownError.make({
|
|
424
420
|
operation: "commit maintenance checkpoint",
|
|
425
421
|
message: "Source facts and maintenance checkpoint could not commit",
|
|
426
422
|
cause
|
|
427
423
|
}) }) : cause));
|
|
428
|
-
const withTransaction = (body) => Effect.
|
|
424
|
+
const withTransaction = (body) => Effect.withFiber((fiber) => {
|
|
425
|
+
const ambient = Context.getOption(fiber.context, sql.transactionService);
|
|
429
426
|
if (ambient._tag === "Some" && !ownsTransaction(ctx.storage, ambient.value[1])) return Effect.fail(SqlError.make({ reason: UnknownError.make({
|
|
430
427
|
operation: "begin maintenance source transaction",
|
|
431
428
|
message: "Use ThreadMutationGate.withTransaction at the outermost source transaction",
|
|
432
429
|
cause: "Unwrapped SQL transaction cannot own buffered maintenance intent"
|
|
433
430
|
}) }));
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
431
|
+
let frame;
|
|
432
|
+
return Effect.uninterruptibleMask((restore) => Effect.onExitPrimitive(transaction((owner) => {
|
|
433
|
+
const current = Context.getOption(owner.context, sql.transactionService);
|
|
434
|
+
if (current._tag === "None") return SqlError.make({ reason: UnknownError.make({
|
|
435
|
+
operation: "begin maintenance source transaction",
|
|
436
|
+
message: "SQL transaction unavailable",
|
|
437
|
+
cause: "SQL transaction unavailable"
|
|
438
|
+
}) });
|
|
439
|
+
const started = queue.begin(current.value[1]);
|
|
440
|
+
frame = started;
|
|
441
|
+
return Effect.flatMap(restore(body), (value) => Effect.try({
|
|
444
442
|
try: () => {
|
|
445
|
-
|
|
443
|
+
queue.flush(started);
|
|
444
|
+
return value;
|
|
446
445
|
},
|
|
447
446
|
catch: (cause) => SqlError.make({ reason: UnknownError.make({
|
|
448
447
|
cause,
|
|
449
448
|
operation: "flush maintenance due queue",
|
|
450
449
|
message: "Maintenance intent could not commit"
|
|
451
450
|
}) })
|
|
452
|
-
}))
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
}));
|
|
451
|
+
}));
|
|
452
|
+
}), (exit) => {
|
|
453
|
+
if (frame !== void 0) queue.finish(frame, Exit.isSuccess(exit));
|
|
454
|
+
}).pipe(Effect.provideService(Scheduler.PreventSchedulerYield, true)));
|
|
456
455
|
}).pipe(Effect.provideService(SqlClient, sql));
|
|
457
456
|
const run = (operation, execute) => {
|
|
458
457
|
const commit = Effect.withFiber((fiber) => {
|
|
@@ -461,28 +460,30 @@ const makeAlarmOperation = Effect.gen(function* () {
|
|
|
461
460
|
operation: "checkpoint",
|
|
462
461
|
message: "Maintenance checkpoint transaction unavailable"
|
|
463
462
|
}));
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
463
|
+
if (!tx.isActive(fiber)) return Effect.fail(DurableAlarmError.make({
|
|
464
|
+
operation: "enroll maintenance source",
|
|
465
|
+
message: "Source intent requires its active transaction callback's fiber"
|
|
466
|
+
}));
|
|
467
|
+
let checkpoint = Effect.void;
|
|
468
|
+
const intent = {
|
|
469
|
+
at: (at) => {
|
|
470
|
+
checkpoint = tx.mutations.scheduleAlarm(maintenanceAlarmInput(at));
|
|
471
|
+
},
|
|
472
|
+
earlier: (at) => {
|
|
473
|
+
checkpoint = tx.mutations.scheduleAlarmEarlier(maintenanceAlarmInput(at));
|
|
474
|
+
},
|
|
475
|
+
cancel: () => {
|
|
476
|
+
checkpoint = tx.mutations.cancelAlarm(maintenanceAlarmRef);
|
|
477
|
+
}
|
|
478
|
+
};
|
|
479
|
+
return Effect.tryPromise({
|
|
480
|
+
try: () => execute(ctx.storage, intent),
|
|
481
|
+
catch: alarmFailure(operation)
|
|
482
|
+
}).pipe(Effect.tap(() => checkpoint));
|
|
482
483
|
});
|
|
483
484
|
return Effect.withFiber((fiber) => {
|
|
484
485
|
if (fiber.getRef(CurrentCheckpoint) !== void 0) return commit;
|
|
485
|
-
return Context.getOption(fiber.context, sql.transactionService)._tag === "Some" && !buffering(ctx.storage) ? transaction(commit).pipe(Effect.ensuring(Effect.sync(() => invalidate(ctx.storage)))) : withTransaction(commit);
|
|
486
|
+
return Context.getOption(fiber.context, sql.transactionService)._tag === "Some" && !buffering(ctx.storage) ? transaction(() => commit).pipe(Effect.ensuring(Effect.sync(() => invalidate(ctx.storage)))) : withTransaction(commit);
|
|
486
487
|
}).pipe(Effect.uninterruptible, Effect.mapError(alarmFailure(operation)));
|
|
487
488
|
};
|
|
488
489
|
return {
|
|
@@ -624,6 +625,14 @@ const recoveryEvent = (fault, submissionId, transition, occurredAt) => ({
|
|
|
624
625
|
firstFailedAt: fault.firstFailedAt,
|
|
625
626
|
failure: fault.failure
|
|
626
627
|
});
|
|
628
|
+
/** Observe already-owned waves without creating one waiter fiber for each wave. */
|
|
629
|
+
const awaitAnyCompletion = Effect.fnUntraced(function* (fibers, revision) {
|
|
630
|
+
const mutations = yield* ThreadMutationGate;
|
|
631
|
+
return yield* Effect.acquireUseRelease(Effect.sync(() => []), (observers) => Effect.callback((resume) => {
|
|
632
|
+
observers.push(mutations.observeChange(revision, () => resume(Effect.succeed("scan"))));
|
|
633
|
+
for (const fiber of fibers) observers.push(fiber.addObserver(() => resume(Effect.succeed("completed"))));
|
|
634
|
+
}), (observers) => Effect.sync(() => observers.forEach((remove) => remove())));
|
|
635
|
+
});
|
|
627
636
|
/** Post-native delivery shares a finite connection budget across independent host lanes. */
|
|
628
637
|
const afterNativeDispatchConcurrency = 2;
|
|
629
638
|
const NativeWorkCursor = Schema.Struct({
|
|
@@ -709,12 +718,22 @@ var ThreadMutationGate = class ThreadMutationGate extends Context.Service()("@ef
|
|
|
709
718
|
const activeLanes = /* @__PURE__ */ new Map();
|
|
710
719
|
const generationGate = yield* Semaphore.make(1);
|
|
711
720
|
let revision = 0;
|
|
712
|
-
|
|
713
|
-
const
|
|
714
|
-
|
|
715
|
-
|
|
721
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
722
|
+
const observeChange = (observed, listener) => {
|
|
723
|
+
if (observed !== revision) {
|
|
724
|
+
listener();
|
|
725
|
+
return () => {};
|
|
726
|
+
}
|
|
727
|
+
listeners.add(listener);
|
|
728
|
+
return () => {
|
|
729
|
+
listeners.delete(listener);
|
|
730
|
+
};
|
|
731
|
+
};
|
|
732
|
+
const notify = Effect.sync(() => {
|
|
716
733
|
revision++;
|
|
717
|
-
|
|
734
|
+
const pending = [...listeners];
|
|
735
|
+
listeners.clear();
|
|
736
|
+
for (const listener of pending) listener();
|
|
718
737
|
});
|
|
719
738
|
const minimumAlarmDelay = Math.max(1, Math.ceil(config.alarmBackoffBase / 2));
|
|
720
739
|
const runTransaction = yield* makeStorageOperation;
|
|
@@ -740,8 +759,8 @@ var ThreadMutationGate = class ThreadMutationGate extends Context.Service()("@ef
|
|
|
740
759
|
dirty: state.dirty + 1n
|
|
741
760
|
})));
|
|
742
761
|
}
|
|
743
|
-
const next$
|
|
744
|
-
if (Number.isFinite(next$
|
|
762
|
+
const next$2 = next(dueQueue.read());
|
|
763
|
+
if (Number.isFinite(next$2)) checkpoint.earlier(Math.max(next$2, now + minimumAlarmDelay));
|
|
745
764
|
};
|
|
746
765
|
yield* runAlarmTransaction("schedule maintenance lane", enroll);
|
|
747
766
|
yield* notify;
|
|
@@ -818,7 +837,11 @@ var ThreadMutationGate = class ThreadMutationGate extends Context.Service()("@ef
|
|
|
818
837
|
recordProgress,
|
|
819
838
|
activeLanes: Effect.sync(() => new Set(activeLanes.keys())),
|
|
820
839
|
revision: Effect.sync(() => revision),
|
|
821
|
-
|
|
840
|
+
observeChange,
|
|
841
|
+
awaitChange: (observed) => Effect.callback((resume) => {
|
|
842
|
+
const remove = observeChange(observed, () => resume(Effect.void));
|
|
843
|
+
return Effect.sync(remove);
|
|
844
|
+
}),
|
|
822
845
|
withSnapshot: (body) => generationGate.withPermit(Effect.flatMap(Ref.get(activeMutations), body))
|
|
823
846
|
});
|
|
824
847
|
}));
|
|
@@ -849,6 +872,7 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
849
872
|
const runtime = yield* DurableAgentRuntime;
|
|
850
873
|
const recoveryConfig = yield* DurableRuntimeConfig;
|
|
851
874
|
const ledger = yield* SubmissionLedger;
|
|
875
|
+
const listNonterminal = ledger.listNonterminal ?? Stream.runCollect(ledger.scanNonterminal);
|
|
852
876
|
const wakes = yield* WakeScheduler;
|
|
853
877
|
const hints = yield* DurableAlarmService;
|
|
854
878
|
const alarms = yield* ThreadMaintenanceAlarm;
|
|
@@ -865,6 +889,8 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
865
889
|
const messages = yield* ThreadMessageDelivery;
|
|
866
890
|
const host = yield* ThreadHostMaintenance;
|
|
867
891
|
const framework = yield* ThreadNativeMaintenance;
|
|
892
|
+
const placement = yield* Effect.serviceOption(ThreadObjectPlacement);
|
|
893
|
+
const nativeThread = Option.isSome(placement) ? placement.value.threadId : void 0;
|
|
868
894
|
const nativeDispatchConcurrency = () => framework.singleThreadRuntime === runtime ? 1 : 2;
|
|
869
895
|
for (const lane of host.lanes) yield* Schema.decodeEffect(HostLaneId)(lane.id).pipe(Effect.mapError(alarmFailure("maintenance lane ID")));
|
|
870
896
|
const recoveryEvents = Option.getOrElse(yield* Effect.serviceOption(ThreadRecoveryEvents), () => ThreadRecoveryEvents.of({ publish: () => Effect.void }));
|
|
@@ -914,8 +940,8 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
914
940
|
const now = yield* Clock.currentTimeMillis;
|
|
915
941
|
const claimed = yield* runAlarmTransaction("charge maintenance attempt", async (_transaction, checkpoint) => {
|
|
916
942
|
const claimed = dueQueue.claim(selected, now);
|
|
917
|
-
const next$
|
|
918
|
-
if (Number.isFinite(next$
|
|
943
|
+
const next$3 = next(dueQueue.read());
|
|
944
|
+
if (Number.isFinite(next$3)) checkpoint.at(Math.max(now + minimumAlarmDelay, next$3));
|
|
919
945
|
else checkpoint.cancel();
|
|
920
946
|
return claimed;
|
|
921
947
|
});
|
|
@@ -1008,7 +1034,7 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
1008
1034
|
for (const blocked of result.blocked) threads.set(blocked.threadId, blocked.failure);
|
|
1009
1035
|
if (threads.size === 0 || [...threads].every(([threadId, failure]) => failure === void 0 && recovery.loaded.has(threadId) && !recovery.faults.has(threadId))) return /* @__PURE__ */ new Map();
|
|
1010
1036
|
const now = yield* Clock.currentTimeMillis;
|
|
1011
|
-
const submissions = current ?? (result.blocked.length === 0 ? [] : yield*
|
|
1037
|
+
const submissions = current ?? (result.blocked.length === 0 ? [] : yield* listNonterminal);
|
|
1012
1038
|
yield* failpoint.hit("maintenance:recovery-status:before");
|
|
1013
1039
|
const retained = yield* runTransaction("record Thread recovery faults", () => dueQueue.transaction(async (transaction) => {
|
|
1014
1040
|
const events = [];
|
|
@@ -1078,6 +1104,7 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
1078
1104
|
do {
|
|
1079
1105
|
const result = yield* runtime.runRecovery({
|
|
1080
1106
|
threadId,
|
|
1107
|
+
deferUnclaimedAdmissions: true,
|
|
1081
1108
|
...cursor === void 0 ? {} : { cursor }
|
|
1082
1109
|
}).pipe(Effect.provideService(CurrentNativeSource, true));
|
|
1083
1110
|
const faults = yield* recordRecoveryFaults(result, recovery, void 0, threadId);
|
|
@@ -1124,8 +1151,8 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
1124
1151
|
if (!initialized) await transaction.put(MAINTENANCE_STATE_KEY, encodeMaintenanceState(state));
|
|
1125
1152
|
const native = state.dirty > state.processed ? state.retry?.generation === state.dirty ? state.retry.notBefore : rows.find((row) => row.id === "effect-agent:native")?.dueAt ?? now + minimumAlarmDelay : null;
|
|
1126
1153
|
dueQueue.checkpointNative(native);
|
|
1127
|
-
const next$
|
|
1128
|
-
if (Number.isFinite(next$
|
|
1154
|
+
const next$1 = next(dueQueue.read());
|
|
1155
|
+
if (Number.isFinite(next$1)) checkpoint.earlier(Math.max(now + minimumAlarmDelay, next$1));
|
|
1129
1156
|
});
|
|
1130
1157
|
yield* failpoint.hit("maintenance:ensure:after");
|
|
1131
1158
|
});
|
|
@@ -1199,8 +1226,8 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
1199
1226
|
const charged = observed.charged.get(row.id) === row.revision ? row : dueQueue.claim(row, now);
|
|
1200
1227
|
if (charged !== void 0) dueQueue.complete(charged, now + backoffDelay(charged.stalls, jitter));
|
|
1201
1228
|
}
|
|
1202
|
-
const next$
|
|
1203
|
-
if (Number.isFinite(next$
|
|
1229
|
+
const next$4 = next(dueQueue.read());
|
|
1230
|
+
if (Number.isFinite(next$4)) checkpoint.at(Math.max(now + minimumAlarmDelay, next$4));
|
|
1204
1231
|
else checkpoint.cancel();
|
|
1205
1232
|
});
|
|
1206
1233
|
}));
|
|
@@ -1291,11 +1318,14 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
1291
1318
|
const { state } = await readMaintenanceState(ctx.storage);
|
|
1292
1319
|
return {
|
|
1293
1320
|
scannedGeneration: state.dirty,
|
|
1294
|
-
afterWorkThread: state.lastRecoveredThreadId
|
|
1321
|
+
afterWorkThread: framework.singleThreadRuntime === runtime && state.lastRecoveredThreadId === nativeThread ? void 0 : state.lastRecoveredThreadId
|
|
1295
1322
|
};
|
|
1296
1323
|
});
|
|
1297
|
-
const current = yield*
|
|
1298
|
-
let workOwners =
|
|
1324
|
+
const current = yield* listNonterminal;
|
|
1325
|
+
let workOwners = framework.singleThreadRuntime === runtime && nativeThread !== void 0 && current.some((submission) => submission.threadId === nativeThread) ? {
|
|
1326
|
+
threadIds: [nativeThread],
|
|
1327
|
+
afterThreadId: void 0
|
|
1328
|
+
} : yield* runtime.discoverWorkThreads({
|
|
1299
1329
|
limit: 32,
|
|
1300
1330
|
...afterWorkThread === void 0 ? {} : { afterThreadId: afterWorkThread }
|
|
1301
1331
|
}).pipe(Effect.provideService(CurrentNativeSource, true));
|
|
@@ -1419,7 +1449,7 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
1419
1449
|
nextAttemptAt: void 0,
|
|
1420
1450
|
dispatched: selection.selected.length > 0
|
|
1421
1451
|
};
|
|
1422
|
-
const remaining = yield*
|
|
1452
|
+
const remaining = yield* listNonterminal;
|
|
1423
1453
|
const waitingHeads = /* @__PURE__ */ new Map();
|
|
1424
1454
|
const autonomous = recovery.pending.size > 0 || recovery.discoveryPending || recoveryFaults.size > 0 || recovery.retryAtMillis !== void 0 || remaining.some((snapshot) => {
|
|
1425
1455
|
if (snapshot.state === "unknown" && waiting(snapshot)) return false;
|
|
@@ -1494,7 +1524,8 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
1494
1524
|
});
|
|
1495
1525
|
});
|
|
1496
1526
|
const dispatch = Effect.fnUntraced(function* (yieldAfter, dispatchUntil, observed) {
|
|
1497
|
-
const
|
|
1527
|
+
const leanSelection = framework.singleThreadRuntime === runtime && publication === emptyPublication && host.lanes.length === 0 && framework.lanes.length === 0;
|
|
1528
|
+
const notified = leanSelection ? Effect.never : (yield* Stream.toPull(wakes.wakes)).pipe(Effect.asVoid, Effect.catch(() => Effect.never));
|
|
1498
1529
|
const started = yield* beginNative(observed);
|
|
1499
1530
|
yield* mutations.withSnapshot(() => Effect.gen(function* () {
|
|
1500
1531
|
const queued = yield* queueSnapshot;
|
|
@@ -1531,8 +1562,35 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
1531
1562
|
repaired: false,
|
|
1532
1563
|
discoveryPending: false
|
|
1533
1564
|
};
|
|
1534
|
-
|
|
1535
|
-
|
|
1565
|
+
let recoveryFiber;
|
|
1566
|
+
let backfill;
|
|
1567
|
+
const dispatch = {
|
|
1568
|
+
scope: auxiliaryScope,
|
|
1569
|
+
active: /* @__PURE__ */ new Map(),
|
|
1570
|
+
deferred: /* @__PURE__ */ new Set(),
|
|
1571
|
+
dispatched: 0,
|
|
1572
|
+
settled: 0,
|
|
1573
|
+
progressed: false,
|
|
1574
|
+
needsCheckpoint: false
|
|
1575
|
+
};
|
|
1576
|
+
let native;
|
|
1577
|
+
let result;
|
|
1578
|
+
let backlog;
|
|
1579
|
+
if (leanSelection) {
|
|
1580
|
+
result = yield* advance(started, yieldAfter, observed, recovery, dispatch);
|
|
1581
|
+
recovery.started = true;
|
|
1582
|
+
yield* Deferred.succeed(recovery.queue, []);
|
|
1583
|
+
backlog = yield* Deferred.await(recovery.queue);
|
|
1584
|
+
} else {
|
|
1585
|
+
native = yield* fork(advance(started, yieldAfter, observed, recovery, dispatch));
|
|
1586
|
+
result = {
|
|
1587
|
+
phase: "caught-up",
|
|
1588
|
+
nonterminal: started.nonterminal,
|
|
1589
|
+
nextAttemptAt: void 0
|
|
1590
|
+
};
|
|
1591
|
+
}
|
|
1592
|
+
if (backlog === void 0 || backlog.length > 0) recoveryFiber = yield* fork(Effect.gen(function* () {
|
|
1593
|
+
for (const threadId of backlog ?? (yield* Deferred.await(recovery.queue))) {
|
|
1536
1594
|
yield* failpoint.hit("maintenance:select:before");
|
|
1537
1595
|
yield* runTransaction("select old recovery lane", () => dueQueue.transaction(async (transaction) => {
|
|
1538
1596
|
const { state } = await readMaintenanceState(transaction);
|
|
@@ -1547,31 +1605,11 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
1547
1605
|
if (!recovery.faults.has(threadId)) yield* wakes.notify(threadId);
|
|
1548
1606
|
}
|
|
1549
1607
|
}));
|
|
1550
|
-
const
|
|
1551
|
-
|
|
1552
|
-
const row = (yield* queueSnapshot).find((row) => row.id === Projection);
|
|
1553
|
-
if (row?.dueAt === null || row === void 0 || row.dueAt > (yield* Clock.currentTimeMillis)) return;
|
|
1554
|
-
return yield* runQueued(row, projection.drain.pipe(Effect.andThen(projection.pendingDeadline)), observed).pipe(Effect.timeoutOption(config.projectionDispatchTimeoutMillis));
|
|
1555
|
-
}));
|
|
1556
|
-
let backfillObserved = false;
|
|
1557
|
-
let recoveryObserved = false;
|
|
1558
|
-
const dispatch = {
|
|
1559
|
-
scope: auxiliaryScope,
|
|
1560
|
-
active: /* @__PURE__ */ new Map(),
|
|
1561
|
-
deferred: /* @__PURE__ */ new Set(),
|
|
1562
|
-
dispatched: 0,
|
|
1563
|
-
settled: 0,
|
|
1564
|
-
progressed: false,
|
|
1565
|
-
needsCheckpoint: false
|
|
1566
|
-
};
|
|
1567
|
-
let native = yield* fork(advance(started, yieldAfter, observed, recovery, dispatch));
|
|
1568
|
-
let result = {
|
|
1569
|
-
phase: "caught-up",
|
|
1570
|
-
nonterminal: started.nonterminal,
|
|
1571
|
-
nextAttemptAt: void 0
|
|
1572
|
-
};
|
|
1608
|
+
const projectionRow = (yield* queueSnapshot).find((row) => row.id === Projection);
|
|
1609
|
+
if (projectionRow !== void 0 && projectionRow.dueAt !== null && projectionRow.dueAt <= (yield* Clock.currentTimeMillis) && !(yield* mutations.activeLanes).has("effect-agent:projection")) backfill = yield* fork(runQueued(projectionRow, projection.drain.pipe(Effect.andThen(projection.pendingDeadline)), observed).pipe(Effect.timeoutOption(config.projectionDispatchTimeoutMillis), Effect.asVoid));
|
|
1573
1610
|
let phase = result.phase;
|
|
1574
|
-
let nativeCheck =
|
|
1611
|
+
let nativeCheck = result.dispatched === true && dispatch.active.size < nativeDispatchConcurrency();
|
|
1612
|
+
observed.nativeOnly = dispatch.active.size > 0;
|
|
1575
1613
|
const until = DateTime.toEpochMillis(yieldAfter);
|
|
1576
1614
|
const dispatchEnd = DateTime.toEpochMillis(dispatchUntil);
|
|
1577
1615
|
while (true) {
|
|
@@ -1599,18 +1637,16 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
1599
1637
|
if (exit.value === 0) dispatch.deferred.add(threadId);
|
|
1600
1638
|
nativeCheck = true;
|
|
1601
1639
|
}
|
|
1602
|
-
if (
|
|
1640
|
+
if (recoveryFiber?.pollUnsafe() !== void 0) {
|
|
1603
1641
|
yield* Fiber.join(recoveryFiber);
|
|
1604
|
-
|
|
1642
|
+
recoveryFiber = void 0;
|
|
1605
1643
|
dispatch.scanGeneration = void 0;
|
|
1606
1644
|
nativeCheck ||= recovery.needsCheckpoint;
|
|
1607
1645
|
}
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
if (Exit.isFailure(exit)) failure ??= exit.cause;
|
|
1613
|
-
}
|
|
1646
|
+
const backfillExit = backfill?.pollUnsafe();
|
|
1647
|
+
if (backfillExit !== void 0) {
|
|
1648
|
+
backfill = void 0;
|
|
1649
|
+
if (Exit.isFailure(backfillExit)) failure ??= backfillExit.cause;
|
|
1614
1650
|
}
|
|
1615
1651
|
for (const lane of lanes) {
|
|
1616
1652
|
const exit = lane.fiber?.pollUnsafe();
|
|
@@ -1668,11 +1704,11 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
1668
1704
|
return yield* wave.run;
|
|
1669
1705
|
}), observed).pipe(Effect.asVoid));
|
|
1670
1706
|
}
|
|
1671
|
-
if (native === void 0 && dispatch.active.size === 0 &&
|
|
1707
|
+
if (native === void 0 && dispatch.active.size === 0 && recoveryFiber === void 0 && !recovery.needsCheckpoint && backfill === void 0 && delivery === void 0 && lanes.every((lane) => lane.fiber === void 0)) break;
|
|
1672
1708
|
if (native === void 0 && nativeCheck && dispatch.active.size < nativeDispatchConcurrency()) {
|
|
1673
1709
|
nativeCheck = false;
|
|
1674
1710
|
const nativeCheckpoint = dispatch.needsCheckpoint && dispatch.active.size === 0;
|
|
1675
|
-
const checkpoint =
|
|
1711
|
+
const checkpoint = recoveryFiber === void 0 && recovery.needsCheckpoint || nativeCheckpoint;
|
|
1676
1712
|
if (checkpoint) recovery.needsCheckpoint = false;
|
|
1677
1713
|
const reserved = new Set(dispatch.active.keys());
|
|
1678
1714
|
native = yield* fork(Effect.gen(function* () {
|
|
@@ -1682,18 +1718,19 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
1682
1718
|
}
|
|
1683
1719
|
const next = Math.min(native === void 0 ? result.nextAttemptAt ?? Infinity : Infinity, ...queued.flatMap((row) => row.id !== "effect-agent:native" && row.dueAt !== null && row.dueAt > now ? [row.dueAt] : []), until);
|
|
1684
1720
|
const completing = [
|
|
1685
|
-
|
|
1721
|
+
native,
|
|
1686
1722
|
...dispatch.active.values(),
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
...lanes.
|
|
1691
|
-
];
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1723
|
+
recoveryFiber,
|
|
1724
|
+
backfill,
|
|
1725
|
+
delivery,
|
|
1726
|
+
...lanes.map((lane) => lane.fiber)
|
|
1727
|
+
].filter((fiber) => fiber !== void 0);
|
|
1728
|
+
const changed = awaitAnyCompletion(completing, queueRevision);
|
|
1729
|
+
if ((yield* leanSelection && native === void 0 && dispatch.active.size === 1 && completing.length === 1 && !queued.some((row) => row.id !== "effect-agent:native" && row.dueAt !== null && row.dueAt > now && row.dueAt < until) ? changed : Effect.raceAllFirst([
|
|
1730
|
+
changed,
|
|
1731
|
+
...leanSelection ? [] : [notified.pipe(Effect.as("scan"))],
|
|
1732
|
+
Effect.sleep(Math.max(0, next - now)).pipe(Effect.as("scan"))
|
|
1733
|
+
])) === "scan") nativeCheck = true;
|
|
1697
1734
|
}
|
|
1698
1735
|
if (native !== void 0) {
|
|
1699
1736
|
result = yield* Fiber.join(native);
|
|
@@ -1712,9 +1749,10 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
1712
1749
|
for (const fiber of [
|
|
1713
1750
|
recoveryFiber,
|
|
1714
1751
|
backfill,
|
|
1715
|
-
|
|
1716
|
-
...lanes.
|
|
1752
|
+
delivery,
|
|
1753
|
+
...lanes.map((lane) => lane.fiber)
|
|
1717
1754
|
]) {
|
|
1755
|
+
if (fiber === void 0) continue;
|
|
1718
1756
|
const exit = yield* Fiber.await(fiber);
|
|
1719
1757
|
if (Exit.isFailure(exit)) failure ??= exit.cause;
|
|
1720
1758
|
}
|
|
@@ -1732,7 +1770,7 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
1732
1770
|
};
|
|
1733
1771
|
});
|
|
1734
1772
|
const pass = Effect.fnUntraced(function* (yieldAfter, dispatchUntil, observed) {
|
|
1735
|
-
const concurrent = yield* Effect.exit(Effect.scoped(dispatch(yieldAfter, dispatchUntil, observed)));
|
|
1773
|
+
const concurrent = yield* Effect.exit(Effect.scoped(dispatch(yieldAfter, dispatchUntil, observed)).pipe(Effect.provideService(ThreadMutationGate, mutations)));
|
|
1736
1774
|
const afterNative = yield* Effect.gen(function* () {
|
|
1737
1775
|
const lanes = [
|
|
1738
1776
|
recoveryEventLane,
|
|
@@ -1803,9 +1841,9 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
1803
1841
|
const { state } = await readMaintenanceState(transaction);
|
|
1804
1842
|
const native = active > 0 || state.dirty > state.processed ? state.retry?.generation === state.dirty && active === 0 ? Math.max(now + minimumAlarmDelay, state.retry.notBefore) : state.dirty === observed.generation && active === 0 ? result.nextAttemptAt ?? now + minimumAlarmDelay : now + minimumAlarmDelay : Infinity;
|
|
1805
1843
|
dueQueue.checkpointNative(Number.isFinite(native) ? native : null);
|
|
1806
|
-
const next$
|
|
1807
|
-
if (Number.isFinite(next$
|
|
1808
|
-
checkpoint.at(Math.max(now + minimumAlarmDelay, next$
|
|
1844
|
+
const next$5 = next(dueQueue.read());
|
|
1845
|
+
if (Number.isFinite(next$5)) {
|
|
1846
|
+
checkpoint.at(Math.max(now + minimumAlarmDelay, next$5));
|
|
1809
1847
|
return "rearmed";
|
|
1810
1848
|
}
|
|
1811
1849
|
checkpoint.cancel();
|
|
@@ -1859,4 +1897,4 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
1859
1897
|
//#endregion
|
|
1860
1898
|
export { Lifecycle as _, ThreadHostMaintenance as a, Projection as b, ThreadMaintenanceFailpoint as c, ThreadNativeMaintenance as d, ThreadPublication as f, HostLaneId as g, publishCommitted as h, MaintenancePassReport as i, ThreadMessageDelivery as l, ThreadRecoveryFaultEvent as m, DurableAlarmError as n, ThreadMaintenance as o, ThreadRecoveryEvents as p, DurableAlarmService as r, ThreadMaintenanceAlarm as s, Alarm_exports as t, ThreadMutationGate as u, Messages as v, Publication as x, Native as y };
|
|
1861
1899
|
|
|
1862
|
-
//# sourceMappingURL=Alarm-
|
|
1900
|
+
//# sourceMappingURL=Alarm-7uipp6LW.mjs.map
|