Fix critical bugs

This commit is contained in:
2026-02-20 14:30:45 +00:00
parent e9d80def08
commit aa816f0d64
5 changed files with 21 additions and 7 deletions

View File

@@ -73,7 +73,7 @@ filterwarnings = [
] ]
env = [ env = [
"FIRESTORE_EMULATOR_HOST=[::1]:8911", "FIRESTORE_EMULATOR_HOST=[::1]:8469",
"GCP_PROJECT_ID=test-project", "GCP_PROJECT_ID=test-project",
"GCP_LOCATION=us-central1", "GCP_LOCATION=us-central1",
"GCP_FIRESTORE_DATABASE_ID=(default)", "GCP_FIRESTORE_DATABASE_ID=(default)",

View File

@@ -370,12 +370,13 @@ class ConversationManagerService:
logger.info("Matched quick reply: %s", pregunta.titulo) logger.info("Matched quick reply: %s", pregunta.titulo)
break break
# If no match, use first question as default or delegate to normal flow # If no match, delegate to normal flow
if not matched_answer: if not matched_answer:
logger.warning( logger.warning(
"No matching quick reply found for message: '%s'.", "No matching quick reply found for message: '%s'. Falling back to RAG.",
request.mensaje, request.mensaje,
) )
return None
# Create response with the matched quick reply answer # Create response with the matched quick reply answer
return DetectIntentResponse( return DetectIntentResponse(

View File

@@ -17,6 +17,9 @@ logger = logging.getLogger(__name__)
PREFIX_PO_PARAM = "notification_po_" PREFIX_PO_PARAM = "notification_po_"
# Keep references to background tasks to prevent garbage collection
_background_tasks: set[asyncio.Task] = set()
class NotificationManagerService: class NotificationManagerService:
"""Manages notification processing and integration with conversations. """Manages notification processing and integration with conversations.
@@ -127,6 +130,8 @@ class NotificationManagerService:
) )
# Fire and forget - don't await # Fire and forget - don't await
_task = asyncio.create_task(save_notification_to_firestore()) task = asyncio.create_task(save_notification_to_firestore())
# Store reference to prevent premature garbage collection # Store reference to prevent premature garbage collection
del _task _background_tasks.add(task)
# Remove from set when done to prevent memory leak
task.add_done_callback(_background_tasks.discard)

View File

@@ -87,8 +87,11 @@ class QuickReplySessionService:
""" """
self._validate_phone(telefono) self._validate_phone(telefono)
# Get or create session # Get or create session (check Redis first for consistency)
session = await self.redis_service.get_session(telefono)
if not session:
session = await self.firestore_service.get_session_by_phone(telefono) session = await self.firestore_service.get_session_by_phone(telefono)
if session: if session:
session_id = session.session_id session_id = session.session_id
await self.firestore_service.update_pantalla_contexto( await self.firestore_service.update_pantalla_contexto(

View File

@@ -17,6 +17,7 @@ from capa_de_integracion.services.storage.redis import RedisService
def mock_redis(): def mock_redis():
"""Create mock Redis service.""" """Create mock Redis service."""
redis = Mock(spec=RedisService) redis = Mock(spec=RedisService)
redis.get_session = AsyncMock()
redis.save_session = AsyncMock() redis.save_session = AsyncMock()
return redis return redis
@@ -67,6 +68,7 @@ async def test_validate_phone_whitespace(service):
async def test_start_session_new_user(service, mock_firestore, mock_redis, mock_content): async def test_start_session_new_user(service, mock_firestore, mock_redis, mock_content):
"""Test starting a quick reply session for a new user.""" """Test starting a quick reply session for a new user."""
# Setup mocks # Setup mocks
mock_redis.get_session.return_value = None # No session in Redis
mock_firestore.get_session_by_phone.return_value = None # No existing session mock_firestore.get_session_by_phone.return_value = None # No existing session
# Mock create_session to return a session with the ID that was passed in # Mock create_session to return a session with the ID that was passed in
@@ -100,6 +102,7 @@ async def test_start_session_new_user(service, mock_firestore, mock_redis, mock_
assert result.session_id is not None # Session ID should be generated assert result.session_id is not None # Session ID should be generated
assert result.quick_replies.header == "Home Screen" assert result.quick_replies.header == "Home Screen"
mock_redis.get_session.assert_called_once_with("555-1234")
mock_firestore.get_session_by_phone.assert_called_once_with("555-1234") mock_firestore.get_session_by_phone.assert_called_once_with("555-1234")
mock_firestore.create_session.assert_called_once() mock_firestore.create_session.assert_called_once()
@@ -123,6 +126,7 @@ async def test_start_session_existing_user(service, mock_firestore, mock_redis,
telefono="555-1234", telefono="555-1234",
pantalla_contexto="old_screen", pantalla_contexto="old_screen",
) )
mock_redis.get_session.return_value = None # Not in Redis cache
mock_firestore.get_session_by_phone.return_value = test_session mock_firestore.get_session_by_phone.return_value = test_session
test_quick_replies = QuickReplyScreen( test_quick_replies = QuickReplyScreen(
@@ -145,6 +149,7 @@ async def test_start_session_existing_user(service, mock_firestore, mock_redis,
assert result.session_id == test_session_id assert result.session_id == test_session_id
assert result.quick_replies.header == "Payments Screen" assert result.quick_replies.header == "Payments Screen"
mock_redis.get_session.assert_called_once_with("555-1234")
mock_firestore.get_session_by_phone.assert_called_once_with("555-1234") mock_firestore.get_session_by_phone.assert_called_once_with("555-1234")
mock_firestore.update_pantalla_contexto.assert_called_once_with( mock_firestore.update_pantalla_contexto.assert_called_once_with(
test_session_id, test_session_id,