惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

IT之家
IT之家
博客园_首页
S
SegmentFault 最新的问题
罗磊的独立博客
博客园 - 【当耐特】
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
阮一峰的网络日志
阮一峰的网络日志
D
Docker
雷峰网
雷峰网
Google DeepMind News
Google DeepMind News
博客园 - 司徒正美
V
V2EX
大猫的无限游戏
大猫的无限游戏
V
Visual Studio Blog
腾讯CDC
宝玉的分享
宝玉的分享
酷 壳 – CoolShell
酷 壳 – CoolShell
人人都是产品经理
人人都是产品经理
T
Tailwind CSS Blog
Vercel News
Vercel News
H
Help Net Security
博客园 - Franky
D
DataBreaches.Net
aimingoo的专栏
aimingoo的专栏

Recent Commits to openclaw:main

test: merge chat side-result checks · openclaw/openclaw@ddd2c2a test: merge cron history checks · openclaw/openclaw@f7eb746 test: merge responsive navigation shell checks · openclaw/openclaw@c2e4b47 docs(changelog): add codex oauth fixes · openclaw/openclaw@628e6cd test: merge navigation routing cases · openclaw/openclaw@5d8cecb Tests: mock channel registry bundled fallback · openclaw/openclaw@2b08233 Secrets: avoid broad web search discovery for single plugin config · openclaw/openclaw@a464f59 test: merge config view browser checks · openclaw/openclaw@20cf511 fix(status): align oauth health with runtime · openclaw/openclaw@eed7116 feat: add macOS screen snapshots for monitor preview (#67954) thanks … · openclaw/openclaw@f377db1 fix: report shared auth scopes in hello-ok (#67810) thanks @BunsDev · openclaw/openclaw@0b6c39b Auto-reply: avoid eager bundled route fallback · openclaw/openclaw@3ea1bf4 Tests: narrow session binding contract setup · openclaw/openclaw@54e4e16 fix(macOS): enable undo/redo in webchat composer text input (#34962) · openclaw/openclaw@00951dc Tests: speed up channel setup promotion · openclaw/openclaw@82b529a Docs: refresh agent instructions · openclaw/openclaw@5775fe2 fix(auth): serialize OAuth refresh across agents to fix #26322 (#67876) · openclaw/openclaw@8e79080 test: allow ollama public surface boundary test · openclaw/openclaw@7d4f1a6 Docs: add test performance guardrails · openclaw/openclaw@89706d3 Tests: restore context-engine usage proof · openclaw/openclaw@e4c4f95 Tests: slim context engine runtime coverage · openclaw/openclaw@74c198f ci: retry failed custom checkouts · openclaw/openclaw@0ee5baf test: trim duplicate provider auth onboarding cases · openclaw/openclaw@1ffc02e matrix: fix sessions_spawn --thread subagent session spawning (#67643) · openclaw/openclaw@1ce2596 test: reduce auth choice fixture churn · openclaw/openclaw@857b9cd test: mock health status config boundaries · openclaw/openclaw@9d5ab4a test: mock onboard config io boundary · openclaw/openclaw@299694d test: mock legacy state plugin boundaries · openclaw/openclaw@2713089 test: mock channel install boundaries · openclaw/openclaw@b945248 test: mock doctor preview channel boundaries · openclaw/openclaw@b1a3ad4
Fix Telegram polling ingress under event-loop stalls (#81...
joshavant · 2026-05-14 · via Recent Commits to openclaw:main

@@ -115,6 +115,11 @@ type RunnerStub = {

115115

isRunning: () => boolean;

116116

};

117117118+

const withLegacyPolling = (opts: MonitorTelegramOpts): MonitorTelegramOpts => ({

119+

...opts,

120+

isolatedIngress: { enabled: false, ...opts.isolatedIngress },

121+

});

122+118123

const makeRunnerStub = (overrides: Partial<RunnerStub> = {}): RunnerStub => ({

119124

task: overrides.task ?? (() => Promise.resolve()),

120125

stop: overrides.stop ?? vi.fn<() => void | Promise<void>>(),

@@ -197,7 +202,7 @@ async function expectOffsetConfirmationSkipped(offset: number | null) {

197202

api.deleteWebhook.mockResolvedValueOnce(true);

198203

mockRunOnceAndAbort(abort);

199204200-

await monitorTelegramProvider({ token: "tok", abortSignal: abort.signal });

205+

await monitorTelegramProvider(withLegacyPolling({ token: "tok", abortSignal: abort.signal }));

201206202207

expect(api.getUpdates).not.toHaveBeenCalled();

203208

}

@@ -225,7 +230,7 @@ async function runMonitorAndCaptureStartupOrder(params?: { persistedOffset?: num

225230

return makeAbortRunner(abort);

226231

});

227232228-

await monitorTelegramProvider({ token: "tok", abortSignal: abort.signal });

233+

await monitorTelegramProvider(withLegacyPolling({ token: "tok", abortSignal: abort.signal }));

229234

return { order };

230235

}

231236

@@ -305,6 +310,7 @@ async function monitorWithAutoAbort(opts: Omit<MonitorTelegramOpts, "abortSignal

305310

token: "tok",

306311

...opts,

307312

abortSignal: abort.signal,

313+

isolatedIngress: { enabled: false, ...opts.isolatedIngress },

308314

});

309315

}

310316

@@ -496,7 +502,7 @@ describe("monitorTelegramProvider (grammY)", () => {

496502

)

497503

.mockImplementationOnce(() => makeAbortRunner(abort));

498504499-

await monitorTelegramProvider({ token: "tok", abortSignal: abort.signal });

505+

await monitorTelegramProvider(withLegacyPolling({ token: "tok", abortSignal: abort.signal }));

500506501507

expectRecoverableRetryState(2);

502508

});

