Skip to content

Commit bac5e4b

Browse files
committed
decode_server_notifications
1 parent ec1d984 commit bac5e4b

6 files changed

Lines changed: 135 additions & 19 deletions

File tree

examples/room_manager/routes.py

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from flask import Flask, abort, jsonify, request
44
from room_service import RoomService
55

6-
from fishjam import receive_binary
6+
from fishjam import decode_server_notifications
77
from fishjam.room import RoomType
88

99

@@ -36,12 +36,7 @@ def get_room_query():
3636

3737
@app.post("/api/rooms/webhook")
3838
def webhook():
39-
message = receive_binary(request.data)
40-
41-
if message:
42-
notifications = message if isinstance(message, list) else [message]
43-
44-
for notification in notifications:
45-
room_service.handle_notification(notification)
39+
for notification in decode_server_notifications(request.data):
40+
room_service.handle_notification(notification)
4641

4742
return "Webhook Notification Received", 200

fishjam/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from fishjam._openapi_client.models import PeerMetadata
1313

1414
# API
15-
from fishjam._webhook_notifier import receive_binary
15+
from fishjam._webhook_notifier import decode_server_notifications, receive_binary
1616
from fishjam._ws_notifier import FishjamNotifier
1717
from fishjam.api._fishjam_client import (
1818
AgentOptions,
@@ -31,6 +31,7 @@
3131
__all__ = [
3232
"FishjamClient",
3333
"FishjamNotifier",
34+
"decode_server_notifications",
3435
"receive_binary",
3536
"PeerMetadata",
3637
"PeerOptions",

fishjam/_webhook_notifier.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""Module for decoding received webhook notifications from Fishjam."""
22

3+
import warnings
34
from typing import List, Union
45

56
import betterproto
@@ -40,11 +41,43 @@ def _unpack_batch(
4041
return notifications
4142

4243

44+
def decode_server_notifications(binary: bytes) -> List[AllowedNotification]:
45+
"""Decode a received protobuf payload into a list of notifications.
46+
47+
Handles both single notifications and batches transparently: a single
48+
notification is returned as a one-element list, a batch is unpacked into
49+
its members (in order), and anything unsupported yields an empty list.
50+
51+
The available notifications are listed in the `fishjam.events` module.
52+
53+
Args:
54+
binary: The raw binary data received from the webhook.
55+
56+
Returns:
57+
list[AllowedNotification]: The decoded notifications, in order. Empty
58+
when the payload carries no supported notification.
59+
"""
60+
message = ServerMessage().parse(binary)
61+
_which, content = betterproto.which_one_of(message, "content")
62+
63+
if isinstance(content, ServerMessageNotificationBatch):
64+
return _unpack_batch(content)
65+
66+
if isinstance(content, ALLOWED_NOTIFICATIONS):
67+
return [content]
68+
69+
return []
70+
71+
4372
def receive_binary(
4473
binary: bytes,
4574
) -> Union[AllowedNotification, List[AllowedNotification], None]:
4675
"""Transforms a received protobuf notification into a notification instance.
4776
77+
.. deprecated::
78+
Use `decode_server_notifications` instead, which always returns a list
79+
and handles batched payloads with a single, consistent return type.
80+
4881
The available notifications are listed in `fishjam.events` module.
4982
5083
Args:
@@ -56,6 +89,12 @@ def receive_binary(
5689
payload is a batch (webhook batching enabled).
5790
None: When the payload is not a supported notification.
5891
"""
92+
warnings.warn(
93+
"receive_binary is deprecated; use decode_server_notifications instead.",
94+
DeprecationWarning,
95+
stacklevel=2,
96+
)
97+
5998
message = ServerMessage().parse(binary)
6099
_which, content = betterproto.which_one_of(message, "content")
61100

tests/support/webhook_notifier.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from flask import Flask, Response, request
44

5-
from fishjam import receive_binary
5+
from fishjam import decode_server_notifications
66

77
app = Flask(__name__)
88
QUEUES = None
@@ -16,12 +16,9 @@ def respond_default():
1616
@app.route("/webhook", methods=["POST"])
1717
def respond_root():
1818
data = request.get_data()
19-
msg = receive_binary(data)
20-
if msg is not None:
21-
notifications = msg if isinstance(msg, list) else [msg]
22-
for notification in notifications:
23-
for q in QUEUES.values():
24-
q.put(notification)
19+
for notification in decode_server_notifications(data):
20+
for q in QUEUES.values():
21+
q.put(notification)
2522

2623
return Response(status=200)
2724

tests/test_allowed_notifications.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020
"ServerMessageTrackForwarding",
2121
"ServerMessageTrackForwardingRemoved",
2222
"ServerMessageVadNotification",
23-
# Transport wrapper, not a user-facing event: `receive_binary` unpacks it
24-
# into the individual notifications it carries.
23+
# Transport wrapper, not a user-facing event: `decode_server_notifications`
24+
# unpacks it into the individual notifications it carries.
2525
"ServerMessageNotificationBatch",
2626
# Deprecated in the proto.
2727
"ServerMessageStreamConnected",

tests/test_webhook_notifier.py

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
from fishjam import receive_binary
1+
import pytest
2+
3+
from fishjam import decode_server_notifications, receive_binary
24
from fishjam.events import (
35
ServerMessagePeerConnected,
46
ServerMessageRoomCreated,
@@ -87,3 +89,85 @@ def test_empty_batch_returns_empty_list():
8789
result = receive_binary(binary)
8890

8991
assert result == []
92+
93+
94+
def test_receive_binary_is_deprecated():
95+
binary = bytes(ServerMessage(room_created=ServerMessageRoomCreated(room_id="r1")))
96+
97+
with pytest.warns(DeprecationWarning):
98+
receive_binary(binary)
99+
100+
101+
def test_decode_single_notification_returns_one_element_list():
102+
binary = bytes(ServerMessage(room_created=ServerMessageRoomCreated(room_id="r1")))
103+
104+
result = decode_server_notifications(binary)
105+
106+
assert isinstance(result, list)
107+
assert [type(n) for n in result] == [ServerMessageRoomCreated]
108+
assert result[0].room_id == "r1"
109+
110+
111+
def test_decode_unsupported_single_message_returns_empty_list():
112+
binary = bytes(ServerMessage(auth_request=ServerMessageAuthRequest(token="t")))
113+
114+
assert decode_server_notifications(binary) == []
115+
116+
117+
def test_decode_batch_is_unpacked_into_ordered_list():
118+
binary = bytes(
119+
ServerMessage(
120+
notification_batch=ServerMessageNotificationBatch(
121+
notifications=[
122+
ServerMessage(room_created=ServerMessageRoomCreated(room_id="r1")),
123+
ServerMessage(
124+
peer_connected=ServerMessagePeerConnected(
125+
room_id="r1", peer_id="p1"
126+
)
127+
),
128+
ServerMessage(room_deleted=ServerMessageRoomDeleted(room_id="r1")),
129+
]
130+
)
131+
)
132+
)
133+
134+
result = decode_server_notifications(binary)
135+
136+
assert [type(n) for n in result] == [
137+
ServerMessageRoomCreated,
138+
ServerMessagePeerConnected,
139+
ServerMessageRoomDeleted,
140+
]
141+
assert result[0].room_id == "r1"
142+
assert result[1].peer_id == "p1"
143+
144+
145+
def test_decode_batch_filters_out_unsupported_members():
146+
binary = bytes(
147+
ServerMessage(
148+
notification_batch=ServerMessageNotificationBatch(
149+
notifications=[
150+
ServerMessage(room_created=ServerMessageRoomCreated(room_id="r1")),
151+
ServerMessage(auth_request=ServerMessageAuthRequest(token="t")),
152+
ServerMessage(room_deleted=ServerMessageRoomDeleted(room_id="r1")),
153+
]
154+
)
155+
)
156+
)
157+
158+
result = decode_server_notifications(binary)
159+
160+
assert [type(n) for n in result] == [
161+
ServerMessageRoomCreated,
162+
ServerMessageRoomDeleted,
163+
]
164+
165+
166+
def test_decode_empty_batch_returns_empty_list():
167+
binary = bytes(
168+
ServerMessage(
169+
notification_batch=ServerMessageNotificationBatch(notifications=[])
170+
)
171+
)
172+
173+
assert decode_server_notifications(binary) == []

0 commit comments

Comments
 (0)