From a59fc507c991bcfe5786009226ac594e027dd4b1 Mon Sep 17 00:00:00 2001 From: leo <260626284+cameledev@users.noreply.github.com> Date: Wed, 9 Sep 2026 16:55:58 +0200 Subject: [PATCH] fix 1 --- src/backend/core/services/livekit_events.py | 13 ++++- .../tests/services/test_livekit_events.py | 51 +++++++++++++++++-- 2 files changed, 57 insertions(+), 7 deletions(-) diff --git a/src/backend/core/services/livekit_events.py b/src/backend/core/services/livekit_events.py index 6a287e28..88402fcb 100644 --- a/src/backend/core/services/livekit_events.py +++ b/src/backend/core/services/livekit_events.py @@ -92,6 +92,12 @@ class LiveKitWebhookEventType(Enum): class LiveKitEventsService: """Service for processing and handling LiveKit webhook events and notifications.""" + # Terminal egress statuses LiveKit reports when the recording did not succeed. + UNSUCCESSFUL_EGRESS_EVENTS = { + api.EgressStatus.EGRESS_ABORTED: "aborted", + api.EgressStatus.EGRESS_FAILED: "failed", + } + def __init__(self): """Initialize with required services.""" @@ -220,7 +226,6 @@ class LiveKitEventsService: data.egress_info.status == api.EgressStatus.EGRESS_ABORTED and recording.status == models.RecordingStatusChoices.ACTIVE ): - self._log_egress_error(data, recording, "aborted") try: self.recording_events.handle_aborted(recording) except RecordingEventsError: @@ -232,7 +237,6 @@ class LiveKitEventsService: data.egress_info.status == api.EgressStatus.EGRESS_FAILED and recording.is_savable() ): - self._log_egress_error(data, recording, "failed") try: self.recording_events.handle_failed(recording) except RecordingEventsError: @@ -273,6 +277,11 @@ class LiveKitEventsService: f"Recording with worker ID {data.egress_info.egress_id} does not exist" ) from err + # Log unsuccessful events + event = self.UNSUCCESSFUL_EGRESS_EVENTS.get(data.egress_info.status) + if event is not None: + self._log_egress_error(data, recording, event) + # Update room try: room_name = str(recording.room.id) diff --git a/src/backend/core/tests/services/test_livekit_events.py b/src/backend/core/tests/services/test_livekit_events.py index 39f735e4..3792d078 100644 --- a/src/backend/core/tests/services/test_livekit_events.py +++ b/src/backend/core/tests/services/test_livekit_events.py @@ -455,20 +455,30 @@ def test_handle_egress_ended_unsuccessful_egress_notification_fails( @pytest.mark.parametrize( - ("egress_status", "event"), + ("egress_status", "recording_status", "event"), ( - (EgressStatus.EGRESS_ABORTED, "aborted"), - (EgressStatus.EGRESS_FAILED, "failed"), + (EgressStatus.EGRESS_ABORTED, "active", "aborted"), + (EgressStatus.EGRESS_FAILED, "active", "failed"), + # The synchronous stop may already have persisted the terminal status, + # and the error details exist only in the webhook payload. + (EgressStatus.EGRESS_ABORTED, "aborted", "aborted"), + (EgressStatus.EGRESS_FAILED, "failed", "failed"), ), ) @mock.patch("core.utils.notify_participants") @mock.patch("core.services.room_management.RoomManagement.update_metadata") def test_handle_egress_ended_logs_livekit_error( # noqa: PLR0913 - mock_update_metadata, mock_notify, egress_status, event, service, caplog + mock_update_metadata, + mock_notify, + egress_status, + recording_status, + event, + service, + caplog, ): # pylint: disable=too-many-arguments,too-many-positional-arguments """Should log the reason LiveKit reported an unsuccessful egress.""" - recording = RecordingFactory(worker_id="worker-1", status="active") + recording = RecordingFactory(worker_id="worker-1", status=recording_status) mock_data = mock.MagicMock() mock_data.egress_info.egress_id = recording.worker_id mock_data.egress_info.status = egress_status @@ -483,6 +493,37 @@ def test_handle_egress_ended_logs_livekit_error( # noqa: PLR0913 assert "error_code=500" in caplog.text +@pytest.mark.parametrize( + "egress_status", + (EgressStatus.EGRESS_COMPLETE, EgressStatus.EGRESS_LIMIT_REACHED), +) +@mock.patch( + "core.recording.services.recording_events.notification_service." + "notify_external_services" +) +@mock.patch("core.utils.notify_participants") +@mock.patch("core.services.room_management.RoomManagement.update_metadata") +def test_handle_egress_ended_does_not_log_error_on_successful_egress( # noqa: PLR0913 + mock_update_metadata, + mock_notify, + mock_notify_external_services, + egress_status, + service, + caplog, +): # pylint: disable=too-many-arguments,too-many-positional-arguments + """Shouldn't log an egress error when LiveKit reports a successful egress.""" + + recording = RecordingFactory(worker_id="worker-1", status="active") + mock_data = mock.MagicMock() + mock_data.egress_info.egress_id = recording.worker_id + mock_data.egress_info.status = egress_status + + with caplog.at_level(logging.ERROR): + service._handle_egress_ended(mock_data) + + assert "Egress" not in caplog.text + + @pytest.mark.parametrize( "egress_status", [