chore: refactor telephony

This commit is contained in:
Sabiha Khan 2026-02-14 07:28:36 +05:30
parent e485f649bd
commit 942a20bd14
14 changed files with 52 additions and 252 deletions

View file

@ -19,8 +19,8 @@ from api.services.telephony.transfer_event_protocol import (
)
class TransferCoordinator:
"""Coordinates transfer events and context storage using Redis."""
class CallTransferManager:
"""Manages call transfer events and context storage using Redis."""
def __init__(self, redis_client: Optional[aioredis.Redis] = None):
self._redis_client = redis_client
@ -155,7 +155,6 @@ class TransferCoordinator:
timeout_event = TransferEvent(
type=TransferEventType.TRANSFER_TIMEOUT,
tool_call_id=tool_call_id,
workflow_run_id=0, # Will be updated by caller
original_call_sid="",
status="failed",
reason="timeout",
@ -192,13 +191,13 @@ class TransferCoordinator:
logger.error(f"Error during transfer coordinator cleanup: {e}")
# Global transfer coordinator instance
_transfer_coordinator: Optional[TransferCoordinator] = None
# Global call transfer manager instance
_call_transfer_manager: Optional[CallTransferManager] = None
async def get_transfer_coordinator() -> TransferCoordinator:
"""Get or create the global transfer coordinator instance."""
global _transfer_coordinator
if not _transfer_coordinator:
_transfer_coordinator = TransferCoordinator()
return _transfer_coordinator
async def get_call_transfer_manager() -> CallTransferManager:
"""Get or create the global call transfer manager instance."""
global _call_transfer_manager
if not _call_transfer_manager:
_call_transfer_manager = CallTransferManager()
return _call_transfer_manager

View file

@ -27,7 +27,6 @@ class TransferEvent:
type: TransferEventType
tool_call_id: str
workflow_run_id: int
original_call_sid: str
transfer_call_sid: Optional[str] = None
target_number: Optional[str] = None
@ -75,7 +74,6 @@ class TransferContext:
original_call_sid: str
caller_number: Optional[str]
initiated_at: float
workflow_run_id: int
def to_json(self) -> str:
"""Convert context to JSON string."""

View file

@ -11,7 +11,7 @@ from typing import Optional
from loguru import logger
from api.services.telephony.transfer_coordination import get_transfer_coordinator
from api.services.telephony.call_transfer_manager import get_call_transfer_manager
from api.services.telephony.transfer_event_protocol import (
TransferContext,
TransferEvent,
@ -23,7 +23,7 @@ async def test_redis_coordination():
"""Test basic Redis pub/sub coordination for transfers."""
logger.info("Testing Redis-based transfer coordination...")
transfer_coordinator = await get_transfer_coordinator()
call_transfer_manager = await get_call_transfer_manager()
# Test 1: Store and retrieve transfer context
tool_call_id = str(uuid.uuid4())
@ -34,15 +34,14 @@ async def test_redis_coordination():
tool_uuid="test_tool_uuid",
original_call_sid="original_call_123",
caller_number="+0987654321",
initiated_at=time.time(),
workflow_run_id=123
initiated_at=time.time()
)
logger.info("Test 1: Storing transfer context...")
await transfer_coordinator.store_transfer_context(test_context)
await call_transfer_manager.store_transfer_context(test_context)
logger.info("Test 1: Retrieving transfer context...")
retrieved_context = await transfer_coordinator.get_transfer_context(tool_call_id)
retrieved_context = await call_transfer_manager.get_transfer_context(tool_call_id)
if retrieved_context and retrieved_context.tool_call_id == tool_call_id:
logger.info("✅ Test 1 PASSED: Context storage/retrieval works")
@ -55,7 +54,7 @@ async def test_redis_coordination():
# Start waiting for completion in background
async def wait_for_completion():
return await transfer_coordinator.wait_for_transfer_completion(tool_call_id, 5.0)
return await call_transfer_manager.wait_for_transfer_completion(tool_call_id, 5.0)
wait_task = asyncio.create_task(wait_for_completion())
@ -66,7 +65,6 @@ async def test_redis_coordination():
test_event = TransferEvent(
type=TransferEventType.TRANSFER_COMPLETED,
tool_call_id=tool_call_id,
workflow_run_id=123,
original_call_sid="original_call_123",
transfer_call_sid="transfer_call_456",
conference_name="test-conference",
@ -76,7 +74,7 @@ async def test_redis_coordination():
)
logger.info("Test 2: Publishing completion event...")
await transfer_coordinator.publish_transfer_event(test_event)
await call_transfer_manager.publish_transfer_event(test_event)
# Wait for the completion
received_event = await wait_task
@ -89,9 +87,9 @@ async def test_redis_coordination():
# Test 3: Cleanup
logger.info("Test 3: Testing cleanup...")
await transfer_coordinator.remove_transfer_context(tool_call_id)
await call_transfer_manager.remove_transfer_context(tool_call_id)
cleanup_context = await transfer_coordinator.get_transfer_context(tool_call_id)
cleanup_context = await call_transfer_manager.get_transfer_context(tool_call_id)
if cleanup_context is None:
logger.info("✅ Test 3 PASSED: Cleanup works")
else:
@ -106,12 +104,12 @@ async def test_timeout_handling():
"""Test timeout handling in transfer coordination."""
logger.info("Testing timeout handling...")
transfer_coordinator = await get_transfer_coordinator()
call_transfer_manager = await get_call_transfer_manager()
tool_call_id = str(uuid.uuid4())
# Wait for completion with short timeout (should timeout)
start_time = time.time()
result = await transfer_coordinator.wait_for_transfer_completion(tool_call_id, 2.0)
result = await call_transfer_manager.wait_for_transfer_completion(tool_call_id, 2.0)
elapsed = time.time() - start_time
if result is None and elapsed >= 2.0:

View file

@ -35,7 +35,7 @@ from pipecat.utils.enums import EndTaskReason
from pipecat.transports.websocket.fastapi import FastAPIWebsocketClient
from api.utils.hold_audio import load_hold_audio
from api.services.telephony.transfer_coordination import get_transfer_coordinator
from api.services.telephony.call_transfer_manager import get_call_transfer_manager
from api.services.telephony.transfer_event_protocol import (
TransferEvent,
TransferContext,
@ -359,7 +359,7 @@ class CustomToolManager:
backend_url, _ = await get_backend_endpoints()
# Get transfer coordinator for Redis-based coordination
transfer_coordinator = await get_transfer_coordinator()
call_transfer_manager = await get_call_transfer_manager()
# Now initiate the transfer call
transfer_url = f"{backend_url}/api/v1/telephony/call-transfer"
@ -415,7 +415,7 @@ class CustomToolManager:
"Waiting for transfer completion via Redis pub/sub..."
)
transfer_event = (
await transfer_coordinator.wait_for_transfer_completion(
await call_transfer_manager.wait_for_transfer_completion(
transfer_data["tool_call_id"], timeout_seconds
)
)
@ -435,7 +435,7 @@ class CustomToolManager:
# Get transfer context for caller number
transfer_context = (
await transfer_coordinator.get_transfer_context(
await call_transfer_manager.get_transfer_context(
transfer_data["tool_call_id"]
)
)