Skip to content

Commit 0367d81

Browse files
committed
tweak the example sever
1 parent 5339c35 commit 0367d81

File tree

2 files changed

+83
-2
lines changed

2 files changed

+83
-2
lines changed

examples/realtime/twilio_sip/server.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,15 @@ async def observe_call(call_id: str) -> None:
173173

174174
def _track_call_task(call_id: str) -> None:
175175
existing = active_call_tasks.get(call_id)
176-
if existing and not existing.done():
177-
existing.cancel()
176+
if existing:
177+
if not existing.done():
178+
logger.info(
179+
"Call %s already has an active observer; ignoring duplicate webhook delivery.",
180+
call_id,
181+
)
182+
return
183+
# Remove completed tasks so a new observer can start for a fresh call.
184+
active_call_tasks.pop(call_id, None)
178185

179186
task = asyncio.create_task(observe_call(call_id))
180187
active_call_tasks[call_id] = task
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
from __future__ import annotations
2+
3+
import importlib
4+
from types import ModuleType
5+
from unittest.mock import AsyncMock, Mock
6+
7+
import pytest
8+
9+
#
10+
# This is a unit test for examples/realtime/twilio_sip/server.py
11+
# If this is no longer relevant in the future, we can remove it.
12+
#
13+
14+
@pytest.fixture
15+
def twilio_server(monkeypatch: pytest.MonkeyPatch) -> ModuleType:
16+
monkeypatch.setenv("OPENAI_API_KEY", "test")
17+
monkeypatch.setenv("OPENAI_WEBHOOK_SECRET", "secret")
18+
module = importlib.import_module("examples.realtime.twilio_sip.server")
19+
module = importlib.reload(module)
20+
monkeypatch.setattr(module, "active_call_tasks", {})
21+
return module
22+
23+
24+
@pytest.mark.asyncio
25+
async def test_track_call_task_ignores_duplicate_webhooks(
26+
monkeypatch: pytest.MonkeyPatch, twilio_server: ModuleType
27+
) -> None:
28+
call_id = "call-123"
29+
existing_task = Mock()
30+
existing_task.done.return_value = False
31+
existing_task.cancel = Mock()
32+
33+
monkeypatch.setitem(twilio_server.active_call_tasks, call_id, existing_task)
34+
35+
create_task_mock = Mock()
36+
37+
def fake_create_task(coro):
38+
coro.close()
39+
return create_task_mock.return_value
40+
41+
monkeypatch.setattr(twilio_server.asyncio, "create_task", fake_create_task)
42+
43+
twilio_server._track_call_task(call_id)
44+
45+
existing_task.cancel.assert_not_called()
46+
create_task_mock.assert_not_called()
47+
assert twilio_server.active_call_tasks[call_id] is existing_task
48+
49+
50+
@pytest.mark.asyncio
51+
async def test_track_call_task_restarts_after_completion(
52+
monkeypatch: pytest.MonkeyPatch, twilio_server: ModuleType
53+
) -> None:
54+
call_id = "call-456"
55+
existing_task = Mock()
56+
existing_task.done.return_value = True
57+
existing_task.cancel = Mock()
58+
59+
monkeypatch.setitem(twilio_server.active_call_tasks, call_id, existing_task)
60+
61+
new_task = AsyncMock()
62+
create_task_mock = Mock(return_value=new_task)
63+
64+
def fake_create_task(coro):
65+
coro.close()
66+
return create_task_mock(coro)
67+
68+
monkeypatch.setattr(twilio_server.asyncio, "create_task", fake_create_task)
69+
70+
twilio_server._track_call_task(call_id)
71+
72+
existing_task.cancel.assert_not_called()
73+
create_task_mock.assert_called_once()
74+
assert twilio_server.active_call_tasks[call_id] is new_task

0 commit comments

Comments
 (0)