@yielded/agent-platform-cloudflare 0.1.0-beta.173 → 0.1.0-beta.175
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-BMEAZo3p.mjs → Alarm-B44efvB1.mjs} +162 -103
- package/dist/Alarm-B44efvB1.mjs.map +1 -0
- package/dist/Alarm.d.mts +2 -0
- package/dist/Alarm.mjs +1 -1
- package/dist/BrowserRestCapture.mjs.map +1 -1
- package/dist/BrowserRestCrawl.mjs.map +1 -1
- package/dist/{BrowserSession-Bx0V1-6_.d.mts → BrowserSession-Cojp7nth.d.mts} +3 -2
- package/dist/{BrowserSession-BfNmyayH.mjs → BrowserSession-aovMjfL4.mjs} +14 -14
- package/dist/BrowserSession-aovMjfL4.mjs.map +1 -0
- package/dist/BrowserSession.d.mts +1 -1
- package/dist/BrowserSession.mjs +2 -2
- package/dist/BrowserUse.d.mts +40 -64
- package/dist/BrowserUse.mjs +223 -2
- package/dist/BrowserUse.mjs.map +1 -0
- package/dist/CloudflareBrowser-Vt8qTdYW.mjs.map +1 -1
- package/dist/CloudflareCodeMode.mjs.map +1 -1
- package/dist/CloudflareScheduling.mjs +9 -9
- package/dist/CloudflareScheduling.mjs.map +1 -1
- package/dist/CloudflareSubscriptions.mjs +15 -15
- package/dist/CloudflareSubscriptions.mjs.map +1 -1
- package/dist/{CloudflareThreadClient-DgZVrZzF.mjs → CloudflareThreadClient-Ai3MTs3X.mjs} +43 -40
- package/dist/CloudflareThreadClient-Ai3MTs3X.mjs.map +1 -0
- package/dist/CloudflareThreadClient.mjs +1 -1
- package/dist/{InteractiveBrowser-LdKzQeLR.mjs → InteractiveBrowser-BHNlwjZL.mjs} +40 -31
- package/dist/InteractiveBrowser-BHNlwjZL.mjs.map +1 -0
- package/dist/InteractiveBrowser.mjs +1 -1
- package/dist/{ThreadObject-CRbLbdXM.d.mts → ThreadObject-CxNlhoPL.d.mts} +3 -3
- package/dist/{ThreadObject-CGIaz6Jv.mjs → ThreadObject-DGvlHWYi.mjs} +50 -52
- package/dist/ThreadObject-DGvlHWYi.mjs.map +1 -0
- package/dist/ThreadObject.d.mts +1 -1
- package/dist/ThreadObject.mjs +1 -1
- package/dist/WakeScheduler.d.mts +1 -1
- package/dist/WakeScheduler.mjs +8 -3
- package/dist/WakeScheduler.mjs.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +5 -5
- package/dist/{prepared-admission-CSdzFM_v.mjs → prepared-admission-DYdffQ8K.mjs} +2 -2
- package/dist/{prepared-admission-CSdzFM_v.mjs.map → prepared-admission-DYdffQ8K.mjs.map} +1 -1
- package/package.json +1 -1
- package/src/Alarm.ts +293 -155
- package/src/BrowserRestCapture.ts +1 -0
- package/src/BrowserRestCrawl.ts +1 -0
- package/src/BrowserSession.ts +3 -2
- package/src/BrowserUse.ts +287 -1504
- package/src/CloudflareCodeMode.ts +6 -0
- package/src/CloudflareScheduling.ts +103 -103
- package/src/CloudflareSubscriptions.ts +192 -199
- package/src/CloudflareThreadClient.ts +258 -269
- package/src/InteractiveBrowser.ts +43 -17
- package/src/ThreadObject.ts +51 -45
- package/src/WakeScheduler.ts +12 -9
- package/src/internal/browser-binding.ts +8 -0
- package/src/internal/browser-credentials.ts +18 -13
- package/src/internal/browser-file-selection.ts +13 -2
- package/src/internal/browser-quick-action.ts +1 -0
- package/src/internal/browser-session-lifecycle.ts +32 -36
- package/src/internal/due-queue.ts +38 -19
- package/src/internal/layers.ts +108 -87
- package/src/internal/message-delivery.ts +61 -37
- package/dist/Alarm-BMEAZo3p.mjs.map +0 -1
- package/dist/BrowserSession-BfNmyayH.mjs.map +0 -1
- package/dist/BrowserUse-Bc2JdLW2.mjs +0 -1528
- package/dist/BrowserUse-Bc2JdLW2.mjs.map +0 -1
- package/dist/CloudflareThreadClient-DgZVrZzF.mjs.map +0 -1
- package/dist/InteractiveBrowser-LdKzQeLR.mjs.map +0 -1
- package/dist/ThreadObject-CGIaz6Jv.mjs.map +0 -1
- package/dist/page-function-CmUCcyNP.mjs +0 -11
- package/dist/page-function-CmUCcyNP.mjs.map +0 -1
- package/src/internal/browser-dom.ts +0 -886
- package/src/internal/browser-jev-dom.ts +0 -362
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
|
|
2
|
-
import { DurableObjectContext } from "./CloudflareBindings.mjs";
|
|
2
|
+
import { DurableObjectContext, ThreadObjectPlacement } from "./CloudflareBindings.mjs";
|
|
3
3
|
import { AuxiliaryDispatchMillis, CloudflareDurableRuntimeConfig } from "./CloudflareConfig.mjs";
|
|
4
4
|
import { r as safeCauseMessage } from "./boundary-BguazVkh.mjs";
|
|
5
5
|
import { CurrentNativeSource } from "@yielded/agent-storage-cloudflare/port-routing";
|
|
@@ -108,7 +108,7 @@ const make = (storage) => {
|
|
|
108
108
|
}
|
|
109
109
|
};
|
|
110
110
|
const write = (changes) => {
|
|
111
|
-
if (
|
|
111
|
+
if (sql.exec(`WITH changes (id, revision, dueAt, stalls, progressKey, notBefore, state, reported, expected_revision) AS (
|
|
112
112
|
VALUES ${changes.map(() => "(?, ?, ?, ?, ?, ?, ?, ?, ?)").join(", ")}
|
|
113
113
|
) INSERT INTO platform_cloudflare_due_queue
|
|
114
114
|
(id, revision, dueAt, stalls, progressKey, notBefore, state, reported)
|
|
@@ -118,7 +118,7 @@ const make = (storage) => {
|
|
|
118
118
|
notBefore = excluded.notBefore, state = excluded.state, reported = excluded.reported
|
|
119
119
|
WHERE platform_cloudflare_due_queue.revision = (
|
|
120
120
|
SELECT expected_revision FROM changes WHERE changes.id = excluded.id
|
|
121
|
-
) RETURNING
|
|
121
|
+
) RETURNING 1`, ...changes.flatMap(({ before, after }) => [
|
|
122
122
|
after.id,
|
|
123
123
|
after.revision,
|
|
124
124
|
after.dueAt,
|
|
@@ -128,7 +128,7 @@ const make = (storage) => {
|
|
|
128
128
|
after.state,
|
|
129
129
|
after.reported,
|
|
130
130
|
before?.revision ?? -1
|
|
131
|
-
])).toArray()
|
|
131
|
+
])).toArray().length !== changes.length) throw new Error("Maintenance due revision changed during transaction");
|
|
132
132
|
};
|
|
133
133
|
const flush = (frame) => {
|
|
134
134
|
if (frame.parent !== void 0) return;
|
|
@@ -205,6 +205,14 @@ const make = (storage) => {
|
|
|
205
205
|
progressKey: progressKey ?? row?.progressKey ?? null
|
|
206
206
|
}));
|
|
207
207
|
};
|
|
208
|
+
/** Native checkpoints fence the generation, not each source commit. Once progress
|
|
209
|
+
* resets a claimed lane, further native commits owe the same recovery opportunity.
|
|
210
|
+
* A new claim, deadline, or retry budget makes the next commit advance it again. */
|
|
211
|
+
const progressNative = (dueAt) => {
|
|
212
|
+
const row = read().find((row) => row.id === Native);
|
|
213
|
+
if (row?.state === "pending" && row.dueAt !== null && row.dueAt <= dueAt && row.stalls === 0 && row.notBefore === 0 && row.reported === 0) return;
|
|
214
|
+
dirty(Native, dueAt, true);
|
|
215
|
+
};
|
|
208
216
|
/** A strictly increasing source cursor; old or repeated notices cannot renew a budget. */
|
|
209
217
|
const progress = (id, dueAt, cursor) => {
|
|
210
218
|
Schema.decodeSync(Schema.BigInt.check(Schema.isGreaterThanOrEqualToBigInt(0n)))(cursor);
|
|
@@ -287,6 +295,7 @@ const make = (storage) => {
|
|
|
287
295
|
transaction,
|
|
288
296
|
read,
|
|
289
297
|
dirty,
|
|
298
|
+
progressNative,
|
|
290
299
|
progress,
|
|
291
300
|
register,
|
|
292
301
|
claim,
|
|
@@ -384,8 +393,8 @@ var DurableAlarmService = class DurableAlarmService extends Context.Service()("@
|
|
|
384
393
|
ensureScheduledBy: (at) => wrap("advance maintenance checkpoint", alarms.scheduleAlarmEarlier(maintenanceAlarmInput(at))),
|
|
385
394
|
scheduleNow: Ref.get(inlineWork).pipe(Effect.flatMap((active) => active > 0 ? Effect.void : wrap("hint maintenance checkpoint", alarms.transaction((tx) => Effect.gen(function* () {
|
|
386
395
|
const now = yield* Clock.currentTimeMillis;
|
|
387
|
-
const next$
|
|
388
|
-
if (Number.isFinite(next$
|
|
396
|
+
const next$6 = next(make(ctx.storage).read());
|
|
397
|
+
if (Number.isFinite(next$6)) yield* tx.scheduleAlarmEarlier(maintenanceAlarmInput(Math.max(now, next$6)));
|
|
389
398
|
}))))),
|
|
390
399
|
withHintsDeferred: (body) => Effect.acquireUseRelease(Ref.update(inlineWork, (active) => active + 1), () => body, () => Ref.update(inlineWork, (active) => active - 1)),
|
|
391
400
|
cancel: wrap("cancel maintenance checkpoint", alarms.cancelAlarm(maintenanceAlarmRef))
|
|
@@ -420,12 +429,16 @@ const makeAlarmOperation = Effect.gen(function* () {
|
|
|
420
429
|
if (ambient._tag === "Some" && !ownsTransaction(ctx.storage, ambient.value[1])) return Effect.fail(SqlError.make({ reason: UnknownError.make({
|
|
421
430
|
operation: "begin maintenance source transaction",
|
|
422
431
|
message: "Use ThreadMutationGate.withTransaction at the outermost source transaction",
|
|
423
|
-
cause:
|
|
432
|
+
cause: "Unwrapped SQL transaction cannot own buffered maintenance intent"
|
|
424
433
|
}) }));
|
|
425
434
|
return Effect.uninterruptibleMask((restore) => Effect.suspend(() => {
|
|
426
435
|
let frame;
|
|
427
|
-
return transaction(Effect.flatMap(Effect.serviceOption(sql.transactionService), (transaction) => Effect.
|
|
428
|
-
if (transaction._tag === "None")
|
|
436
|
+
return transaction(Effect.flatMap(Effect.serviceOption(sql.transactionService), (transaction) => Effect.gen(function* () {
|
|
437
|
+
if (transaction._tag === "None") return yield* SqlError.make({ reason: UnknownError.make({
|
|
438
|
+
operation: "begin maintenance source transaction",
|
|
439
|
+
message: "SQL transaction unavailable",
|
|
440
|
+
cause: "SQL transaction unavailable"
|
|
441
|
+
}) });
|
|
429
442
|
frame = queue.begin(transaction.value[1]);
|
|
430
443
|
})).pipe(Effect.andThen(restore(body)), Effect.tap(() => Effect.try({
|
|
431
444
|
try: () => {
|
|
@@ -442,8 +455,12 @@ const makeAlarmOperation = Effect.gen(function* () {
|
|
|
442
455
|
}));
|
|
443
456
|
}).pipe(Effect.provideService(SqlClient, sql));
|
|
444
457
|
const run = (operation, execute) => {
|
|
445
|
-
const commit = Effect.
|
|
446
|
-
|
|
458
|
+
const commit = Effect.withFiber((fiber) => {
|
|
459
|
+
const tx = fiber.getRef(CurrentCheckpoint);
|
|
460
|
+
if (tx === void 0) return Effect.die(DurableAlarmError.make({
|
|
461
|
+
operation: "checkpoint",
|
|
462
|
+
message: "Maintenance checkpoint transaction unavailable"
|
|
463
|
+
}));
|
|
447
464
|
return tx.requireActive.pipe(Effect.andThen(Effect.suspend(() => {
|
|
448
465
|
let checkpoint = Effect.void;
|
|
449
466
|
const intent = {
|
|
@@ -463,9 +480,9 @@ const makeAlarmOperation = Effect.gen(function* () {
|
|
|
463
480
|
}).pipe(Effect.tap(() => checkpoint));
|
|
464
481
|
})));
|
|
465
482
|
});
|
|
466
|
-
return Effect.
|
|
467
|
-
if ((
|
|
468
|
-
return
|
|
483
|
+
return Effect.withFiber((fiber) => {
|
|
484
|
+
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);
|
|
469
486
|
}).pipe(Effect.uninterruptible, Effect.mapError(alarmFailure(operation)));
|
|
470
487
|
};
|
|
471
488
|
return {
|
|
@@ -607,6 +624,14 @@ const recoveryEvent = (fault, submissionId, transition, occurredAt) => ({
|
|
|
607
624
|
firstFailedAt: fault.firstFailedAt,
|
|
608
625
|
failure: fault.failure
|
|
609
626
|
});
|
|
627
|
+
/** Observe already-owned waves without creating one waiter fiber for each wave. */
|
|
628
|
+
const awaitAnyCompletion = Effect.fnUntraced(function* (fibers, revision) {
|
|
629
|
+
const mutations = yield* ThreadMutationGate;
|
|
630
|
+
return yield* Effect.acquireUseRelease(Effect.sync(() => []), (observers) => Effect.callback((resume) => {
|
|
631
|
+
observers.push(mutations.observeChange(revision, () => resume(Effect.succeed("scan"))));
|
|
632
|
+
for (const fiber of fibers) observers.push(fiber.addObserver(() => resume(Effect.succeed("completed"))));
|
|
633
|
+
}), (observers) => Effect.sync(() => observers.forEach((remove) => remove())));
|
|
634
|
+
});
|
|
610
635
|
/** Post-native delivery shares a finite connection budget across independent host lanes. */
|
|
611
636
|
const afterNativeDispatchConcurrency = 2;
|
|
612
637
|
const NativeWorkCursor = Schema.Struct({
|
|
@@ -684,18 +709,30 @@ var ThreadMutationGate = class ThreadMutationGate extends Context.Service()("@ef
|
|
|
684
709
|
const { ctx } = yield* DurableObjectContext;
|
|
685
710
|
const sql = yield* SqlClient;
|
|
686
711
|
const dueQueue = make(ctx.storage);
|
|
712
|
+
const placement = yield* Effect.serviceOption(ThreadObjectPlacement);
|
|
713
|
+
const singleThread = Option.isSome(placement) && placement.value.threadId !== void 0;
|
|
687
714
|
const config = yield* CloudflareDurableRuntimeConfig;
|
|
688
715
|
const failpoint = yield* ThreadMaintenanceFailpoint;
|
|
689
716
|
const activeMutations = yield* Ref.make(0);
|
|
690
717
|
const activeLanes = /* @__PURE__ */ new Map();
|
|
691
718
|
const generationGate = yield* Semaphore.make(1);
|
|
692
719
|
let revision = 0;
|
|
693
|
-
|
|
694
|
-
const
|
|
695
|
-
|
|
696
|
-
|
|
720
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
721
|
+
const observeChange = (observed, listener) => {
|
|
722
|
+
if (observed !== revision) {
|
|
723
|
+
listener();
|
|
724
|
+
return () => {};
|
|
725
|
+
}
|
|
726
|
+
listeners.add(listener);
|
|
727
|
+
return () => {
|
|
728
|
+
listeners.delete(listener);
|
|
729
|
+
};
|
|
730
|
+
};
|
|
731
|
+
const notify = Effect.sync(() => {
|
|
697
732
|
revision++;
|
|
698
|
-
|
|
733
|
+
const pending = [...listeners];
|
|
734
|
+
listeners.clear();
|
|
735
|
+
for (const listener of pending) listener();
|
|
699
736
|
});
|
|
700
737
|
const minimumAlarmDelay = Math.max(1, Math.ceil(config.alarmBackoffBase / 2));
|
|
701
738
|
const runTransaction = yield* makeStorageOperation;
|
|
@@ -721,8 +758,8 @@ var ThreadMutationGate = class ThreadMutationGate extends Context.Service()("@ef
|
|
|
721
758
|
dirty: state.dirty + 1n
|
|
722
759
|
})));
|
|
723
760
|
}
|
|
724
|
-
const next$
|
|
725
|
-
if (Number.isFinite(next$
|
|
761
|
+
const next$2 = next(dueQueue.read());
|
|
762
|
+
if (Number.isFinite(next$2)) checkpoint.earlier(Math.max(next$2, now + minimumAlarmDelay));
|
|
726
763
|
};
|
|
727
764
|
yield* runAlarmTransaction("schedule maintenance lane", enroll);
|
|
728
765
|
yield* notify;
|
|
@@ -779,7 +816,8 @@ var ThreadMutationGate = class ThreadMutationGate extends Context.Service()("@ef
|
|
|
779
816
|
const now = yield* Clock.currentTimeMillis;
|
|
780
817
|
const nativeSource = yield* CurrentNativeSource;
|
|
781
818
|
yield* runAlarmTransaction("record maintenance producer progress", async (transaction, checkpoint) => {
|
|
782
|
-
for (const id of affected)
|
|
819
|
+
for (const id of affected) if (singleThread && nativeSource && id === "effect-agent:native") dueQueue.progressNative(now);
|
|
820
|
+
else dueQueue.dirty(id, now, true);
|
|
783
821
|
if (affected.has("effect-agent:native")) {
|
|
784
822
|
const { state, initialized } = await readMaintenanceState(transaction);
|
|
785
823
|
if (!initialized || !nativeSource || state.retry !== void 0) await transaction.put(MAINTENANCE_STATE_KEY, encodeMaintenanceState(ThreadMaintenanceState.make({
|
|
@@ -789,7 +827,7 @@ var ThreadMutationGate = class ThreadMutationGate extends Context.Service()("@ef
|
|
|
789
827
|
}
|
|
790
828
|
checkpoint.earlier(now + minimumAlarmDelay);
|
|
791
829
|
});
|
|
792
|
-
yield* notify;
|
|
830
|
+
if (!(singleThread && nativeSource && affected.size === 1 && affected.has("effect-agent:native"))) yield* notify;
|
|
793
831
|
});
|
|
794
832
|
return ThreadMutationGate.of({
|
|
795
833
|
withTransaction,
|
|
@@ -798,7 +836,11 @@ var ThreadMutationGate = class ThreadMutationGate extends Context.Service()("@ef
|
|
|
798
836
|
recordProgress,
|
|
799
837
|
activeLanes: Effect.sync(() => new Set(activeLanes.keys())),
|
|
800
838
|
revision: Effect.sync(() => revision),
|
|
801
|
-
|
|
839
|
+
observeChange,
|
|
840
|
+
awaitChange: (observed) => Effect.callback((resume) => {
|
|
841
|
+
const remove = observeChange(observed, () => resume(Effect.void));
|
|
842
|
+
return Effect.sync(remove);
|
|
843
|
+
}),
|
|
802
844
|
withSnapshot: (body) => generationGate.withPermit(Effect.flatMap(Ref.get(activeMutations), body))
|
|
803
845
|
});
|
|
804
846
|
}));
|
|
@@ -829,6 +871,7 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
829
871
|
const runtime = yield* DurableAgentRuntime;
|
|
830
872
|
const recoveryConfig = yield* DurableRuntimeConfig;
|
|
831
873
|
const ledger = yield* SubmissionLedger;
|
|
874
|
+
const listNonterminal = ledger.listNonterminal ?? Stream.runCollect(ledger.scanNonterminal);
|
|
832
875
|
const wakes = yield* WakeScheduler;
|
|
833
876
|
const hints = yield* DurableAlarmService;
|
|
834
877
|
const alarms = yield* ThreadMaintenanceAlarm;
|
|
@@ -845,6 +888,8 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
845
888
|
const messages = yield* ThreadMessageDelivery;
|
|
846
889
|
const host = yield* ThreadHostMaintenance;
|
|
847
890
|
const framework = yield* ThreadNativeMaintenance;
|
|
891
|
+
const placement = yield* Effect.serviceOption(ThreadObjectPlacement);
|
|
892
|
+
const nativeThread = Option.isSome(placement) ? placement.value.threadId : void 0;
|
|
848
893
|
const nativeDispatchConcurrency = () => framework.singleThreadRuntime === runtime ? 1 : 2;
|
|
849
894
|
for (const lane of host.lanes) yield* Schema.decodeEffect(HostLaneId)(lane.id).pipe(Effect.mapError(alarmFailure("maintenance lane ID")));
|
|
850
895
|
const recoveryEvents = Option.getOrElse(yield* Effect.serviceOption(ThreadRecoveryEvents), () => ThreadRecoveryEvents.of({ publish: () => Effect.void }));
|
|
@@ -894,8 +939,8 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
894
939
|
const now = yield* Clock.currentTimeMillis;
|
|
895
940
|
const claimed = yield* runAlarmTransaction("charge maintenance attempt", async (_transaction, checkpoint) => {
|
|
896
941
|
const claimed = dueQueue.claim(selected, now);
|
|
897
|
-
const next$
|
|
898
|
-
if (Number.isFinite(next$
|
|
942
|
+
const next$3 = next(dueQueue.read());
|
|
943
|
+
if (Number.isFinite(next$3)) checkpoint.at(Math.max(now + minimumAlarmDelay, next$3));
|
|
899
944
|
else checkpoint.cancel();
|
|
900
945
|
return claimed;
|
|
901
946
|
});
|
|
@@ -956,10 +1001,10 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
956
1001
|
};
|
|
957
1002
|
}));
|
|
958
1003
|
for (let sequence = range.next; sequence <= range.through; sequence++) {
|
|
959
|
-
const event = yield* runTransaction("read recovery event", async () =>
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
1004
|
+
const event = yield* runTransaction("read recovery event", async () => decodeRecoveryEvent(await ctx.storage.get(recoveryEventKey(sequence))));
|
|
1005
|
+
if (event.sequence !== sequence) return yield* DurableAlarmError.make({
|
|
1006
|
+
operation: "read recovery event",
|
|
1007
|
+
message: "Recovery event does not match its sequence key"
|
|
963
1008
|
});
|
|
964
1009
|
yield* recoveryEvents.publish(event);
|
|
965
1010
|
const acknowledgedAt = yield* Clock.currentTimeMillis;
|
|
@@ -986,9 +1031,9 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
986
1031
|
for (const report of result.reports) threads.set(report.threadId, void 0);
|
|
987
1032
|
for (const report of result.workReports ?? []) threads.set(report.threadId, void 0);
|
|
988
1033
|
for (const blocked of result.blocked) threads.set(blocked.threadId, blocked.failure);
|
|
989
|
-
if (threads.size === 0) return /* @__PURE__ */ new Map();
|
|
1034
|
+
if (threads.size === 0 || [...threads].every(([threadId, failure]) => failure === void 0 && recovery.loaded.has(threadId) && !recovery.faults.has(threadId))) return /* @__PURE__ */ new Map();
|
|
990
1035
|
const now = yield* Clock.currentTimeMillis;
|
|
991
|
-
const submissions = current ?? (result.blocked.length === 0 ? [] : yield*
|
|
1036
|
+
const submissions = current ?? (result.blocked.length === 0 ? [] : yield* listNonterminal);
|
|
992
1037
|
yield* failpoint.hit("maintenance:recovery-status:before");
|
|
993
1038
|
const retained = yield* runTransaction("record Thread recovery faults", () => dueQueue.transaction(async (transaction) => {
|
|
994
1039
|
const events = [];
|
|
@@ -1046,20 +1091,23 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
1046
1091
|
return retained.faults;
|
|
1047
1092
|
});
|
|
1048
1093
|
const recoverThread = Effect.fnUntraced(function* (threadId, recovery) {
|
|
1049
|
-
|
|
1050
|
-
const
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1094
|
+
const retained = yield* runTransaction("read work recovery cursor", async () => {
|
|
1095
|
+
const value = await ctx.storage.get(workCursorKey(threadId));
|
|
1096
|
+
return value === void 0 ? void 0 : Schema.decodeUnknownSync(NativeWorkCursor)(value);
|
|
1097
|
+
});
|
|
1098
|
+
if (retained !== void 0 && retained.threadId !== threadId) return yield* DurableAlarmError.make({
|
|
1099
|
+
operation: "read work recovery cursor",
|
|
1100
|
+
message: "Work cursor belongs to another Thread"
|
|
1055
1101
|
});
|
|
1102
|
+
let cursor = retained?.cursor;
|
|
1056
1103
|
do {
|
|
1057
1104
|
const result = yield* runtime.runRecovery({
|
|
1058
1105
|
threadId,
|
|
1106
|
+
deferUnclaimedAdmissions: true,
|
|
1059
1107
|
...cursor === void 0 ? {} : { cursor }
|
|
1060
1108
|
}).pipe(Effect.provideService(CurrentNativeSource, true));
|
|
1061
1109
|
const faults = yield* recordRecoveryFaults(result, recovery, void 0, threadId);
|
|
1062
|
-
yield* runTransaction("checkpoint work recovery cursor", async () => {
|
|
1110
|
+
if (cursor !== void 0 || result.cursor !== void 0) yield* runTransaction("checkpoint work recovery cursor", async () => {
|
|
1063
1111
|
if (result.cursor === void 0) await ctx.storage.delete(workCursorKey(threadId));
|
|
1064
1112
|
else await ctx.storage.put(workCursorKey(threadId), Schema.encodeSync(NativeWorkCursor)({
|
|
1065
1113
|
threadId,
|
|
@@ -1102,8 +1150,8 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
1102
1150
|
if (!initialized) await transaction.put(MAINTENANCE_STATE_KEY, encodeMaintenanceState(state));
|
|
1103
1151
|
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;
|
|
1104
1152
|
dueQueue.checkpointNative(native);
|
|
1105
|
-
const next$
|
|
1106
|
-
if (Number.isFinite(next$
|
|
1153
|
+
const next$1 = next(dueQueue.read());
|
|
1154
|
+
if (Number.isFinite(next$1)) checkpoint.earlier(Math.max(now + minimumAlarmDelay, next$1));
|
|
1107
1155
|
});
|
|
1108
1156
|
yield* failpoint.hit("maintenance:ensure:after");
|
|
1109
1157
|
});
|
|
@@ -1177,8 +1225,8 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
1177
1225
|
const charged = observed.charged.get(row.id) === row.revision ? row : dueQueue.claim(row, now);
|
|
1178
1226
|
if (charged !== void 0) dueQueue.complete(charged, now + backoffDelay(charged.stalls, jitter));
|
|
1179
1227
|
}
|
|
1180
|
-
const next$
|
|
1181
|
-
if (Number.isFinite(next$
|
|
1228
|
+
const next$4 = next(dueQueue.read());
|
|
1229
|
+
if (Number.isFinite(next$4)) checkpoint.at(Math.max(now + minimumAlarmDelay, next$4));
|
|
1182
1230
|
else checkpoint.cancel();
|
|
1183
1231
|
});
|
|
1184
1232
|
}));
|
|
@@ -1269,11 +1317,14 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
1269
1317
|
const { state } = await readMaintenanceState(ctx.storage);
|
|
1270
1318
|
return {
|
|
1271
1319
|
scannedGeneration: state.dirty,
|
|
1272
|
-
afterWorkThread: state.lastRecoveredThreadId
|
|
1320
|
+
afterWorkThread: framework.singleThreadRuntime === runtime && state.lastRecoveredThreadId === nativeThread ? void 0 : state.lastRecoveredThreadId
|
|
1273
1321
|
};
|
|
1274
1322
|
});
|
|
1275
|
-
const current = yield*
|
|
1276
|
-
let workOwners =
|
|
1323
|
+
const current = yield* listNonterminal;
|
|
1324
|
+
let workOwners = framework.singleThreadRuntime === runtime && nativeThread !== void 0 && current.some((submission) => submission.threadId === nativeThread) ? {
|
|
1325
|
+
threadIds: [nativeThread],
|
|
1326
|
+
afterThreadId: void 0
|
|
1327
|
+
} : yield* runtime.discoverWorkThreads({
|
|
1277
1328
|
limit: 32,
|
|
1278
1329
|
...afterWorkThread === void 0 ? {} : { afterThreadId: afterWorkThread }
|
|
1279
1330
|
}).pipe(Effect.provideService(CurrentNativeSource, true));
|
|
@@ -1360,7 +1411,7 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
1360
1411
|
const pivot = Math.max(0, runnable.findIndex((threadId) => state.lastServedThreadId === void 0 || threadId > state.lastServedThreadId));
|
|
1361
1412
|
const selected = dispatch ? [...runnable.slice(pivot), ...runnable.slice(0, pivot)].slice(0, nativeDispatchConcurrency() - reserved.size) : [];
|
|
1362
1413
|
const next = selected.at(-1);
|
|
1363
|
-
if (next !== void 0) await transaction.put(MAINTENANCE_STATE_KEY, encodeMaintenanceState(ThreadMaintenanceState.make({
|
|
1414
|
+
if (next !== void 0 && next !== state.lastServedThreadId) await transaction.put(MAINTENANCE_STATE_KEY, encodeMaintenanceState(ThreadMaintenanceState.make({
|
|
1364
1415
|
...state,
|
|
1365
1416
|
lastServedThreadId: next
|
|
1366
1417
|
})));
|
|
@@ -1397,7 +1448,7 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
1397
1448
|
nextAttemptAt: void 0,
|
|
1398
1449
|
dispatched: selection.selected.length > 0
|
|
1399
1450
|
};
|
|
1400
|
-
const remaining = yield*
|
|
1451
|
+
const remaining = yield* listNonterminal;
|
|
1401
1452
|
const waitingHeads = /* @__PURE__ */ new Map();
|
|
1402
1453
|
const autonomous = recovery.pending.size > 0 || recovery.discoveryPending || recoveryFaults.size > 0 || recovery.retryAtMillis !== void 0 || remaining.some((snapshot) => {
|
|
1403
1454
|
if (snapshot.state === "unknown" && waiting(snapshot)) return false;
|
|
@@ -1472,7 +1523,8 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
1472
1523
|
});
|
|
1473
1524
|
});
|
|
1474
1525
|
const dispatch = Effect.fnUntraced(function* (yieldAfter, dispatchUntil, observed) {
|
|
1475
|
-
const
|
|
1526
|
+
const leanSelection = framework.singleThreadRuntime === runtime && publication === emptyPublication && host.lanes.length === 0 && framework.lanes.length === 0;
|
|
1527
|
+
const notified = leanSelection ? Effect.never : (yield* Stream.toPull(wakes.wakes)).pipe(Effect.asVoid, Effect.catch(() => Effect.never));
|
|
1476
1528
|
const started = yield* beginNative(observed);
|
|
1477
1529
|
yield* mutations.withSnapshot(() => Effect.gen(function* () {
|
|
1478
1530
|
const queued = yield* queueSnapshot;
|
|
@@ -1509,8 +1561,35 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
1509
1561
|
repaired: false,
|
|
1510
1562
|
discoveryPending: false
|
|
1511
1563
|
};
|
|
1512
|
-
|
|
1513
|
-
|
|
1564
|
+
let recoveryFiber;
|
|
1565
|
+
let backfill;
|
|
1566
|
+
const dispatch = {
|
|
1567
|
+
scope: auxiliaryScope,
|
|
1568
|
+
active: /* @__PURE__ */ new Map(),
|
|
1569
|
+
deferred: /* @__PURE__ */ new Set(),
|
|
1570
|
+
dispatched: 0,
|
|
1571
|
+
settled: 0,
|
|
1572
|
+
progressed: false,
|
|
1573
|
+
needsCheckpoint: false
|
|
1574
|
+
};
|
|
1575
|
+
let native;
|
|
1576
|
+
let result;
|
|
1577
|
+
let backlog;
|
|
1578
|
+
if (leanSelection) {
|
|
1579
|
+
result = yield* advance(started, yieldAfter, observed, recovery, dispatch);
|
|
1580
|
+
recovery.started = true;
|
|
1581
|
+
yield* Deferred.succeed(recovery.queue, []);
|
|
1582
|
+
backlog = yield* Deferred.await(recovery.queue);
|
|
1583
|
+
} else {
|
|
1584
|
+
native = yield* fork(advance(started, yieldAfter, observed, recovery, dispatch));
|
|
1585
|
+
result = {
|
|
1586
|
+
phase: "caught-up",
|
|
1587
|
+
nonterminal: started.nonterminal,
|
|
1588
|
+
nextAttemptAt: void 0
|
|
1589
|
+
};
|
|
1590
|
+
}
|
|
1591
|
+
if (backlog === void 0 || backlog.length > 0) recoveryFiber = yield* fork(Effect.gen(function* () {
|
|
1592
|
+
for (const threadId of backlog ?? (yield* Deferred.await(recovery.queue))) {
|
|
1514
1593
|
yield* failpoint.hit("maintenance:select:before");
|
|
1515
1594
|
yield* runTransaction("select old recovery lane", () => dueQueue.transaction(async (transaction) => {
|
|
1516
1595
|
const { state } = await readMaintenanceState(transaction);
|
|
@@ -1525,31 +1604,11 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
1525
1604
|
if (!recovery.faults.has(threadId)) yield* wakes.notify(threadId);
|
|
1526
1605
|
}
|
|
1527
1606
|
}));
|
|
1528
|
-
const
|
|
1529
|
-
|
|
1530
|
-
const row = (yield* queueSnapshot).find((row) => row.id === Projection);
|
|
1531
|
-
if (row?.dueAt === null || row === void 0 || row.dueAt > (yield* Clock.currentTimeMillis)) return;
|
|
1532
|
-
return yield* runQueued(row, projection.drain.pipe(Effect.andThen(projection.pendingDeadline)), observed).pipe(Effect.timeoutOption(config.projectionDispatchTimeoutMillis));
|
|
1533
|
-
}));
|
|
1534
|
-
let backfillObserved = false;
|
|
1535
|
-
let recoveryObserved = false;
|
|
1536
|
-
const dispatch = {
|
|
1537
|
-
scope: auxiliaryScope,
|
|
1538
|
-
active: /* @__PURE__ */ new Map(),
|
|
1539
|
-
deferred: /* @__PURE__ */ new Set(),
|
|
1540
|
-
dispatched: 0,
|
|
1541
|
-
settled: 0,
|
|
1542
|
-
progressed: false,
|
|
1543
|
-
needsCheckpoint: false
|
|
1544
|
-
};
|
|
1545
|
-
let native = yield* fork(advance(started, yieldAfter, observed, recovery, dispatch));
|
|
1546
|
-
let result = {
|
|
1547
|
-
phase: "caught-up",
|
|
1548
|
-
nonterminal: started.nonterminal,
|
|
1549
|
-
nextAttemptAt: void 0
|
|
1550
|
-
};
|
|
1607
|
+
const projectionRow = (yield* queueSnapshot).find((row) => row.id === Projection);
|
|
1608
|
+
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));
|
|
1551
1609
|
let phase = result.phase;
|
|
1552
|
-
let nativeCheck =
|
|
1610
|
+
let nativeCheck = result.dispatched === true && dispatch.active.size < nativeDispatchConcurrency();
|
|
1611
|
+
observed.nativeOnly = dispatch.active.size > 0;
|
|
1553
1612
|
const until = DateTime.toEpochMillis(yieldAfter);
|
|
1554
1613
|
const dispatchEnd = DateTime.toEpochMillis(dispatchUntil);
|
|
1555
1614
|
while (true) {
|
|
@@ -1577,18 +1636,16 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
1577
1636
|
if (exit.value === 0) dispatch.deferred.add(threadId);
|
|
1578
1637
|
nativeCheck = true;
|
|
1579
1638
|
}
|
|
1580
|
-
if (
|
|
1639
|
+
if (recoveryFiber?.pollUnsafe() !== void 0) {
|
|
1581
1640
|
yield* Fiber.join(recoveryFiber);
|
|
1582
|
-
|
|
1641
|
+
recoveryFiber = void 0;
|
|
1583
1642
|
dispatch.scanGeneration = void 0;
|
|
1584
1643
|
nativeCheck ||= recovery.needsCheckpoint;
|
|
1585
1644
|
}
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
if (Exit.isFailure(exit)) failure ??= exit.cause;
|
|
1591
|
-
}
|
|
1645
|
+
const backfillExit = backfill?.pollUnsafe();
|
|
1646
|
+
if (backfillExit !== void 0) {
|
|
1647
|
+
backfill = void 0;
|
|
1648
|
+
if (Exit.isFailure(backfillExit)) failure ??= backfillExit.cause;
|
|
1592
1649
|
}
|
|
1593
1650
|
for (const lane of lanes) {
|
|
1594
1651
|
const exit = lane.fiber?.pollUnsafe();
|
|
@@ -1646,11 +1703,11 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
1646
1703
|
return yield* wave.run;
|
|
1647
1704
|
}), observed).pipe(Effect.asVoid));
|
|
1648
1705
|
}
|
|
1649
|
-
if (native === void 0 && dispatch.active.size === 0 &&
|
|
1706
|
+
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;
|
|
1650
1707
|
if (native === void 0 && nativeCheck && dispatch.active.size < nativeDispatchConcurrency()) {
|
|
1651
1708
|
nativeCheck = false;
|
|
1652
1709
|
const nativeCheckpoint = dispatch.needsCheckpoint && dispatch.active.size === 0;
|
|
1653
|
-
const checkpoint =
|
|
1710
|
+
const checkpoint = recoveryFiber === void 0 && recovery.needsCheckpoint || nativeCheckpoint;
|
|
1654
1711
|
if (checkpoint) recovery.needsCheckpoint = false;
|
|
1655
1712
|
const reserved = new Set(dispatch.active.keys());
|
|
1656
1713
|
native = yield* fork(Effect.gen(function* () {
|
|
@@ -1660,18 +1717,19 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
1660
1717
|
}
|
|
1661
1718
|
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);
|
|
1662
1719
|
const completing = [
|
|
1663
|
-
|
|
1720
|
+
native,
|
|
1664
1721
|
...dispatch.active.values(),
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
...lanes.
|
|
1669
|
-
];
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1722
|
+
recoveryFiber,
|
|
1723
|
+
backfill,
|
|
1724
|
+
delivery,
|
|
1725
|
+
...lanes.map((lane) => lane.fiber)
|
|
1726
|
+
].filter((fiber) => fiber !== void 0);
|
|
1727
|
+
const changed = awaitAnyCompletion(completing, queueRevision);
|
|
1728
|
+
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([
|
|
1729
|
+
changed,
|
|
1730
|
+
...leanSelection ? [] : [notified.pipe(Effect.as("scan"))],
|
|
1731
|
+
Effect.sleep(Math.max(0, next - now)).pipe(Effect.as("scan"))
|
|
1732
|
+
])) === "scan") nativeCheck = true;
|
|
1675
1733
|
}
|
|
1676
1734
|
if (native !== void 0) {
|
|
1677
1735
|
result = yield* Fiber.join(native);
|
|
@@ -1690,9 +1748,10 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
1690
1748
|
for (const fiber of [
|
|
1691
1749
|
recoveryFiber,
|
|
1692
1750
|
backfill,
|
|
1693
|
-
|
|
1694
|
-
...lanes.
|
|
1751
|
+
delivery,
|
|
1752
|
+
...lanes.map((lane) => lane.fiber)
|
|
1695
1753
|
]) {
|
|
1754
|
+
if (fiber === void 0) continue;
|
|
1696
1755
|
const exit = yield* Fiber.await(fiber);
|
|
1697
1756
|
if (Exit.isFailure(exit)) failure ??= exit.cause;
|
|
1698
1757
|
}
|
|
@@ -1710,7 +1769,7 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
1710
1769
|
};
|
|
1711
1770
|
});
|
|
1712
1771
|
const pass = Effect.fnUntraced(function* (yieldAfter, dispatchUntil, observed) {
|
|
1713
|
-
const concurrent = yield* Effect.exit(Effect.scoped(dispatch(yieldAfter, dispatchUntil, observed)));
|
|
1772
|
+
const concurrent = yield* Effect.exit(Effect.scoped(dispatch(yieldAfter, dispatchUntil, observed)).pipe(Effect.provideService(ThreadMutationGate, mutations)));
|
|
1714
1773
|
const afterNative = yield* Effect.gen(function* () {
|
|
1715
1774
|
const lanes = [
|
|
1716
1775
|
recoveryEventLane,
|
|
@@ -1781,9 +1840,9 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
1781
1840
|
const { state } = await readMaintenanceState(transaction);
|
|
1782
1841
|
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;
|
|
1783
1842
|
dueQueue.checkpointNative(Number.isFinite(native) ? native : null);
|
|
1784
|
-
const next$
|
|
1785
|
-
if (Number.isFinite(next$
|
|
1786
|
-
checkpoint.at(Math.max(now + minimumAlarmDelay, next$
|
|
1843
|
+
const next$5 = next(dueQueue.read());
|
|
1844
|
+
if (Number.isFinite(next$5)) {
|
|
1845
|
+
checkpoint.at(Math.max(now + minimumAlarmDelay, next$5));
|
|
1787
1846
|
return "rearmed";
|
|
1788
1847
|
}
|
|
1789
1848
|
checkpoint.cancel();
|
|
@@ -1837,4 +1896,4 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
1837
1896
|
//#endregion
|
|
1838
1897
|
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 };
|
|
1839
1898
|
|
|
1840
|
-
//# sourceMappingURL=Alarm-
|
|
1899
|
+
//# sourceMappingURL=Alarm-B44efvB1.mjs.map
|