Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft: Test that /messages works on remote homeserver and can be backfilled properly after many batches (MSC2716) #214

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
8099f47
Test that /messages can be backfilled properly after many batches
MadLittleMods Oct 19, 2021
094c5f7
Add message suffix to better distinguish messages
MadLittleMods Oct 21, 2021
e30bcd4
v4 room version
MadLittleMods Oct 30, 2021
1e333d6
Make sure marker event is sent
MadLittleMods Nov 3, 2021
2022b31
Cleanup tests
MadLittleMods Nov 3, 2021
d325349
Some test cleanup and comments
MadLittleMods Nov 3, 2021
2fe5180
Delays not needed for test servers (get result ASAP)
MadLittleMods Nov 11, 2021
0604564
Fix typo
MadLittleMods Nov 11, 2021
83adbe2
Merge branch 'master' into madlittlemods/test-backfill-and-messages-s…
MadLittleMods Nov 11, 2021
4aba836
Fix missing params after merge
MadLittleMods Nov 11, 2021
ffbca43
Make sure historical state doesn't appear between batches
MadLittleMods Dec 2, 2021
37109fa
Re-use JSONArrayEach
MadLittleMods Dec 2, 2021
cc7236b
Merge branch 'master' into madlittlemods/test-backfill-and-messages-s…
MadLittleMods Dec 17, 2021
4c8284a
v4 was never merged
MadLittleMods Dec 17, 2021
9b90429
Merge branch 'master' into madlittlemods/test-backfill-and-messages-s…
MadLittleMods Dec 17, 2021
677836b
Merge branch 'master' into madlittlemods/test-backfill-and-messages-s…
MadLittleMods Jan 13, 2022
85eb7bd
Merge branch 'main' into madlittlemods/test-backfill-and-messages-sti…
MadLittleMods Mar 30, 2022
3532821
Merge branch 'main' into madlittlemods/test-backfill-and-messages-sti…
MadLittleMods May 13, 2022
1667e15
Merge branch 'main' into madlittlemods/test-backfill-and-messages-sti…
MadLittleMods Aug 10, 2022
0589546
Merge branch 'main' into madlittlemods/test-backfill-and-messages-sti…
MadLittleMods Sep 20, 2022
606197a
Update test name
MadLittleMods Sep 21, 2022
d679384
Changes and debugging
MadLittleMods Sep 29, 2022
230c46e
Mulitply timeout by the number of requests we expect
MadLittleMods Sep 29, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion internal/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,7 @@ func NewLoggedClient(t *testing.T, hsName string, cli *http.Client) *http.Client
t.Helper()
if cli == nil {
cli = &http.Client{
Timeout: 30 * time.Second,
Timeout: 200 * time.Second,
}
}
transport := cli.Transport
Expand Down
88 changes: 83 additions & 5 deletions tests/msc2716_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1026,6 +1026,75 @@ func TestImportHistoricalMessages(t *testing.T) {
2,
)
})

