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

Fix timeout errors and add more fields to GroupWrapper #470

Merged
merged 9 commits into from
Aug 19, 2024

Conversation

nmalzieu
Copy link
Collaborator

@nmalzieu nmalzieu commented Aug 15, 2024

Exploring the RN thread getting completely locked sometimes, I managed to create 3 reproducible tests:

  • creating 10 groups in // : not a real use case but interesting to see that creating 9 groups in // works all of the time, creating 10 groups in // fails all of the time, on iOS + Android
  • listing many groups' members in // : this is closer to what we do in Converse and it's interesting to see that Android is able to list 50 groups's members in // while iOS fails at 20
  • doing other stuff not linked to the database while we have locked the database => other RN methods should still work, but they get blocked until the timeout throws, the whole thread is blocked

These lock last 30 seconds (I guess that's the duration of the db lock?)
During these 30 seconds, no other call to the SDK resolves (even calls to the SDK that don't rely on the database, like canMessage v2 version - the call just does not reach the native code)

Also in Converse it happens in a loop because during the sync process

  • try to sync => cause a 30 sec lock & timout
  • after 30 sec fail => retries a sync

There is an increasing backoff for retries but it explains why it looks like the app is "bricked" forever, as soon as it gets unlocked, it goes into a lock again.

We should probably understand why these calls cause a timeout and fix it (creating 10 groups should be possible, even if we need to wait a bit for the pool, here it seems we never get back the pool connection and it times out)

We should also understand why if one async call to the sdk is locking, other calls to the sdk, even not using the database, lock as well => should a pool connection awaitance cause a thread lock?

Capture d’écran 2024-08-15 à 14 25 52

@nmalzieu nmalzieu requested a review from a team as a code owner August 15, 2024 09:30
@nmalzieu nmalzieu marked this pull request as draft August 15, 2024 09:51
@nmalzieu nmalzieu marked this pull request as ready for review August 15, 2024 12:28
@nplasterer nplasterer changed the title Add a test to stress test SDK parallelism Fix timeout errors and add more fields to GroupWrapper Aug 19, 2024
@nplasterer
Copy link
Contributor

This PR now Fixes ephemeraHQ/converse-app#422 and Fixes xmtp/libxmtp#955
And adds functionality for addedBy and members list to the group

Closes #476
Closes #475

@@ -13,11 +13,12 @@ class GroupWrapper {
"clientAddress" to client.address,
"id" to group.id,
"createdAt" to group.createdAt.time,
"peerInboxIds" to group.peerInboxIds(),
"members" to group.members().map { MemberWrapper.encode(it) },
Copy link
Contributor

Choose a reason for hiding this comment

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

I didn't want to duplicate the DB call to members so this is a breaking change for anyone who is using peerInboxIds directly but is easily mitigated by mapping on inboxID if desired.

}

return true
})
Copy link
Contributor

Choose a reason for hiding this comment

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

Only left this one test that was previously failing for me and passing now.

Comment on lines +634 to 636
async membersList(): Promise<Member[]> {
return await XMTP.listGroupMembers(this.client.inboxId, this.id)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of removing this method renamed it. Since typescript wouldn't allow the name collision. It's maybe not necessary?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@nplasterer the method is still useful
If we call group.sync() , I don't think the value of the attribute group.members will be updated in place? So being able to call group.membersList() to get the refreshed value is useful?

Comment on lines +2040 to +2041
const wallet1 = Wallet.createRandom()
const wallet2 = Wallet.createRandom()
Copy link
Contributor

Choose a reason for hiding this comment

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

These wallets are in the bad key package state so had to use random ones. I think this is better anyways. But good to know for future testing when we have a fix.

@nplasterer
Copy link
Contributor

Android iOS
Screenshot 2024-08-19 at 4 39 40 PM Screenshot 2024-08-19 at 5 06 31 PM

@nplasterer nplasterer merged commit 80cae17 into main Aug 19, 2024
5 of 6 checks passed
@nplasterer nplasterer deleted the noe/rn-thread-blocked branch August 19, 2024 23:07
Copy link

🎉 This PR is included in version 2.4.5 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants