perf(group): reduce websocket fanout serialization
This commit is contained in:
@@ -4334,3 +4334,75 @@ func TestMain(m *testing.M) {
|
||||
globals.maxSubscriberCount = 1_000_000_000
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestGroupBroadcastReusesSerializedWebSocketPayload(t *testing.T) {
|
||||
uid1, uid2, uid3 := types.Uid(1), types.Uid(2), types.Uid(3)
|
||||
sess1 := &Session{sid: "ws-1", proto: WEBSOCK, send: make(chan any, 2)}
|
||||
sess2 := &Session{sid: "ws-2", proto: WEBSOCK, send: make(chan any, 2)}
|
||||
sessNoRead := &Session{sid: "ws-no-read", proto: WEBSOCK, send: make(chan any, 2)}
|
||||
topic := &Topic{
|
||||
tenantID: 1,
|
||||
name: "grpShared",
|
||||
xoriginal: "grpShared",
|
||||
cat: types.TopicCatGrp,
|
||||
sessions: map[*Session]perSessionData{
|
||||
sess1: {uid: uid1},
|
||||
sess2: {uid: uid2},
|
||||
sessNoRead: {uid: uid3},
|
||||
},
|
||||
perUser: map[types.Uid]perUserData{
|
||||
uid1: {modeWant: types.ModeCFull, modeGiven: types.ModeCFull},
|
||||
uid2: {modeWant: types.ModeCFull, modeGiven: types.ModeCFull},
|
||||
uid3: {modeWant: types.ModeNone, modeGiven: types.ModeNone},
|
||||
},
|
||||
}
|
||||
msg := &ServerComMessage{Data: &MsgServerData{
|
||||
Topic: "grpShared", From: uid1.UserId(), SeqId: 42, Timestamp: time.Now(), Content: "hello",
|
||||
}}
|
||||
|
||||
topic.broadcastToSessions(msg)
|
||||
|
||||
payload1, ok := (<-sess1.send).(sharedServerMessage)
|
||||
if !ok {
|
||||
t.Fatal("first WebSocket did not receive a serialized payload")
|
||||
}
|
||||
payload2, ok := (<-sess2.send).(sharedServerMessage)
|
||||
if !ok {
|
||||
t.Fatal("second WebSocket did not receive a serialized payload")
|
||||
}
|
||||
if len(payload1) == 0 || len(payload2) == 0 || &payload1[0] != &payload2[0] {
|
||||
t.Fatal("group WebSocket recipients did not reuse the same serialized payload")
|
||||
}
|
||||
var decoded ServerComMessage
|
||||
if err := json.Unmarshal(payload1, &decoded); err != nil {
|
||||
t.Fatalf("invalid shared payload: %v", err)
|
||||
}
|
||||
if decoded.Data == nil || decoded.Data.Topic != "grpShared" || decoded.Data.SeqId != 42 || decoded.Data.Content != "hello" {
|
||||
t.Fatalf("unexpected shared payload: %#v", decoded.Data)
|
||||
}
|
||||
if len(sessNoRead.send) != 0 {
|
||||
t.Fatal("non-reader received a group broadcast")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSharedBroadcastEligibility(t *testing.T) {
|
||||
sess := &Session{proto: WEBSOCK}
|
||||
msg := &ServerComMessage{Data: &MsgServerData{Topic: "grpShared"}}
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
topic Topic
|
||||
pssd perSessionData
|
||||
want bool
|
||||
}{
|
||||
{name: "ordinary group", topic: Topic{cat: types.TopicCatGrp}, want: true},
|
||||
{name: "channel", topic: Topic{cat: types.TopicCatGrp, isChan: true}},
|
||||
{name: "channel subscription", topic: Topic{cat: types.TopicCatGrp}, pssd: perSessionData{isChanSub: true}},
|
||||
{name: "p2p", topic: Topic{cat: types.TopicCatP2P}},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
if got := tc.topic.canShareSerializedBroadcast(msg, sess, tc.pssd); got != tc.want {
|
||||
t.Fatalf("eligibility=%v want=%v", got, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user