MM-61130: Use a channelMember map at web_hub level (#28810)

Tests at very high scale indicates that the iteration
of all connections during websocket broadcast starts
to become a bottleneck.

To optimize this, we move the channelMember cache from
inside web_conn.go to the hubConnectionIndex.

This involves adding a new map keyed by the channelID
and containing all webConns where the user is a member
of that channel. Subsequently, a new method needed to
be added to invalidate the cache which previously
used to happen in web_conn.

And as a last step, we remove the cache from web_conn
to reduce SQL queries to the DB.

https://mattermost.atlassian.net/browse/MM-61130

```release-note
NONE
```
Этот коммит содержится в:
Agniva De Sarker
2024-11-08 09:57:54 +05:30
коммит произвёл GitHub
родитель 37d97e8024
Коммит bd8774bdce
11 изменённых файлов: 564 добавлений и 329 удалений

Просмотреть файл

@@ -15,6 +15,9 @@ import (
"github.com/mattermost/mattermost/server/v8/channels/app/platform"
)
// TestWebConnShouldSendEvent is not exhaustive because some of the checks
// happen inside web_hub.go before the event is actually broadcasted, and checked
// via ShouldSendEvent.
func TestWebConnShouldSendEvent(t *testing.T) {
os.Setenv("MM_FEATUREFLAGS_WEBSOCKETEVENTSCOPE", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_WEBSOCKETEVENTSCOPE")
@@ -157,14 +160,6 @@ func TestWebConnShouldSendEvent(t *testing.T) {
})
}
t.Run("should send to basic user in basic channel", func(t *testing.T) {
event = event.SetBroadcast(&model.WebsocketBroadcast{ChannelId: th.BasicChannel.Id})
assert.True(t, basicUserWc.ShouldSendEvent(event), "expected user 1")
assert.False(t, basicUser2Wc.ShouldSendEvent(event), "did not expect user 2")
assert.False(t, adminUserWc.ShouldSendEvent(event), "did not expect admin")
})
t.Run("should not send typing event unless in scope", func(t *testing.T) {
event2 := model.NewWebSocketEvent(model.WebsocketEventTyping, "", th.BasicChannel.Id, "", nil, "")
// Basic, unset case
@@ -222,14 +217,6 @@ func TestWebConnShouldSendEvent(t *testing.T) {
assert.False(t, basicUserWc.ShouldSendEvent(event2))
})
t.Run("should send to basic user and admin in channel2", func(t *testing.T) {
event = event.SetBroadcast(&model.WebsocketBroadcast{ChannelId: channel2.Id})
assert.True(t, basicUserWc.ShouldSendEvent(event), "expected user 1")
assert.False(t, basicUser2Wc.ShouldSendEvent(event), "did not expect user 2")
assert.True(t, adminUserWc.ShouldSendEvent(event), "expected admin")
})
t.Run("channel member cache invalidated after user added to channel", func(t *testing.T) {
th.AddUserToChannel(th.BasicUser2, channel2)
basicUser2Wc.InvalidateCache()