mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-25 02:26:12 +02:00
fix: keep readiness confirmation responsive near its deadline
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
7e1a841ba5
commit
039a74c582
2 files changed
+24
-5
No files matched your search
@@ -46,5 +46,21 @@ it("does not reset the probe budget when readiness alternates", async () => {
|
||||
.then(() => "unexpected-ready", error => String(error));
|
||||
await vi.advanceTimersByTimeAsync(122_000);
|
||||
expect(await result).toContain("native_runner_warm_attachment_not_quiescent");
|
||||
expect(calls).toBeLessThan(250);
|
||||
expect(calls).toBeLessThan(350);
|
||||
});
|
||||
|
||||
it("confirms readiness near the deadline after one unsettled observation", async () => {
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(0);
|
||||
let recoveredProbes = 0;
|
||||
const result = waitForWarmAttachmentReadiness({
|
||||
graceMs: 5_000,
|
||||
waitForConnection: async () => {},
|
||||
snapshot: async () => ({
|
||||
warmAttachReady: Date.now() >= 4_400 && ++recoveredProbes !== 2,
|
||||
warmAttachBlockers: [],
|
||||
}),
|
||||
}).then(() => "ready", error => String(error));
|
||||
await vi.advanceTimersByTimeAsync(5_000);
|
||||
expect(await result).toBe("ready");
|
||||
});
|
||||
@@ -8,13 +8,17 @@ export async function waitForWarmAttachmentReadiness(input: {
|
||||
const deadline = Date.now() + input.graceMs;
|
||||
let consecutiveReadyProbes = 0;
|
||||
let lastBlockers: unknown = null;
|
||||
let blockedDelayMs = 25;
|
||||
let probes = 0;
|
||||
// Each probe is a durable command. A 25 ms loop over the remote 120 second
|
||||
// reconnect budget can exhaust its 500-command journal before that budget.
|
||||
const maxBlockedDelayMs = Math.max(1_000, Math.ceil(input.graceMs / 100));
|
||||
// Leave room for both ready-confirmation probes and ordinary commands. The
|
||||
// interval is proportional to the deadline, so a short local deadline never
|
||||
// inherits a one-second delay after a transient readiness regression.
|
||||
const blockedDelayMs = Math.max(25, Math.ceil(input.graceMs / 160));
|
||||
while (Date.now() < deadline) {
|
||||
await input.waitForConnection(deadline);
|
||||
const snapshot = await input.snapshot(deadline);
|
||||
probes += 1;
|
||||
if (snapshot.warmAttachReady !== true && JSON.stringify(snapshot.warmAttachBlockers) !== JSON.stringify(lastBlockers)) {
|
||||
input.onBlocked?.(snapshot.warmAttachBlockers);
|
||||
}
|
||||
@@ -25,8 +29,7 @@ export async function waitForWarmAttachmentReadiness(input: {
|
||||
} else {
|
||||
consecutiveReadyProbes = 0;
|
||||
}
|
||||
const delayMs = snapshot.warmAttachReady === true ? 25 : blockedDelayMs;
|
||||
if (snapshot.warmAttachReady !== true) blockedDelayMs = Math.min(blockedDelayMs * 2, maxBlockedDelayMs);
|
||||
const delayMs = snapshot.warmAttachReady === true || probes < 8 ? 25 : blockedDelayMs;
|
||||
await new Promise<void>(resolve => setTimeout(resolve, Math.min(delayMs, Math.max(0, deadline - Date.now()))));
|
||||
}
|
||||
throw new Error(`native_runner_warm_attachment_not_quiescent: ${JSON.stringify(lastBlockers)}`);
|
||||
|
||||
Reference in new issue
Block a user