@@ -516,7 +522,7 @@ describe("monitorTelegramProvider (grammY)", () => {

516522

api.deleteWebhook.mockRejectedValueOnce(cleanupError);

517523

mockRunOnceAndAbort(abort);

518524519-

await monitorTelegramProvider({ token: "tok", abortSignal: abort.signal });

525+

await monitorTelegramProvider(withLegacyPolling({ token: "tok", abortSignal: abort.signal }));

520526521527

expect(api.deleteWebhook).toHaveBeenCalledTimes(1);

522528

expect(api.getWebhookInfo).not.toHaveBeenCalled();

@@ -531,7 +537,7 @@ describe("monitorTelegramProvider (grammY)", () => {

531537

api.deleteWebhook.mockRejectedValueOnce(cleanupError);

532538

mockRunOnceAndAbort(abort);

533539534-

await monitorTelegramProvider({ token: "tok", abortSignal: abort.signal });

540+

await monitorTelegramProvider(withLegacyPolling({ token: "tok", abortSignal: abort.signal }));

535541536542

expect(api.deleteWebhook).toHaveBeenCalledTimes(1);

537543

expect(api.getWebhookInfo).not.toHaveBeenCalled();

@@ -545,7 +551,7 @@ describe("monitorTelegramProvider (grammY)", () => {

545551

createTelegramBotErrors.push(setupError);

546552

mockRunOnceAndAbort(abort);

547553548-

await monitorTelegramProvider({ token: "tok", abortSignal: abort.signal });

554+

await monitorTelegramProvider(withLegacyPolling({ token: "tok", abortSignal: abort.signal }));

549555550556

expectRecoverableRetryState(1);

551557

});

@@ -571,7 +577,7 @@ describe("monitorTelegramProvider (grammY)", () => {

571577

return makeAbortRunner(abort);

572578

});

573579574-

await monitorTelegramProvider({ token: "tok", abortSignal: abort.signal });

580+

await monitorTelegramProvider(withLegacyPolling({ token: "tok", abortSignal: abort.signal }));

575581576582

expect(firstStop).toHaveBeenCalled();

577583

expectRecoverableRetryState(2);

@@ -581,7 +587,7 @@ describe("monitorTelegramProvider (grammY)", () => {

581587

const abort = new AbortController();

582588

mockRunOnceAndAbort(abort);

583589584-

await monitorTelegramProvider({ token: "tok", abortSignal: abort.signal });

590+

await monitorTelegramProvider(withLegacyPolling({ token: "tok", abortSignal: abort.signal }));

585591586592

expect(createdBotStops.length).toBe(1);

587593

expect(createdBotStops[0]).toHaveBeenCalledTimes(1);

@@ -591,10 +597,12 @@ describe("monitorTelegramProvider (grammY)", () => {

591597

const abort = new AbortController();

592598

const firstCycle = mockRunOnceWithStalledPollingRunner();

593599594-

const monitor = monitorTelegramProvider({ token: "tok", abortSignal: abort.signal });

600+

const monitor = monitorTelegramProvider(

601+

withLegacyPolling({ token: "tok", abortSignal: abort.signal }),

602+

);

595603

await firstCycle.waitForRunStart();

596604597-

await expect(monitorTelegramProvider({ token: "tok" })).rejects.toThrow(

605+

await expect(monitorTelegramProvider(withLegacyPolling({ token: "tok" }))).rejects.toThrow(

598606

"refusing duplicate poller",

599607

);

600608

expect(runSpy).toHaveBeenCalledTimes(1);

@@ -609,15 +617,19 @@ describe("monitorTelegramProvider (grammY)", () => {

609617

const firstCycle = mockRunOnceWithStalledPollingRunner();

610618

const secondCycle = mockRunOnceWithStalledPollingRunner();

611619612-

const firstMonitor = monitorTelegramProvider({

613-

token: "tok-a",

614-

abortSignal: firstAbort.signal,

615-

});

620+

const firstMonitor = monitorTelegramProvider(

621+

withLegacyPolling({

622+

token: "tok-a",

623+

abortSignal: firstAbort.signal,

624+

}),

625+

);

616626

await firstCycle.waitForRunStart();

617-

const secondMonitor = monitorTelegramProvider({

618-

token: "tok-b",

619-

abortSignal: secondAbort.signal,

620-

});

627+

const secondMonitor = monitorTelegramProvider(

628+

withLegacyPolling({

629+

token: "tok-b",

630+

abortSignal: secondAbort.signal,

631+

}),

632+

);

621633

await secondCycle.waitForRunStart();

622634623635

expect(runSpy).toHaveBeenCalledTimes(2);

@@ -632,18 +644,22 @@ describe("monitorTelegramProvider (grammY)", () => {

632644

const secondAbort = new AbortController();

633645

const firstCycle = mockRunOnceWithStalledPollingRunner();

634646635-

const firstMonitor = monitorTelegramProvider({

636-

token: "tok",

637-

abortSignal: firstAbort.signal,

638-

});

647+

const firstMonitor = monitorTelegramProvider(

648+

withLegacyPolling({

649+

token: "tok",

650+

abortSignal: firstAbort.signal,

651+

}),

652+

);

639653

await firstCycle.waitForRunStart();

640654

firstAbort.abort();

641655642656

const secondCycle = mockRunOnceAndAbort(secondAbort);

643-

const secondMonitor = monitorTelegramProvider({

644-

token: "tok",

645-

abortSignal: secondAbort.signal,

646-

});

657+

const secondMonitor = monitorTelegramProvider(

658+

withLegacyPolling({

659+

token: "tok",

660+

abortSignal: secondAbort.signal,

661+

}),

662+

);

647663

await secondCycle.waitForRunStart();

648664

await Promise.all([firstMonitor, secondMonitor]);

649665

@@ -656,7 +672,7 @@ describe("monitorTelegramProvider (grammY)", () => {

656672

const abort = new AbortController();

657673

mockRunOnceAndAbort(abort);

658674659-

await monitorTelegramProvider({ token: "tok", abortSignal: abort.signal });

675+

await monitorTelegramProvider(withLegacyPolling({ token: "tok", abortSignal: abort.signal }));

660676661677

expect(vi.getTimerCount()).toBe(0);

662678

} finally {

@@ -671,15 +687,19 @@ describe("monitorTelegramProvider (grammY)", () => {

671687

}),

672688

);

673689674-

await expect(monitorTelegramProvider({ token: "tok" })).rejects.toThrow("bad token");

690+

await expect(monitorTelegramProvider(withLegacyPolling({ token: "tok" }))).rejects.toThrow(

691+

"bad token",

692+

);

675693

});

676694677695

it("force-restarts polling when unhandled network rejection stalls runner", async () => {

678696

const abort = new AbortController();

679697

const firstCycle = mockRunOnceWithStalledPollingRunner();

680698

const secondCycle = mockRunOnceWithStalledPollingRunner();

681699682-

const monitor = monitorTelegramProvider({ token: "tok", abortSignal: abort.signal });

700+

const monitor = monitorTelegramProvider(

701+

withLegacyPolling({ token: "tok", abortSignal: abort.signal }),

702+

);

683703

await firstCycle.waitForRunStart();

684704685705

expect(emitUnhandledRejection(await makeTaggedPollingFetchError())).toBe(true);

@@ -697,7 +717,9 @@ describe("monitorTelegramProvider (grammY)", () => {

697717

const firstCycle = mockRunOnceWithStalledPollingRunner();

698718

const secondCycle = mockRunOnceWithStalledPollingRunner();

699719700-

const monitor = monitorTelegramProvider({ token: "tok", abortSignal: abort.signal });

720+

const monitor = monitorTelegramProvider(

721+

withLegacyPolling({ token: "tok", abortSignal: abort.signal }),

722+

);

701723

await firstCycle.waitForRunStart();

702724703725

expect(emitUncaughtException(await makeTaggedPollingFetchError())).toBe(true);

@@ -713,7 +735,9 @@ describe("monitorTelegramProvider (grammY)", () => {

713735

const firstCycle = mockRunOnceWithStalledPollingRunner();

714736

const secondCycle = mockRunOnceWithStalledPollingRunner();

715737716-

const monitor = monitorTelegramProvider({ token: "tok", abortSignal: abort.signal });

738+

const monitor = monitorTelegramProvider(

739+

withLegacyPolling({ token: "tok", abortSignal: abort.signal }),

740+

);

717741

await firstCycle.waitForRunStart();

718742719743

expect(emitUncaughtException(await makeTaggedPollingHttpError())).toBe(true);

@@ -745,7 +769,9 @@ describe("monitorTelegramProvider (grammY)", () => {

745769

const firstCycle = mockRunOnceWithStalledPollingRunner();

746770

const secondCycle = mockRunOnceAndAbort(abort);

747771748-

const monitor = monitorTelegramProvider({ token: "tok", abortSignal: abort.signal });

772+

const monitor = monitorTelegramProvider(

773+

withLegacyPolling({ token: "tok", abortSignal: abort.signal }),

774+

);

749775

await firstCycle.waitForRunStart();

750776751777

vi.advanceTimersByTime(150_000);

@@ -779,7 +805,9 @@ describe("monitorTelegramProvider (grammY)", () => {

779805

.mockReturnValueOnce(rebuiltTransport);

780806

const secondCycle = mockRunOnceAndAbort(abort);

781807782-

const monitor = monitorTelegramProvider({ token: "tok", abortSignal: abort.signal });

808+

const monitor = monitorTelegramProvider(

809+

withLegacyPolling({ token: "tok", abortSignal: abort.signal }),

810+

);

783811

await firstCycle.waitForRunStart();

784812785813

expect(emitUnhandledRejection(await makeTaggedPollingFetchError())).toBe(true);

@@ -798,7 +826,9 @@ describe("monitorTelegramProvider (grammY)", () => {

798826

const { stop, waitForTaskStart } = mockRunOnceWithStalledPollingRunner();

799827

const secondCycle = mockRunOnceAndAbort(abort);

800828801-

const monitor = monitorTelegramProvider({ token: "tok", abortSignal: abort.signal });

829+

const monitor = monitorTelegramProvider(

830+

withLegacyPolling({ token: "tok", abortSignal: abort.signal }),

831+

);

802832

await waitForTaskStart();

803833

const firstSignal = createTelegramBotCalls[0]?.fetchAbortSignal;

804834

expect(firstSignal).toBeInstanceOf(AbortSignal);

@@ -817,7 +847,9 @@ describe("monitorTelegramProvider (grammY)", () => {

817847

const firstCycle = mockRunOnceWithStalledPollingRunner();

818848

const { stop } = firstCycle;

819849820-

const monitor = monitorTelegramProvider({ token: "tok", abortSignal: abort.signal });

850+

const monitor = monitorTelegramProvider(

851+

withLegacyPolling({ token: "tok", abortSignal: abort.signal }),

852+

);

821853

await firstCycle.waitForRunStart();

822854823855

const slackDnsError = Object.assign(

@@ -891,7 +923,9 @@ describe("monitorTelegramProvider (grammY)", () => {

891923

const { stop } = firstCycle;

892924

const secondCycle = mockRunOnceAndAbort(abort);

893925894-

const monitor = monitorTelegramProvider({ token: "tok", abortSignal: abort.signal });

926+

const monitor = monitorTelegramProvider(

927+

withLegacyPolling({ token: "tok", abortSignal: abort.signal }),

928+

);

895929

await firstCycle.waitForRunStart();

896930897931

// Advance time past the stall threshold (120s) + watchdog interval (30s)

@@ -910,14 +944,16 @@ describe("monitorTelegramProvider (grammY)", () => {

910944

const firstCycle = mockRunOnceWithStalledPollingRunner();

911945

const secondCycle = mockRunOnceAndAbort(abort);

912946913-

const monitor = monitorTelegramProvider({

914-

token: "tok",

915-

abortSignal: abort.signal,

916-

config: {

917-

agents: { defaults: { maxConcurrent: 2 } },

918-

channels: { telegram: { pollingStallThresholdMs: 30_000 } },

919-

},

920-

});

947+

const monitor = monitorTelegramProvider(

948+

withLegacyPolling({

949+

token: "tok",

950+

abortSignal: abort.signal,

951+

config: {

952+

agents: { defaults: { maxConcurrent: 2 } },

953+

channels: { telegram: { pollingStallThresholdMs: 30_000 } },

954+

},

955+

}),

956+

);

921957

await firstCycle.waitForRunStart();

922958923959

vi.advanceTimersByTime(60_000);

@@ -996,7 +1032,7 @@ describe("monitorTelegramProvider (grammY)", () => {

9961032

return makeAbortRunner(abort);

9971033

});

9981034999-

await monitorTelegramProvider({ token: "tok", abortSignal: abort.signal });

1035+

await monitorTelegramProvider(withLegacyPolling({ token: "tok", abortSignal: abort.signal }));

1000103610011037

// deleteWebhook should be called twice: once on initial cleanup, once after 409 reset

10021038

expect(api.deleteWebhook).toHaveBeenCalledTimes(2);