test: add coverage for conflict errors, abort signal, and backoff progression
This commit is contained in:
parent
3200d25a99
commit
a52db23c08
@ -227,4 +227,79 @@ describe("monitorTelegramProvider (grammY)", () => {
|
|||||||
expect(sleepWithAbort).toHaveBeenCalled();
|
expect(sleepWithAbort).toHaveBeenCalled();
|
||||||
expect(runSpy).toHaveBeenCalledTimes(2);
|
expect(runSpy).toHaveBeenCalledTimes(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("retries on getUpdates conflict errors (409)", async () => {
|
||||||
|
const conflictError = Object.assign(new Error("Conflict: terminated by other getUpdates"), {
|
||||||
|
error_code: 409,
|
||||||
|
description: "Conflict: terminated by other getUpdates request",
|
||||||
|
method: "getUpdates",
|
||||||
|
});
|
||||||
|
runSpy
|
||||||
|
.mockImplementationOnce(() => ({
|
||||||
|
task: () => Promise.reject(conflictError),
|
||||||
|
stop: vi.fn(),
|
||||||
|
}))
|
||||||
|
.mockImplementationOnce(() => ({
|
||||||
|
task: () => Promise.resolve(),
|
||||||
|
stop: vi.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
await monitorTelegramProvider({ token: "tok" });
|
||||||
|
|
||||||
|
expect(computeBackoff).toHaveBeenCalled();
|
||||||
|
expect(sleepWithAbort).toHaveBeenCalled();
|
||||||
|
expect(runSpy).toHaveBeenCalledTimes(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("respects abort signal during retry backoff", async () => {
|
||||||
|
const abortController = new AbortController();
|
||||||
|
const networkError = Object.assign(new Error("timeout"), { code: "ETIMEDOUT" });
|
||||||
|
|
||||||
|
// Mock sleepWithAbort to abort mid-sleep
|
||||||
|
sleepWithAbort.mockImplementationOnce(async () => {
|
||||||
|
abortController.abort();
|
||||||
|
throw new Error("Aborted");
|
||||||
|
});
|
||||||
|
|
||||||
|
runSpy.mockImplementationOnce(() => ({
|
||||||
|
task: () => Promise.reject(networkError),
|
||||||
|
stop: vi.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
await monitorTelegramProvider({ token: "tok", abortSignal: abortController.signal });
|
||||||
|
|
||||||
|
expect(runSpy).toHaveBeenCalledTimes(1);
|
||||||
|
expect(computeBackoff).toHaveBeenCalled();
|
||||||
|
expect(sleepWithAbort).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("uses exponential backoff for consecutive failures", async () => {
|
||||||
|
computeBackoff.mockReturnValueOnce(2000).mockReturnValueOnce(3600).mockReturnValueOnce(6480);
|
||||||
|
|
||||||
|
runSpy
|
||||||
|
.mockImplementationOnce(() => ({
|
||||||
|
task: () => Promise.reject(Object.assign(new Error("timeout"), { code: "ETIMEDOUT" })),
|
||||||
|
stop: vi.fn(),
|
||||||
|
}))
|
||||||
|
.mockImplementationOnce(() => ({
|
||||||
|
task: () => Promise.reject(Object.assign(new Error("timeout"), { code: "ETIMEDOUT" })),
|
||||||
|
stop: vi.fn(),
|
||||||
|
}))
|
||||||
|
.mockImplementationOnce(() => ({
|
||||||
|
task: () => Promise.reject(Object.assign(new Error("timeout"), { code: "ETIMEDOUT" })),
|
||||||
|
stop: vi.fn(),
|
||||||
|
}))
|
||||||
|
.mockImplementationOnce(() => ({
|
||||||
|
task: () => Promise.resolve(),
|
||||||
|
stop: vi.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
await monitorTelegramProvider({ token: "tok" });
|
||||||
|
|
||||||
|
// Verify backoff was called with increasing attempt numbers
|
||||||
|
expect(computeBackoff).toHaveBeenCalledTimes(4); // 3 failures + 1 normal stop
|
||||||
|
expect(computeBackoff).toHaveBeenCalledWith(expect.anything(), 1);
|
||||||
|
expect(computeBackoff).toHaveBeenCalledWith(expect.anything(), 2);
|
||||||
|
expect(computeBackoff).toHaveBeenCalledWith(expect.anything(), 3);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user