diff --git a/apps/api/src/services/platform_operator_service.py b/apps/api/src/services/platform_operator_service.py index e498c601b..907581103 100644 --- a/apps/api/src/services/platform_operator_service.py +++ b/apps/api/src/services/platform_operator_service.py @@ -7319,21 +7319,42 @@ async def list_recent_channel_events( ) -> dict[str, Any]: """列出最近 channel events,供 Operator Console 顯示收斂/鏡像脈絡。""" safe_limit = max(1, min(limit, _MAX_EVENTS)) + recent_provider_prefix = ( + provider_prefix.strip().lower() if provider_prefix else None + ) + if not recent_provider_prefix: + recent_provider_prefix = None async with get_db_context("awoooi") as db: - stmt = select(AwoooPConversationEvent).order_by( - AwoooPConversationEvent.received_at.desc() - ) + stmt = select(AwoooPConversationEvent) if project_id is not None: stmt = stmt.where(AwoooPConversationEvent.project_id == project_id) if channel_type is not None: stmt = stmt.where(AwoooPConversationEvent.channel_type == channel_type) - if provider_prefix is not None: - stmt = stmt.where( - AwoooPConversationEvent.provider_event_id.like( - f"{provider_prefix}%" + if recent_provider_prefix is not None: + if ":" in recent_provider_prefix: + stmt = stmt.where( + AwoooPConversationEvent.provider_event_id.like( + f"{provider_prefix.strip()}%" + ) ) + else: + stmt = stmt.where( + text( + "LOWER(COALESCE(" + "NULLIF(source_envelope->>'provider', ''), " + "NULLIF(split_part(provider_event_id, ':', 1), ''), " + "channel_type" + ")) = :recent_provider_prefix" + ) + ) + stmt = stmt.params(recent_provider_prefix=recent_provider_prefix) + stmt = stmt.order_by( + AwoooPConversationEvent.received_at.desc(), + AwoooPConversationEvent.event_id.desc(), ) + else: + stmt = stmt.order_by(AwoooPConversationEvent.received_at.desc()) result = await db.execute(stmt.limit(safe_limit)) rows = list(result.scalars().all()) diff --git a/apps/api/tests/test_awooop_conversation_event_hot_path_indexes.py b/apps/api/tests/test_awooop_conversation_event_hot_path_indexes.py index adb7ada07..202f71e3a 100644 --- a/apps/api/tests/test_awooop_conversation_event_hot_path_indexes.py +++ b/apps/api/tests/test_awooop_conversation_event_hot_path_indexes.py @@ -58,6 +58,8 @@ def test_provider_recent_indexes_match_live_hot_queries() -> None: assert "COALESCE(NULLIF(source_envelope->>'provider', '')" in coverage_source assert "ORDER BY received_at DESC" in coverage_source assert "LOWER(COALESCE(NULLIF(source_envelope->>'provider', '')" in operator_source + assert "recent_provider_prefix" in operator_source + assert "NULLIF(split_part(provider_event_id, ':', 1), '')" in operator_source assert "idx_awooop_conv_event_project_provider_recent" in sql assert "idx_awooop_conv_event_project_provider_lower_recent" in sql