From 1b9e5134e33e2863bd3e55c408068471b970e530 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Ro=C5=BCnawski?= Date: Mon, 27 Apr 2026 20:45:30 +0200 Subject: [PATCH 1/7] Allow notification batching --- doc/docs.md | 31 +++++++++++++++++++ fishjam/server_notifications.proto | 23 ++++++++++++++ .../lib/fishjam/server_notifications.pb.ex | 17 ++++++++++ 3 files changed, 71 insertions(+) diff --git a/doc/docs.md b/doc/docs.md index c0822f3..e190805 100644 --- a/doc/docs.md +++ b/doc/docs.md @@ -97,6 +97,7 @@ - [ServerMessage.HlsPlayable](#fishjam-ServerMessage-HlsPlayable) - [ServerMessage.HlsUploadCrashed](#fishjam-ServerMessage-HlsUploadCrashed) - [ServerMessage.HlsUploaded](#fishjam-ServerMessage-HlsUploaded) + - [ServerMessage.NotificationBatch](#fishjam-ServerMessage-NotificationBatch) - [ServerMessage.PeerAdded](#fishjam-ServerMessage-PeerAdded) - [ServerMessage.PeerConnected](#fishjam-ServerMessage-PeerConnected) - [ServerMessage.PeerCrashed](#fishjam-ServerMessage-PeerCrashed) @@ -1363,6 +1364,7 @@ Defines any type of message passed between FJ and server peer | viewer_disconnected | [ServerMessage.ViewerDisconnected](#fishjam-ServerMessage-ViewerDisconnected) | | | | streamer_connected | [ServerMessage.StreamerConnected](#fishjam-ServerMessage-StreamerConnected) | | | | streamer_disconnected | [ServerMessage.StreamerDisconnected](#fishjam-ServerMessage-StreamerDisconnected) | | | +| notification_batch | [ServerMessage.NotificationBatch](#fishjam-ServerMessage-NotificationBatch) | | Batch | | stream_connected | [ServerMessage.StreamConnected](#fishjam-ServerMessage-StreamConnected) | | **Deprecated.** | | stream_disconnected | [ServerMessage.StreamDisconnected](#fishjam-ServerMessage-StreamDisconnected) | | **Deprecated.** | | hls_playable | [ServerMessage.HlsPlayable](#fishjam-ServerMessage-HlsPlayable) | | **Deprecated.** | @@ -1384,6 +1386,7 @@ Request sent by peer, to authenticate to FJ server | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | token | [string](#string) | | | +| supports_notification_batch | [bool](#bool) | | If true, the server may deliver NotificationBatch in addition to single-notification ServerMessages. Defaults to false for websocket and old peers. | @@ -1498,6 +1501,34 @@ Notification sent when the HLS recording is successfully uploaded to AWS S3 + + +### ServerMessage.NotificationBatch +Carries multiple notifications in a single wire frame. + +Constraints (documented, not schema-enforced): + - Each element's `content` MUST be a notification variant — never + Authenticated, AuthRequest, SubscribeRequest, or SubscribeResponse. + - NotificationBatch MUST NOT be nested inside another NotificationBatch. + The schema technically permits this, but senders must not emit + recursive batches and receivers may treat them as a protocol violation. + - Notifications are delivered in array order; consumers must process + them in order. + - The batch is wire-atomic but not semantically atomic: emitting two + batches vs. one batch of the same elements is equivalent. + - Sent only to peers that opted in via + AuthRequest.supports_notification_batch. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| notifications | [ServerMessage](#fishjam-ServerMessage) | repeated | | + + + + + + ### ServerMessage.PeerAdded diff --git a/fishjam/server_notifications.proto b/fishjam/server_notifications.proto index 79d81cc..6cfadd0 100644 --- a/fishjam/server_notifications.proto +++ b/fishjam/server_notifications.proto @@ -66,6 +66,10 @@ message ServerMessage { // Request sent by peer, to authenticate to FJ server message AuthRequest { string token = 1; + // If true, the server may deliver NotificationBatch in addition to + // single-notification ServerMessages. Defaults to false for websocket and + // old peers. + bool supports_notification_batch = 2; } // Defines message groups for which peer can subscribe @@ -233,6 +237,22 @@ message ServerMessage { string streamer_id = 2; } + // Carries multiple notifications in a single wire frame. + // + // Constraints (documented, not schema-enforced): + // - Each element's `content` MUST be a notification variant — never + // Authenticated, AuthRequest, SubscribeRequest, or SubscribeResponse. + // - NotificationBatch MUST NOT be nested inside another NotificationBatch. + // The schema technically permits this, but senders must not emit + // recursive batches and receivers may treat them as a protocol violation. + // - Notifications are delivered in array order; consumers must process + // them in order. + // - The batch is wire-atomic but not semantically atomic: emitting two + // batches vs. one batch of the same elements is equivalent. + // - Sent only to peers that opted in via + // AuthRequest.supports_notification_batch. + message NotificationBatch { repeated ServerMessage notifications = 1; } + reserved 12; oneof content { @@ -273,6 +293,9 @@ message ServerMessage { StreamerConnected streamer_connected = 26; StreamerDisconnected streamer_disconnected = 27; + // Batch + NotificationBatch notification_batch = 33; + // Deprecated StreamConnected stream_connected = 22 [deprecated = true]; diff --git a/fishjam_protos/lib/fishjam/server_notifications.pb.ex b/fishjam_protos/lib/fishjam/server_notifications.pb.ex index d0ad43b..6d729c4 100644 --- a/fishjam_protos/lib/fishjam/server_notifications.pb.ex +++ b/fishjam_protos/lib/fishjam/server_notifications.pb.ex @@ -147,6 +147,7 @@ defmodule Fishjam.ServerMessage.AuthRequest do syntax: :proto3 field :token, 1, type: :string + field :supports_notification_batch, 2, type: :bool, json_name: "supportsNotificationBatch" end defmodule Fishjam.ServerMessage.SubscribeRequest do @@ -443,6 +444,17 @@ defmodule Fishjam.ServerMessage.StreamerDisconnected do field :streamer_id, 2, type: :string, json_name: "streamerId" end +defmodule Fishjam.ServerMessage.NotificationBatch do + @moduledoc false + + use Protobuf, + full_name: "fishjam.ServerMessage.NotificationBatch", + protoc_gen_elixir_version: "0.16.0", + syntax: :proto3 + + field :notifications, 1, repeated: true, type: Fishjam.ServerMessage +end + defmodule Fishjam.ServerMessage do @moduledoc false @@ -572,6 +584,11 @@ defmodule Fishjam.ServerMessage do json_name: "streamerDisconnected", oneof: 0 + field :notification_batch, 33, + type: Fishjam.ServerMessage.NotificationBatch, + json_name: "notificationBatch", + oneof: 0 + field :stream_connected, 22, type: Fishjam.ServerMessage.StreamConnected, json_name: "streamConnected", From 1a0db39149530ce822d60754ea6caed1665f6306 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Ro=C5=BCnawski?= Date: Mon, 27 Apr 2026 20:47:08 +0200 Subject: [PATCH 2/7] Remove from auth request --- fishjam/server_notifications.proto | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/fishjam/server_notifications.proto b/fishjam/server_notifications.proto index 6cfadd0..624ac91 100644 --- a/fishjam/server_notifications.proto +++ b/fishjam/server_notifications.proto @@ -64,13 +64,7 @@ message ServerMessage { message Authenticated {} // Request sent by peer, to authenticate to FJ server - message AuthRequest { - string token = 1; - // If true, the server may deliver NotificationBatch in addition to - // single-notification ServerMessages. Defaults to false for websocket and - // old peers. - bool supports_notification_batch = 2; - } + message AuthRequest { string token = 1; } // Defines message groups for which peer can subscribe enum EventType { @@ -249,8 +243,7 @@ message ServerMessage { // them in order. // - The batch is wire-atomic but not semantically atomic: emitting two // batches vs. one batch of the same elements is equivalent. - // - Sent only to peers that opted in via - // AuthRequest.supports_notification_batch. + // - Sent only to peers that opted in message NotificationBatch { repeated ServerMessage notifications = 1; } reserved 12; From 3f2b8442a7e1f52143e7fe3063a6385f16dec8d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Ro=C5=BCnawski?= Date: Mon, 27 Apr 2026 20:53:35 +0200 Subject: [PATCH 3/7] Format --- fishjam/server_notifications.proto | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/fishjam/server_notifications.proto b/fishjam/server_notifications.proto index 624ac91..609d995 100644 --- a/fishjam/server_notifications.proto +++ b/fishjam/server_notifications.proto @@ -64,7 +64,9 @@ message ServerMessage { message Authenticated {} // Request sent by peer, to authenticate to FJ server - message AuthRequest { string token = 1; } + message AuthRequest { + string token = 1; + } // Defines message groups for which peer can subscribe enum EventType { @@ -244,7 +246,9 @@ message ServerMessage { // - The batch is wire-atomic but not semantically atomic: emitting two // batches vs. one batch of the same elements is equivalent. // - Sent only to peers that opted in - message NotificationBatch { repeated ServerMessage notifications = 1; } + message NotificationBatch { + repeated ServerMessage notifications = 1; + } reserved 12; From 7bf8d4a4b6732c7d498e3513c47a61ee3935a360 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Ro=C5=BCnawski?= Date: Mon, 27 Apr 2026 20:55:57 +0200 Subject: [PATCH 4/7] Update doc --- doc/docs.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/doc/docs.md b/doc/docs.md index e190805..d000931 100644 --- a/doc/docs.md +++ b/doc/docs.md @@ -1386,7 +1386,6 @@ Request sent by peer, to authenticate to FJ server | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | token | [string](#string) | | | -| supports_notification_batch | [bool](#bool) | | If true, the server may deliver NotificationBatch in addition to single-notification ServerMessages. Defaults to false for websocket and old peers. | @@ -1516,8 +1515,7 @@ Constraints (documented, not schema-enforced): them in order. - The batch is wire-atomic but not semantically atomic: emitting two batches vs. one batch of the same elements is equivalent. - - Sent only to peers that opted in via - AuthRequest.supports_notification_batch. + - Sent only to peers that opted in | Field | Type | Label | Description | From 4f713440434e1b26804f402644ea347b70cc9635 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Ro=C5=BCnawski?= Date: Mon, 27 Apr 2026 21:04:51 +0200 Subject: [PATCH 5/7] Add prepare.sh --- fishjam_protos/lib/fishjam/server_notifications.pb.ex | 1 - prepare.sh | 8 ++++++++ 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100755 prepare.sh diff --git a/fishjam_protos/lib/fishjam/server_notifications.pb.ex b/fishjam_protos/lib/fishjam/server_notifications.pb.ex index 6d729c4..60f3d9e 100644 --- a/fishjam_protos/lib/fishjam/server_notifications.pb.ex +++ b/fishjam_protos/lib/fishjam/server_notifications.pb.ex @@ -147,7 +147,6 @@ defmodule Fishjam.ServerMessage.AuthRequest do syntax: :proto3 field :token, 1, type: :string - field :supports_notification_batch, 2, type: :bool, json_name: "supportsNotificationBatch" end defmodule Fishjam.ServerMessage.SubscribeRequest do diff --git a/prepare.sh b/prepare.sh new file mode 100755 index 0000000..23e3f57 --- /dev/null +++ b/prepare.sh @@ -0,0 +1,8 @@ +set -e + +find fishjam -name "*.proto" | sort | xargs docker run --rm -v $(pwd)/doc:/out -v $(pwd):/protos pseudomuto/protoc-gen-doc --doc_opt=markdown,docs.md + +buf lint +buf format -w + +(cd ./fishjam_protos; ./compile_proto.sh) From 7e2c1df6e7637cf1325c2522f45de099f233ab72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Ro=C5=BCnawski?= Date: Mon, 27 Apr 2026 21:09:47 +0200 Subject: [PATCH 6/7] Update doc --- doc/docs.md | 4 +--- fishjam/server_notifications.proto | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/doc/docs.md b/doc/docs.md index d000931..aa96906 100644 --- a/doc/docs.md +++ b/doc/docs.md @@ -1513,9 +1513,7 @@ Constraints (documented, not schema-enforced): recursive batches and receivers may treat them as a protocol violation. - Notifications are delivered in array order; consumers must process them in order. - - The batch is wire-atomic but not semantically atomic: emitting two - batches vs. one batch of the same elements is equivalent. - - Sent only to peers that opted in + - Sent only for webhooks, for peers that opted in | Field | Type | Label | Description | diff --git a/fishjam/server_notifications.proto b/fishjam/server_notifications.proto index 609d995..882569e 100644 --- a/fishjam/server_notifications.proto +++ b/fishjam/server_notifications.proto @@ -243,9 +243,7 @@ message ServerMessage { // recursive batches and receivers may treat them as a protocol violation. // - Notifications are delivered in array order; consumers must process // them in order. - // - The batch is wire-atomic but not semantically atomic: emitting two - // batches vs. one batch of the same elements is equivalent. - // - Sent only to peers that opted in + // - Sent only for webhooks, for peers that opted in message NotificationBatch { repeated ServerMessage notifications = 1; } From f5b019436f201536e929ea719c595fae6c44a3af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Ro=C5=BCnawski?= Date: Mon, 27 Apr 2026 22:05:20 +0200 Subject: [PATCH 7/7] Improve script --- doc/docs.md | 2 +- fishjam/server_notifications.proto | 2 +- prepare.sh | 6 ++++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/doc/docs.md b/doc/docs.md index aa96906..4da81d7 100644 --- a/doc/docs.md +++ b/doc/docs.md @@ -1513,7 +1513,7 @@ Constraints (documented, not schema-enforced): recursive batches and receivers may treat them as a protocol violation. - Notifications are delivered in array order; consumers must process them in order. - - Sent only for webhooks, for peers that opted in + - Sent only for webhooks, for peers that . | Field | Type | Label | Description | diff --git a/fishjam/server_notifications.proto b/fishjam/server_notifications.proto index 882569e..80a7948 100644 --- a/fishjam/server_notifications.proto +++ b/fishjam/server_notifications.proto @@ -243,7 +243,7 @@ message ServerMessage { // recursive batches and receivers may treat them as a protocol violation. // - Notifications are delivered in array order; consumers must process // them in order. - // - Sent only for webhooks, for peers that opted in + // - Sent only for webhooks, for peers that . message NotificationBatch { repeated ServerMessage notifications = 1; } diff --git a/prepare.sh b/prepare.sh index 23e3f57..b61bc7d 100755 --- a/prepare.sh +++ b/prepare.sh @@ -1,8 +1,10 @@ +#!/bin/bash + set -e -find fishjam -name "*.proto" | sort | xargs docker run --rm -v $(pwd)/doc:/out -v $(pwd):/protos pseudomuto/protoc-gen-doc --doc_opt=markdown,docs.md +find fishjam -name "*.proto" | sort | xargs docker run --rm -v $PWD/doc:/out -v $PWD:/protos pseudomuto/protoc-gen-doc --doc_opt=markdown,docs.md -buf lint buf format -w +buf lint (cd ./fishjam_protos; ./compile_proto.sh)