fix(voice-call): retry rejected inbound hangups

This commit is contained in:
Vincent Koc
2026-04-13 17:00:02 +01:00
parent a8977cde64
commit 2c3871b4b1
2 changed files with 53 additions and 1 deletions

View File

@@ -1,5 +1,5 @@
import { describe, expect, it } from "vitest";
import { createManagerHarness } from "./manager.test-harness.js";
import { FakeProvider, createManagerHarness } from "./manager.test-harness.js";
describe("CallManager inbound allowlist", () => {
it("rejects inbound calls with missing caller ID when allowlist enabled", async () => {
@@ -103,6 +103,57 @@ describe("CallManager inbound allowlist", () => {
]);
});
it("retries rejected inbound hangup after a transient provider failure", async () => {
class FlakyHangupProvider extends FakeProvider {
hangupFailuresRemaining = 1;
override async hangupCall(input: Parameters<FakeProvider["hangupCall"]>[0]): Promise<void> {
this.hangupCalls.push(input);
if (this.hangupFailuresRemaining > 0) {
this.hangupFailuresRemaining -= 1;
throw new Error("provider down");
}
}
}
const provider = new FlakyHangupProvider();
const { manager } = await createManagerHarness(
{
inboundPolicy: "disabled",
},
provider,
);
manager.processEvent({
id: "evt-reject-fail-init",
type: "call.initiated",
callId: "provider-flaky",
providerCallId: "provider-flaky",
timestamp: Date.now(),
direction: "inbound",
from: "+15553333333",
to: "+15550000000",
});
await Promise.resolve();
manager.processEvent({
id: "evt-reject-fail-ring",
type: "call.ringing",
callId: "provider-flaky",
providerCallId: "provider-flaky",
timestamp: Date.now(),
direction: "inbound",
from: "+15553333333",
to: "+15550000000",
});
expect(manager.getCallByProviderCallId("provider-flaky")).toBeUndefined();
expect(provider.hangupCalls).toEqual([
expect.objectContaining({ providerCallId: "provider-flaky" }),
expect.objectContaining({ providerCallId: "provider-flaky" }),
]);
});
it("accepts inbound calls that exactly match the allowlist", async () => {
const { manager } = await createManagerHarness({
inboundPolicy: "allowlist",

View File

@@ -138,6 +138,7 @@ export function processEvent(ctx: EventContext, event: NormalizedEvent): void {
reason: "hangup-bot",
})
.catch((err) => {
ctx.rejectedProviderCallIds.delete(pid);
const message = formatErrorMessage(err);
console.warn(`[voice-call] Failed to reject inbound call ${pid}:`, message);
});