2023-06-19 15:56:22 +01:00
|
|
|
package syncv3
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"sync"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
syncv3 "github.com/matrix-org/sliding-sync"
|
|
|
|
"github.com/matrix-org/sliding-sync/sync2"
|
|
|
|
"github.com/matrix-org/sliding-sync/sync3"
|
|
|
|
"github.com/matrix-org/sliding-sync/testutils"
|
|
|
|
"github.com/matrix-org/sliding-sync/testutils/m"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Test that the proxy works fine with low max conns. Low max conns can be a problem
|
|
|
|
// if a request A needs 2 conns to respond and that blocks forward progress on the server,
|
|
|
|
// and the request can only obtain 1 conn.
|
|
|
|
func TestMaxDBConns(t *testing.T) {
|
|
|
|
pqString := testutils.PrepareDBConnectionString()
|
|
|
|
// setup code
|
|
|
|
v2 := runTestV2Server(t)
|
2023-06-19 17:36:41 +01:00
|
|
|
opts := syncv3.Opts{
|
2023-06-19 17:52:10 +01:00
|
|
|
DBMaxConns: 1,
|
2023-06-19 17:36:41 +01:00
|
|
|
}
|
|
|
|
v3 := runTestServer(t, v2, pqString, opts)
|
2023-06-19 15:56:22 +01:00
|
|
|
defer v2.close()
|
|
|
|
defer v3.close()
|
|
|
|
|
2023-06-19 17:36:41 +01:00
|
|
|
testMaxDBConns := func() {
|
|
|
|
// make N users and drip feed some events, make sure they are all seen
|
|
|
|
numUsers := 5
|
|
|
|
var wg sync.WaitGroup
|
|
|
|
wg.Add(numUsers)
|
|
|
|
for i := 0; i < numUsers; i++ {
|
|
|
|
go func(n int) {
|
|
|
|
defer wg.Done()
|
|
|
|
userID := fmt.Sprintf("@maxconns_%d:localhost", n)
|
|
|
|
token := fmt.Sprintf("maxconns_%d", n)
|
|
|
|
roomID := fmt.Sprintf("!maxconns_%d", n)
|
|
|
|
v2.addAccount(t, userID, token)
|
2023-08-11 16:42:15 +01:00
|
|
|
state := createRoomState(t, userID, time.Now())
|
2023-06-19 17:36:41 +01:00
|
|
|
v2.queueResponse(userID, sync2.SyncResponse{
|
|
|
|
Rooms: sync2.SyncRoomsResponse{
|
|
|
|
Join: v2JoinTimeline(roomEvents{
|
|
|
|
roomID: roomID,
|
2023-08-11 16:42:15 +01:00
|
|
|
state: state[:len(state)-1],
|
|
|
|
events: []json.RawMessage{
|
|
|
|
state[len(state)-1],
|
|
|
|
},
|
2023-06-19 17:36:41 +01:00
|
|
|
}),
|
2023-06-19 15:56:22 +01:00
|
|
|
},
|
2023-06-19 17:36:41 +01:00
|
|
|
})
|
|
|
|
// initial sync
|
|
|
|
res := v3.mustDoV3Request(t, token, sync3.Request{
|
|
|
|
Lists: map[string]sync3.RequestList{"a": {
|
|
|
|
Ranges: sync3.SliceRanges{
|
|
|
|
[2]int64{0, 1},
|
2023-06-19 15:56:22 +01:00
|
|
|
},
|
2023-06-19 17:36:41 +01:00
|
|
|
RoomSubscription: sync3.RoomSubscription{
|
|
|
|
TimelineLimit: 1,
|
|
|
|
},
|
|
|
|
}},
|
|
|
|
})
|
|
|
|
t.Logf("user %s has done an initial /sync OK", userID)
|
|
|
|
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(1), m.MatchV3Ops(
|
|
|
|
m.MatchV3SyncOp(0, 0, []string{roomID}),
|
|
|
|
)), m.MatchRoomSubscriptionsStrict(map[string][]m.RoomMatcher{
|
|
|
|
roomID: {
|
|
|
|
m.MatchJoinCount(1),
|
|
|
|
},
|
|
|
|
}))
|
|
|
|
// drip feed and get update
|
|
|
|
dripMsg := testutils.NewEvent(t, "m.room.message", userID, map[string]interface{}{
|
|
|
|
"msgtype": "m.text",
|
|
|
|
"body": "drip drip",
|
|
|
|
})
|
|
|
|
v2.queueResponse(userID, sync2.SyncResponse{
|
|
|
|
Rooms: sync2.SyncRoomsResponse{
|
|
|
|
Join: v2JoinTimeline(roomEvents{
|
|
|
|
roomID: roomID,
|
|
|
|
events: []json.RawMessage{
|
|
|
|
dripMsg,
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
})
|
|
|
|
t.Logf("user %s has queued the drip", userID)
|
|
|
|
v2.waitUntilEmpty(t, userID)
|
|
|
|
t.Logf("user %s poller has received the drip", userID)
|
|
|
|
res = v3.mustDoV3RequestWithPos(t, token, res.Pos, sync3.Request{})
|
|
|
|
m.MatchResponse(t, res, m.MatchRoomSubscriptionsStrict(map[string][]m.RoomMatcher{
|
|
|
|
roomID: {
|
|
|
|
m.MatchRoomTimelineMostRecent(1, []json.RawMessage{dripMsg}),
|
|
|
|
},
|
|
|
|
}))
|
|
|
|
t.Logf("user %s has received the drip", userID)
|
|
|
|
}(i)
|
|
|
|
}
|
|
|
|
wg.Wait()
|
2023-06-19 15:56:22 +01:00
|
|
|
}
|
|
|
|
|
2023-06-19 17:36:41 +01:00
|
|
|
testMaxDBConns()
|
|
|
|
v3.restart(t, v2, pqString, opts)
|
|
|
|
testMaxDBConns()
|
2023-06-19 15:56:22 +01:00
|
|
|
}
|