mirror of
https://github.com/suitenumerique/meet.git
synced 2026-09-09 17:05:56 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 05f3610b1c | |||
| 06d9a2e7de |
@@ -10,12 +10,10 @@ and this project adheres to
|
||||
|
||||
### Fixed
|
||||
|
||||
- 🐛(backend) acknowledge unknown LiveKit webhook events instead of 422
|
||||
- 🔒️(backend) enforce display name setting on rename API
|
||||
|
||||
### Changed
|
||||
|
||||
- 📈(frontend) include LiveKit SIDs in the connection analytics event
|
||||
- 🔇(backend) silence expected 401 warnings on /me
|
||||
- 🔇(backend) silence noisy request summary info logs
|
||||
|
||||
|
||||
@@ -52,6 +52,12 @@ class InvalidPayloadError(LiveKitWebhookError):
|
||||
status_code = 400
|
||||
|
||||
|
||||
class UnsupportedEventTypeError(LiveKitWebhookError):
|
||||
"""Unsupported event type."""
|
||||
|
||||
status_code = 422
|
||||
|
||||
|
||||
class ActionFailedError(LiveKitWebhookError):
|
||||
"""Webhook action fails to process or complete."""
|
||||
|
||||
@@ -68,7 +74,6 @@ class LiveKitWebhookEventType(Enum):
|
||||
# Participant events
|
||||
PARTICIPANT_JOINED = "participant_joined"
|
||||
PARTICIPANT_LEFT = "participant_left"
|
||||
PARTICIPANT_CONNECTION_ABORTED = "participant_connection_aborted"
|
||||
|
||||
# Track events
|
||||
TRACK_PUBLISHED = "track_published"
|
||||
@@ -148,13 +153,10 @@ class LiveKitEventsService:
|
||||
|
||||
try:
|
||||
webhook_type = LiveKitWebhookEventType(data.event)
|
||||
except ValueError:
|
||||
logger.warning(
|
||||
"Ignoring unknown LiveKit webhook event type '%s' for room '%s'",
|
||||
data.event,
|
||||
room_name,
|
||||
)
|
||||
return
|
||||
except ValueError as e:
|
||||
raise UnsupportedEventTypeError(
|
||||
f"Unknown webhook type: {data.event}"
|
||||
) from e
|
||||
|
||||
# Handle according to received webhook type
|
||||
handler = self._webhook_handlers.get(webhook_type.value)
|
||||
|
||||
@@ -94,7 +94,7 @@ def test_invalid_payload(client, auth_token, mock_livekit_config):
|
||||
|
||||
|
||||
def test_unknown_event_type(client, mock_livekit_config):
|
||||
"""Should acknowledge (200) an unknown event type rather than reject it."""
|
||||
"""Should return 422 for unknown event type."""
|
||||
event_data = json.dumps({"event": "unknown_event_type"})
|
||||
|
||||
# Generate auth token for this specific payload
|
||||
@@ -112,8 +112,10 @@ def test_unknown_event_type(client, mock_livekit_config):
|
||||
HTTP_AUTHORIZATION=auth_token,
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"status": "success"}
|
||||
assert response.status_code == 422
|
||||
assert response.json() == {
|
||||
"status": "error",
|
||||
}
|
||||
|
||||
|
||||
@mock.patch.object(LiveKitEventsService, "_handle_room_finished")
|
||||
|
||||
@@ -16,6 +16,7 @@ from core.services.livekit_events import (
|
||||
AuthenticationError,
|
||||
InvalidPayloadError,
|
||||
LiveKitEventsService,
|
||||
UnsupportedEventTypeError,
|
||||
api,
|
||||
)
|
||||
from core.services.lobby import LobbyService
|
||||
@@ -664,27 +665,22 @@ def test_receive_missing_auth(service):
|
||||
|
||||
|
||||
@mock.patch.object(api.WebhookReceiver, "receive")
|
||||
def test_receive_unknown_event_is_acknowledged(mock_receive, service, caplog):
|
||||
"""Unknown event types are logged and ignored, not rejected.
|
||||
|
||||
LiveKit adds event types over time and does not retry 4xx responses, so
|
||||
raising here would silently drop the event.
|
||||
"""
|
||||
def test_receive_unsupported_event(mock_receive, service):
|
||||
"""Should raise LiveKitWebhookError for unsupported events."""
|
||||
mock_request = mock.MagicMock()
|
||||
mock_request.headers = {"Authorization": "test_token"}
|
||||
mock_request.body = b"{}"
|
||||
|
||||
# Mock returned data with unsupported event type
|
||||
mock_data = mock.MagicMock()
|
||||
mock_data.room.name = str(uuid.uuid4())
|
||||
mock_data.event = "some_future_event"
|
||||
mock_data.event = "unsupported_event"
|
||||
mock_receive.return_value = mock_data
|
||||
|
||||
with caplog.at_level("WARNING", logger="core.services.livekit_events"):
|
||||
service.receive(mock_request) # must not raise
|
||||
|
||||
assert "Ignoring unknown LiveKit webhook event type 'some_future_event'" in (
|
||||
caplog.text
|
||||
)
|
||||
with pytest.raises(
|
||||
UnsupportedEventTypeError, match="Unknown webhook type: unsupported_event"
|
||||
):
|
||||
service.receive(mock_request)
|
||||
|
||||
|
||||
@mock.patch.object(api.WebhookReceiver, "receive")
|
||||
|
||||
@@ -71,30 +71,20 @@ export const ConnectionObserver = () => {
|
||||
useEffect(() => {
|
||||
if (!isAnalyticsEnabled) return
|
||||
|
||||
const handleConnection = async () => {
|
||||
const handleConnection = () => {
|
||||
// Preserve original connection timestamp across reconnections to measure
|
||||
// total session duration from first connect to final disconnect.
|
||||
if (connectionStartTimeRef.current != null) return
|
||||
connectionStartTimeRef.current = Date.now()
|
||||
const participantSid = room.localParticipant.sid
|
||||
const roomSid = await room.getSid().catch(() => undefined)
|
||||
void captureMediaEvent('connection-event', {
|
||||
livekit_room_sid: roomSid,
|
||||
livekit_participant_sid: participantSid,
|
||||
})
|
||||
void captureMediaEvent('connection-event', {})
|
||||
}
|
||||
|
||||
const handleReconnect = () => {
|
||||
captureEvent('reconnect-event')
|
||||
}
|
||||
|
||||
const handleReconnected = async () => {
|
||||
const participantSid = room.localParticipant.sid
|
||||
const roomSid = await room.getSid().catch(() => undefined)
|
||||
captureEvent('reconnected-event', {
|
||||
livekit_room_sid: roomSid,
|
||||
livekit_participant_sid: participantSid,
|
||||
})
|
||||
const handleReconnected = () => {
|
||||
captureEvent('reconnected-event')
|
||||
}
|
||||
|
||||
const handleSignalingConnect = () => {
|
||||
|
||||
Reference in New Issue
Block a user