Skip to content

Commit 0b26a1b

Browse files
committed
fix(telegram): cancel clean restart stop timers
1 parent 0bcdb9c commit 0b26a1b

2 files changed

Lines changed: 27 additions & 10 deletions

File tree

extensions/telegram/src/polling-session.test.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -217,11 +217,12 @@ function installPollingStallWatchdogHarness(dateNowSequence: readonly number[] =
217217
return 1 as unknown as ReturnType<typeof setInterval>;
218218
});
219219
const clearIntervalSpy = vi.spyOn(globalThis, "clearInterval").mockImplementation(() => {});
220-
const setTimeoutSpy = vi.spyOn(globalThis, "setTimeout").mockImplementation((fn) => {
221-
void Promise.resolve().then(() => (fn as () => void)());
222-
return 1 as unknown as ReturnType<typeof setTimeout>;
220+
const setTimeoutSpy = vi
221+
.spyOn(globalThis, "setTimeout")
222+
.mockImplementation((fn) => realSetTimeout(fn as () => void, 0));
223+
const clearTimeoutSpy = vi.spyOn(globalThis, "clearTimeout").mockImplementation((timeoutId) => {
224+
realClearTimeout(timeoutId);
223225
});
224-
const clearTimeoutSpy = vi.spyOn(globalThis, "clearTimeout").mockImplementation(() => {});
225226
const dateNowSpy = vi.spyOn(Date, "now");
226227
for (const value of dateNowSequence) {
227228
dateNowSpy.mockImplementationOnce(() => value);
@@ -1136,6 +1137,7 @@ describe("TelegramPollingSession", () => {
11361137

11371138
expectLogIncludes(log, "Polling stall detected");
11381139
expectLogIncludes(log, "isolated polling ingress finished reason=polling stall detected");
1140+
expectLogExcludes(log, "Isolated polling ingress stop timed out");
11391141
} finally {
11401142
watchdogHarness.restore();
11411143
abort.abort();
@@ -3034,6 +3036,7 @@ describe("TelegramPollingSession", () => {
30343036
expect(botStop).toHaveBeenCalledTimes(1);
30353037
expectLogIncludes(log, "Polling stall detected");
30363038
expectLogIncludes(log, "polling stall detected");
3039+
expectLogExcludes(log, "Polling runner stop timed out");
30373040
} finally {
30383041
watchdogHarness.restore();
30393042
}

extensions/telegram/src/polling-session.ts

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -904,6 +904,13 @@ export class TelegramPollingSession {
904904
.then(() => undefined)
905905
.catch(() => undefined);
906906
};
907+
const clearForceCycleTimer = () => {
908+
if (!forceCycleTimer) {
909+
return;
910+
}
911+
clearTimeout(forceCycleTimer);
912+
forceCycleTimer = undefined;
913+
};
907914
const requestStopForRestart = () => {
908915
if (restartRequested) {
909916
return;
@@ -989,6 +996,7 @@ export class TelegramPollingSession {
989996
try {
990997
try {
991998
await Promise.race([worker.task(), forceCyclePromise]);
999+
clearForceCycleTimer();
9921000
} catch (err) {
9931001
if (this.opts.abortSignal?.aborted) {
9941002
return "exit";
@@ -1003,6 +1011,7 @@ export class TelegramPollingSession {
10031011
const message = formatErrorMessage(err);
10041012
this.opts.log(`[telegram][diag] isolated polling ingress failed: ${message}`);
10051013
this.#status.notePollingError(message);
1014+
clearForceCycleTimer();
10061015
const shouldRestart = await this.#waitBeforeRestart(
10071016
(delay) => `Telegram isolated polling ingress failed; restarting in ${delay}.`,
10081017
);
@@ -1034,9 +1043,7 @@ export class TelegramPollingSession {
10341043
} finally {
10351044
clearInterval(watchdog);
10361045
clearInterval(drainTimer);
1037-
if (forceCycleTimer) {
1038-
clearTimeout(forceCycleTimer);
1039-
}
1046+
clearForceCycleTimer();
10401047
unsubscribe();
10411048
this.opts.abortSignal?.removeEventListener("abort", stopOnAbort);
10421049
await stopWorker();
@@ -1092,6 +1099,13 @@ export class TelegramPollingSession {
10921099
const forceCyclePromise = new Promise<void>((resolve) => {
10931100
forceCycleResolve = resolve;
10941101
});
1102+
const clearForceCycleTimer = () => {
1103+
if (!forceCycleTimer) {
1104+
return;
1105+
}
1106+
clearTimeout(forceCycleTimer);
1107+
forceCycleTimer = undefined;
1108+
};
10951109
const stopRunner = () => {
10961110
fetchAbortController?.abort();
10971111
stopPromise ??= Promise.resolve(runner.stop())
@@ -1154,6 +1168,7 @@ export class TelegramPollingSession {
11541168
this.opts.abortSignal?.addEventListener("abort", stopOnAbort, { once: true });
11551169
try {
11561170
await Promise.race([runner.task(), forceCyclePromise]);
1171+
clearForceCycleTimer();
11571172
if (this.opts.abortSignal?.aborted) {
11581173
return "exit";
11591174
}
@@ -1200,15 +1215,14 @@ export class TelegramPollingSession {
12001215
this.opts.log(
12011216
`[telegram][diag] polling cycle error reason=${reason} ${liveness.formatDiagnosticFields("lastGetUpdatesError")} err=${errMsg}${conflictHint}`,
12021217
);
1218+
clearForceCycleTimer();
12031219
const shouldRestart = await this.#waitBeforeRestart(
12041220
(delay) => `Telegram ${reason}: ${errMsg};${conflictHint} retrying in ${delay}.`,
12051221
);
12061222
return shouldRestart ? "continue" : "exit";
12071223
} finally {
12081224
clearInterval(watchdog);
1209-
if (forceCycleTimer) {
1210-
clearTimeout(forceCycleTimer);
1211-
}
1225+
clearForceCycleTimer();
12121226
this.opts.abortSignal?.removeEventListener("abort", abortFetch);
12131227
this.opts.abortSignal?.removeEventListener("abort", stopOnAbort);
12141228
await waitForGracefulStop(stopRunner);

0 commit comments

Comments
 (0)