t.Run("Backfill still works after many contiguous batches are imported", func(t *testing.T) {
t.Parallel()

roomID := as.CreateRoom(t, createPublicRoomOpts)
alice.JoinRoom(t, roomID, nil)

// Create some normal messages in the timeline
eventIDsBefore := createMessagesInRoom(t, alice, roomID, 2, "eventIDsBefore")
eventIdBefore := eventIDsBefore[len(eventIDsBefore)-1]
timeAfterEventBefore := time.Now()

// We chose the magic number 11 because Synapse currently limits the
// backfill extremities to 5. 10 also seemed like a round number someone
// could pick for other homeserver implementations so I just did 10+1 to
// make sure it also worked in that case.
numBatches := 11
numHistoricalMessagesPerBatch := 100
// wait X number of ms to ensure that the timestamp changes enough for
// each of the historical messages we try to import later
time.Sleep(time.Duration(numBatches*numHistoricalMessagesPerBatch) * timeBetweenMessages)

// eventIDsAfter
createMessagesInRoom(t, alice, roomID, 2, "eventIDsAfter")

// Import a long chain of batches connected to each other.
// We want to make sure Synapse doesn't blow up after we import
// many messages.
var expectedEventIDs []string
var denyListEventIDs []string
var baseInsertionEventID string
nextBatchID := ""
for i := 0; i < numBatches; i++ {
insertTime := timeAfterEventBefore.Add(timeBetweenMessages * time.Duration(numBatches-numHistoricalMessagesPerBatch*i))
batchSendRes := batchSendHistoricalMessages(
t,
as,
roomID,
eventIdBefore,
nextBatchID,
createJoinStateEventsForBatchSendRequest([]string{virtualUserID}, insertTime),
createMessageEventsForBatchSendRequest([]string{virtualUserID}, insertTime, numHistoricalMessagesPerBatch),
// Status
200,
)
batchSendResBody := client.ParseJSON(t, batchSendRes)
// Make sure we see all of the historical messages
expectedEventIDs = append(expectedEventIDs, client.GetJSONFieldStringArray(t, batchSendResBody, "event_ids")...)
// We should not find any historical state between the batches of messages
nextBatchID = client.GetJSONFieldStr(t, batchSendResBody, "next_batch_id")

// Grab the base insertion event ID to reference later in the marker event
if i == 0 {
baseInsertionEventID = client.GetJSONFieldStr(t, batchSendResBody, "base_insertion_event_id")
}
}

// Make sure we see the events at the very start of the message history
expectedEventIDs = append(expectedEventIDs, eventIDsBefore...)

// Join the room from a remote homeserver after the historical messages were sent
remoteCharlie.JoinRoom(t, roomID, []string{"hs1"})

// Send the marker event
sendMarkerAndEnsureBackfilled(t, as, remoteCharlie, roomID, baseInsertionEventID)

// Make sure events can be backfilled from the remote homeserver
paginateUntilMessageCheckOff(t, remoteCharlie, roomID, "", expectedEventIDs, denyListEventIDs)
})
})

t.Run("Existing room versions", func(t *testing.T) {
Expand Down Expand Up @@ -1167,10 +1236,10 @@ func includes(needle string, haystack []string) bool {
func fetchUntilMessagesResponseHas(t *testing.T, c *client.CSAPI, roomID string, check func(gjson.Result) bool) {
t.Helper()
start := time.Now()
checkCounter := 0
callCounter := 0
for {
if time.Since(start) > c.SyncUntilTimeout {
t.Fatalf("fetchUntilMessagesResponseHas timed out. Called check function %d times", checkCounter)
t.Fatalf("fetchUntilMessagesResponseHas timed out. Called check function %d times", callCounter)
}

messagesRes := c.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, client.WithContentType("application/json"), client.WithQueries(url.Values{
Expand All @@ -1194,7 +1263,7 @@ func fetchUntilMessagesResponseHas(t *testing.T, c *client.CSAPI, roomID string,
}
}

checkCounter++
callCounter++
// Add a slight delay so we don't hammmer the messages endpoint
time.Sleep(500 * time.Millisecond)
}
Expand Down Expand Up @@ -1239,8 +1308,12 @@ func paginateUntilMessageCheckOff(t *testing.T, c *client.CSAPI, roomID string,
)
}

// We grab 100 events per `/messages` request so it should only take us
// (total / 100) requests to see everything. Add +1 to add some slack
// for things like state events.
expectedNumberOfMessagesRequests := (len(expectedEventIDs) / 100) + 1
for {
if time.Since(start) > c.SyncUntilTimeout {
if time.Since(start) > time.Duration(expectedNumberOfMessagesRequests)*c.SyncUntilTimeout {
t.Fatalf(
"paginateUntilMessageCheckOff timed out. %s",
generateErrorMesssageInfo(),
Expand All @@ -1254,7 +1327,6 @@ func paginateUntilMessageCheckOff(t *testing.T, c *client.CSAPI, roomID string,
}))
callCounter++
messsageResBody := client.ParseJSON(t, messagesRes)
messageResEnd = client.GetJSONFieldStr(t, messsageResBody, "end")
// Since the original body can only be read once, create a new one from the body bytes we just read
messagesRes.Body = ioutil.NopCloser(bytes.NewBuffer(messsageResBody))

Expand Down Expand Up @@ -1294,6 +1366,12 @@ func paginateUntilMessageCheckOff(t *testing.T, c *client.CSAPI, roomID string,
if len(workingExpectedEventIDMap) == 0 {
return
}

// Since this will throw an error if they key does not exist,
// do this at the end of the loop. It's a valid scenario to be at the end
// of the room and have no more to paginate so we want the `return` when
// we've found all of the expected events to have a chance to run first.
messageResEnd = client.GetJSONFieldStr(t, messsageResBody, "end")
Comment on lines +1370 to +1374
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Split out to #489

}
}

Expand Down