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

Add a test to verify that the user directory is properly updated after a lazy load join finishes syncing #587

Merged
merged 5 commits into from
Jan 23, 2023

Conversation

H-Shay
Copy link
Contributor

@H-Shay H-Shay commented Jan 18, 2023

As the title states.

@H-Shay H-Shay requested review from a team as code owners January 18, 2023 22:37
@H-Shay H-Shay marked this pull request as draft January 18, 2023 22:37
// the rooms stats are updated by a background job in Synapse which is not guaranteed to have completed by the time
// the state sync has completed. We check for up to 3 seconds that the job has completed, after which Charlie
// the job should have finished and Charlie and Derek should be visible in the user directory
time.Sleep(time.Second * 3)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

In the interest of expediency I stuck a sleep here. I attempted on lines 3363-3374 (I commented out the attempt in case it's helpful to see) to use client.WithRetryUntil to loop until the condition was met, but I could not figure out how to make that function work with a request body, which is necessary for this API (I think?). It worked for the first iteration but then complained about an empty body for the next iteration, my best guess is that the request body is being consumed on the first attempt? I tried a few different formulations to feed the request body in but failed, any insight here would be appreciated.

Copy link
Contributor

Choose a reason for hiding this comment

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

the request body is being consumed on the first attempt

That looks like what is happening. req.Body is set to an io.Reader containing the JSON. At the end of the first request, the read position lies at the end of the JSON, and so the retry reads 0 bytes.

There's a GetBody field that can be set on http.Request. If we modify WithRawBody, we can get the retries to work:

diff --git a/internal/client/client.go b/internal/client/client.go
index 7ffacff..05dc056 100644
--- a/internal/client/client.go
+++ b/internal/client/client.go
@@ -522,6 +522,10 @@ func (c *CSAPI) GetDefaultRoomVersion(t *testing.T) gomatrixserverlib.RoomVersio
 // WithRawBody sets the HTTP request body to `body`
 func WithRawBody(body []byte) RequestOpt {
        return func(req *http.Request) {
-               req.Body = ioutil.NopCloser(bytes.NewBuffer(body))
+               req.Body = ioutil.NopCloser(bytes.NewReader(body))
+               req.GetBody = func() (io.ReadCloser, error) {
+                       r := bytes.NewReader(body)
+                       return ioutil.NopCloser(r), nil
+               }
                // we need to manually set this because we don't set the body
                // in http.NewRequest due to using functional options, and only in NewRequest
                // does the stdlib set this for us.

We replace NewBuffer with NewReader, because the docs say

NewBuffer creates and initializes a new Buffer using buf as its initial contents. The new Buffer takes ownership of buf, and the caller should not use buf after this call.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I put this change in this PR, let me know if it should be in a separate PR instead.

@H-Shay
Copy link
Contributor Author

H-Shay commented Jan 19, 2023

Related: matrix-org/synapse#12815

@H-Shay H-Shay marked this pull request as ready for review January 19, 2023 02:18
// the rooms stats are updated by a background job in Synapse which is not guaranteed to have completed by the time
// the state sync has completed. We check for up to 3 seconds that the job has completed, after which Charlie
// the job should have finished and Charlie and Derek should be visible in the user directory
time.Sleep(time.Second * 3)
Copy link
Contributor

Choose a reason for hiding this comment

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

the request body is being consumed on the first attempt

That looks like what is happening. req.Body is set to an io.Reader containing the JSON. At the end of the first request, the read position lies at the end of the JSON, and so the retry reads 0 bytes.

There's a GetBody field that can be set on http.Request. If we modify WithRawBody, we can get the retries to work:

diff --git a/internal/client/client.go b/internal/client/client.go
index 7ffacff..05dc056 100644
--- a/internal/client/client.go
+++ b/internal/client/client.go
@@ -522,6 +522,10 @@ func (c *CSAPI) GetDefaultRoomVersion(t *testing.T) gomatrixserverlib.RoomVersio
 // WithRawBody sets the HTTP request body to `body`
 func WithRawBody(body []byte) RequestOpt {
        return func(req *http.Request) {
-               req.Body = ioutil.NopCloser(bytes.NewBuffer(body))
+               req.Body = ioutil.NopCloser(bytes.NewReader(body))
+               req.GetBody = func() (io.ReadCloser, error) {
+                       r := bytes.NewReader(body)
+                       return ioutil.NopCloser(r), nil
+               }
                // we need to manually set this because we don't set the body
                // in http.NewRequest due to using functional options, and only in NewRequest
                // does the stdlib set this for us.

We replace NewBuffer with NewReader, because the docs say

NewBuffer creates and initializes a new Buffer using buf as its initial contents. The new Buffer takes ownership of buf, and the caller should not use buf after this call.

tests/federation_room_join_partial_state_test.go Outdated Show resolved Hide resolved
tests/federation_room_join_partial_state_test.go Outdated Show resolved Hide resolved
tests/federation_room_join_partial_state_test.go Outdated Show resolved Hide resolved
@squahtx
Copy link
Contributor

squahtx commented Jan 19, 2023

I forgot to mention: this passed when I ran it locally with workers, modulo the missing Notifier.notify_replication call of course.

@H-Shay H-Shay requested a review from kegsay as a code owner January 19, 2023 20:20
@H-Shay H-Shay removed the request for review from kegsay January 19, 2023 20:31
@@ -414,7 +414,7 @@ func (c *CSAPI) LoginUser(t *testing.T, localpart, password string) (userID, acc
"user": localpart,
},
"password": password,
"type": "m.login.password",
"type": "m.login.password",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

My editor insisted on this change, I can edit the file here if it's a problem.

Copy link
Contributor

Choose a reason for hiding this comment

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

Can we revert this change please?

@H-Shay H-Shay requested a review from squahtx January 19, 2023 20:48
Copy link
Contributor

@squahtx squahtx left a comment

Choose a reason for hiding this comment

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

Looks good!

If you're feeling up for it, you could try factoring out the common code from the 3 checks into an assertUserDirectoryContains local function. createJoinEvent has an example of the syntax.

@DMRobertson
Copy link
Contributor

If you're feeling up for it, you could try factoring out the common code from the 3 checks into an assertUserDirectoryContains local function. createJoinEvent has an example of the syntax.

In the interests of getting faster joins out there I'm going to merge this as-is; though by all means do feel free to factor this out.

@DMRobertson DMRobertson merged commit e45d3f9 into main Jan 23, 2023
@DMRobertson DMRobertson deleted the shay/test_user_dir branch January 23, 2023 00:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Faster joins: Update user directory once state re-sync completes
3 participants