Skip to content

Commit

Permalink
Recovers inactive websockets connections on reconnect in plugin mode (#…
Browse files Browse the repository at this point in the history
…1324)

* Stores a cache of inactive connections so their subscriptions are recovered on reconnections

* Adds test for getUserIDsForWorkspace and simplify messages through helpers

* Make the plugin websocket client more resilient

* Remove missed event callback and limit ws state polling to one at a time

* Add read lock for the plugin adapter and guarantee atomic ops on inactiveAt

* Add mutex to the plugin adapter client and tests to cover for races

* Split plugin adapter mutex in two and use them to lock only on data access

* Group plugin adapter fields by the mutex that's guarding them
  • Loading branch information
mgdelacroix authored Sep 29, 2021
1 parent 7970d4e commit ce98ec5
Show file tree
Hide file tree
Showing 9 changed files with 3,217 additions and 90 deletions.
7 changes: 7 additions & 0 deletions server/auth/auth.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:generate mockgen --build_flags=--mod=mod -destination=mocks/mockauth_interface.go -package mocks . AuthInterface
package auth

import (
Expand All @@ -10,6 +11,12 @@ import (
"github.com/pkg/errors"
)

type AuthInterface interface {
GetSession(token string) (*model.Session, error)
IsValidReadToken(c store.Container, blockID string, readToken string) (bool, error)
DoesUserHaveWorkspaceAccess(userID string, workspaceID string) bool
}

// Auth authenticates sessions.
type Auth struct {
config *config.Configuration
Expand Down
80 changes: 80 additions & 0 deletions server/auth/mocks/mockauth_interface.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

57 changes: 57 additions & 0 deletions server/ws/helpers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package ws

import (
"testing"

authMocks "github.com/mattermost/focalboard/server/auth/mocks"
wsMocks "github.com/mattermost/focalboard/server/ws/mocks"

mmModel "github.com/mattermost/mattermost-server/v6/model"

"github.com/golang/mock/gomock"
)

type TestHelper struct {
api *wsMocks.MockAPI
auth *authMocks.MockAuthInterface
ctrl *gomock.Controller
pa *PluginAdapter
}

func SetupTestHelper(t *testing.T) *TestHelper {
ctrl := gomock.NewController(t)
mockAPI := wsMocks.NewMockAPI(ctrl)
mockAuth := authMocks.NewMockAuthInterface(ctrl)

mockAPI.EXPECT().LogDebug(gomock.Any(), gomock.Any()).AnyTimes()
mockAPI.EXPECT().LogInfo(gomock.Any(), gomock.Any()).AnyTimes()
mockAPI.EXPECT().LogError(gomock.Any(), gomock.Any()).AnyTimes()
mockAPI.EXPECT().LogWarn(gomock.Any(), gomock.Any()).AnyTimes()

return &TestHelper{
api: mockAPI,
auth: mockAuth,
ctrl: ctrl,
pa: NewPluginAdapter(mockAPI, mockAuth),
}
}

func (th *TestHelper) ReceiveWebSocketMessage(webConnID, userID, action string, data map[string]interface{}) {
req := &mmModel.WebSocketRequest{Action: websocketMessagePrefix + action, Data: data}

th.pa.WebSocketMessageHasBeenPosted(webConnID, userID, req)
}

func (th *TestHelper) SubscribeWebConnToWorkspace(webConnID, userID, workspaceID string) {
th.auth.EXPECT().
DoesUserHaveWorkspaceAccess(userID, workspaceID).
Return(true)

msgData := map[string]interface{}{"workspaceId": workspaceID}
th.ReceiveWebSocketMessage(webConnID, userID, websocketActionSubscribeWorkspace, msgData)
}

func (th *TestHelper) UnsubscribeWebConnFromWorkspace(webConnID, userID, workspaceID string) {
msgData := map[string]interface{}{"workspaceId": workspaceID}
th.ReceiveWebSocketMessage(webConnID, userID, websocketActionUnsubscribeWorkspace, msgData)
}
Loading

0 comments on commit ce98ec5

Please sign in to comment.