From 109acc831aaef70e1920508596e090ae47c09764 Mon Sep 17 00:00:00 2001 From: leo <260626284+cameledev@users.noreply.github.com> Date: Wed, 9 Sep 2026 17:40:40 +0200 Subject: [PATCH] wip --- src/backend/core/recording/worker/services.py | 24 +++++++++++++++++ .../tests/recording/worker/test_services.py | 27 +++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/src/backend/core/recording/worker/services.py b/src/backend/core/recording/worker/services.py index 3d1ed593..59d6b369 100644 --- a/src/backend/core/recording/worker/services.py +++ b/src/backend/core/recording/worker/services.py @@ -2,6 +2,8 @@ # pylint: disable=no-member +import logging + from asgiref.sync import async_to_sync from livekit import api as livekit_api @@ -10,6 +12,8 @@ from ..enums import FileExtension from .exceptions import WorkerConnectionError, WorkerResponseError from .factories import WorkerServiceConfig +logger = logging.getLogger(__name__) + class BaseEgressService: """Base egress defining common methods to manage and interact with LiveKit egress processes.""" @@ -49,6 +53,23 @@ class BaseEgressService: finally: await lkapi.aclose() + @staticmethod + def _log_egress_error(response, event: str): + """Log the reason LiveKit reported an unsuccessful egress on stop. + + Mirrors the logging done in the 'egress_ended' webhook. The + StopEgress response carries the same error fields. + """ + + logger.error( + "Egress %s on stop (egress_id=%s, status=%s): %s (error_code=%s)", + event, + response.egress_id, + livekit_api.EgressStatus.Name(response.status), + response.error or "no error reported", + response.error_code or "no error_code reported", + ) + def stop(self, worker_id: str) -> str: """Stop an ongoing egress worker. The StopEgressRequest is shared among all types of egress, @@ -69,14 +90,17 @@ class BaseEgressService: # To avoid exposing EgressStatus values and coupling with LiveKit outside of this class, # the response status is mapped to simpler "ABORTED", "STOPPED" or "FAILED_TO_STOP" strings. if response.status == livekit_api.EgressStatus.EGRESS_ABORTED: + self._log_egress_error(response, "aborted") return "ABORTED" if response.status == livekit_api.EgressStatus.EGRESS_FAILED: + self._log_egress_error(response, "failed") return "FAILED" if response.status == livekit_api.EgressStatus.EGRESS_ENDING: return "STOPPED" + self._log_egress_error(response, "failed to stop") return "FAILED_TO_STOP" def start(self, room_name, recording_id): diff --git a/src/backend/core/tests/recording/worker/test_services.py b/src/backend/core/tests/recording/worker/test_services.py index 3d5d4813..b53175c3 100644 --- a/src/backend/core/tests/recording/worker/test_services.py +++ b/src/backend/core/tests/recording/worker/test_services.py @@ -4,6 +4,7 @@ Test worker service classes. # pylint: disable=protected-access,redefined-outer-name,unused-argument,no-member +import logging from unittest.mock import AsyncMock, Mock, patch import pytest @@ -175,6 +176,32 @@ def test_base_egress_stop_with_status(service, response_status, expected_result) assert result == expected_result +@pytest.mark.parametrize( + "response_status,event", + [ + (livekit_api.EgressStatus.EGRESS_ABORTED, "aborted"), + (livekit_api.EgressStatus.EGRESS_FAILED, "failed"), + (livekit_api.EgressStatus.EGRESS_COMPLETE, "failed to stop"), + ], +) +def test_base_egress_stop_logs_livekit_error(service, response_status, event, caplog): + """Should log the reason LiveKit reported for an unsuccessful stop.""" + mock_response = Mock( + status=response_status, + egress_id="test_worker_id", + error="could not connect to the room", + error_code=500, + ) + service._handle_request = Mock(return_value=mock_response) + + with caplog.at_level(logging.ERROR): + service.stop("test_worker_id") + + assert f"Egress {event} on stop (egress_id=test_worker_id" in caplog.text + assert "could not connect to the room" in caplog.text + assert "error_code=500" in caplog.text + + def test_base_egress_stop_missing_status(service): """Test stop method when response is missing status""" # Mock _handle_request with missing status