MM-54238 Add WebSocket broadcast hook and don't broadcast when other users were mentioned (#24641)
* MM-54238 Initial implementation * MM-54238 Move websocket hook into app package * MM-54238 Add tests for mentions in posted websocket messages * Fix styling * Fix other styling * Idiomatic ID naming for new code * Fix more styles * Separate hooks to add mentions and followers * Improved error handling for invalid types in hooks * Rename HasChanges to ShouldProcess * Pass broadcast hooks through hubStart * Add test helper for asserting json unmarshaling * Fix missing arguments in tests * Ensure broadcast hooks are sent across the cluster and not to users * Ensure tests actually cover following a post * Fix code broken by merge * Go vet again... * Deep copy event before processing it with hooks * Replace RemoveBroadcastHooks with WithoutBroadcastHooks * Address feedback * Add helper to fix type information for hook args * Wrap WebSocketEvent and simplify BroadcastHook * Address feedback * Address feedback
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
5e62ba8ccc
Коммит
ef66f7beab
@@ -4,6 +4,7 @@
|
||||
package platform
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"net"
|
||||
"net/http"
|
||||
@@ -69,7 +70,7 @@ func TestHubStopWithMultipleConnections(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
th.Service.Start()
|
||||
th.Service.Start(nil)
|
||||
wc1 := registerDummyWebConn(t, th, s.Listener.Addr(), session)
|
||||
wc2 := registerDummyWebConn(t, th, s.Listener.Addr(), session)
|
||||
wc3 := registerDummyWebConn(t, th, s.Listener.Addr(), session)
|
||||
@@ -93,7 +94,7 @@ func TestHubStopRaceCondition(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
th.Service.Start()
|
||||
th.Service.Start(nil)
|
||||
wc1 := registerDummyWebConn(t, th, s.Listener.Addr(), session)
|
||||
defer wc1.Close()
|
||||
|
||||
@@ -476,7 +477,7 @@ func TestHubIsRegistered(t *testing.T) {
|
||||
s := httptest.NewServer(dummyWebsocketHandler(t))
|
||||
defer s.Close()
|
||||
|
||||
th.Service.Start()
|
||||
th.Service.Start(nil)
|
||||
wc1 := registerDummyWebConn(t, th, s.Listener.Addr(), session)
|
||||
wc2 := registerDummyWebConn(t, th, s.Listener.Addr(), session)
|
||||
wc3 := registerDummyWebConn(t, th, s.Listener.Addr(), session)
|
||||
@@ -583,7 +584,7 @@ func BenchmarkGetHubForUserId(b *testing.B) {
|
||||
th := Setup(b).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
th.Service.Start()
|
||||
th.Service.Start(nil)
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
@@ -618,3 +619,54 @@ func TestClusterBroadcast(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, clusterEvent.Broadcast, broadcast)
|
||||
}
|
||||
|
||||
func TestClusterBroadcastHooks(t *testing.T) {
|
||||
t.Run("should send broadcast hook information across cluster", func(t *testing.T) {
|
||||
testCluster := &testlib.FakeClusterInterface{}
|
||||
|
||||
th := SetupWithCluster(t, testCluster)
|
||||
defer th.TearDown()
|
||||
|
||||
hookID := broadcastTest
|
||||
hookArgs := map[string]any{
|
||||
"makes_changes": true,
|
||||
}
|
||||
|
||||
event := model.NewWebSocketEvent(model.WebsocketEventPosted, "", "", "", nil, "")
|
||||
event.GetBroadcast().AddHook(hookID, hookArgs)
|
||||
|
||||
th.Service.Publish(event)
|
||||
|
||||
received, err := model.WebSocketEventFromJSON(bytes.NewReader(testCluster.GetMessages()[0].Data))
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, []string{hookID}, received.GetBroadcast().BroadcastHooks)
|
||||
assert.Equal(t, []map[string]any{hookArgs}, received.GetBroadcast().BroadcastHookArgs)
|
||||
})
|
||||
|
||||
t.Run("should not preserve type information for args", func(t *testing.T) {
|
||||
// This behaviour isn't ideal, but this test confirms that it hasn't changed
|
||||
testCluster := &testlib.FakeClusterInterface{}
|
||||
|
||||
th := SetupWithCluster(t, testCluster)
|
||||
defer th.TearDown()
|
||||
|
||||
hookID := "test_broadcast_hook_with_args"
|
||||
hookArgs := map[string]any{
|
||||
"user": &model.User{Id: "user1"},
|
||||
"array": []string{"a", "b", "c"},
|
||||
}
|
||||
|
||||
event := model.NewWebSocketEvent(model.WebsocketEventPosted, "", "", "", nil, "")
|
||||
event.GetBroadcast().AddHook(hookID, hookArgs)
|
||||
|
||||
th.Service.Publish(event)
|
||||
|
||||
received, err := model.WebSocketEventFromJSON(bytes.NewReader(testCluster.GetMessages()[0].Data))
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, []string{hookID}, received.GetBroadcast().BroadcastHooks)
|
||||
assert.IsType(t, map[string]any{}, received.GetBroadcast().BroadcastHookArgs[0]["user"])
|
||||
assert.IsType(t, []any{}, received.GetBroadcast().BroadcastHookArgs[0]["array"])
|
||||
})
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user