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: reusing PagingData crash [WPB-15055][WPB-15079][WPB-15064] #3758

Open
wants to merge 4 commits into
base: release/candidate
Choose a base branch
from

Conversation

saleniuk
Copy link
Contributor

@saleniuk saleniuk commented Dec 18, 2024

BugWPB-15055 [Android] Crash when opening connection request from paginated list


PR Submission Checklist for internal contributors

  • The PR Title

    • conforms to the style of semantic commits messages¹ supported in Wire's Github Workflow²
    • contains a reference JIRA issue number like SQPIT-764
    • answers the question: If merged, this PR will: ... ³
  • The PR Description

    • is free of optional paragraphs and you have filled the relevant parts to the best of your ability

What's new in this PR?

Issues

There are crashes related to reusing PagingData flow when doing some actions on paginated conversation list screen, like accepting legal hold request, answering 1:1 call or opening pending connection request which can fetch user data.

Causes (Optional)

Each action that modifies (or even puts the same exact data but just requires executing insert, update or delete query) a table that then affects paginated conversation list query, makes this query dirty and executes it again, which reloads the list.
When using combine, it creates a new instance of flow, so if the combine is used after PagingData is created then if the data is changed and emitted by the flow that's combined, it will re-use the same PagingData and put it into a new flow, so cachedIn won't cache the flow properly and it will crash because PagingData cannot be used twice.

Solutions

Move combine "above" the PagingData flow so that each time a new value is emitted, it will always create a new PagingData for the new flow and also cachedIn will be used correctly.
Make use of changes in kalium that doesn't execute upsert queries for User and Client if actually there's no new data so that it doesn't notify other queries - in this case paginated conversation list query thus the query doesn't get dirty and doesn't need to be executed again.
Simplify showLoading parameter to be a simple logical equation rather than a state. Make use of mocked previewConversationFoldersFlow with proper LoadStates to represent loaded data instead of using specific initiallyLoaded parameter.
Fix rememberSearchbarState so that it actually saves the searchQueryTextState.

Dependencies (Optional)

Needs releases with:

Testing

Test Coverage (Optional)

  • I have added automated test to this contribution

How to Test

The crash was happening when opening pending connection request (most frequently), answering 1:1 call or accepting legal hold request, so these actions shouldn't crash the app. Also, after opening connection request or 1:1 conversation, if your or that user's data hasn't changed since the last fetch, then it shouldn't refresh the conversation list when navigating back.

Attachments (Optional)

Before After
refreshing_when_going_back.mp4
no_refreshing_when_going_back.mp4
pagination_crash.mp4

PR Post Submission Checklist for internal contributors (Optional)

  • Wire's Github Workflow has automatically linked the PR to a JIRA issue

PR Post Merge Checklist for internal contributors

  • If any soft of configuration variable was introduced by this PR, it has been added to the relevant documents and the CI jobs have been updated.

References
  1. https://sparkbox.com/foundry/semantic_commit_messages
  2. https://github.com/wireapp/.github#usage
  3. E.g. feat(conversation-list): Sort conversations by most emojis in the title #SQPIT-764.

@echoes-hq echoes-hq bot added the echoes: unplanned Any work item that isn’t part of the product or technical roadmap. label Dec 18, 2024
Copy link
Contributor

Built wire-android-staging-compat-pr-3758.apk is available for download

@saleniuk saleniuk requested review from a team, typfel, alexandreferris, MohamadJaara, Garzas and ohassine and removed request for a team December 19, 2024 08:22
Copy link
Contributor

@borichellow borichellow 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 and very nice catch! Just a small suggestion

Comment on lines +231 to +238
private fun observeSelfUserLegalHoldState() {
viewModelScope.launch {
observeLegalHoldStateForSelfUser()
.map { it is LegalHoldStateForSelfUser.Enabled }
.flowOn(dispatcher.io())
.collect { isSelfUserUnderLegalHoldFlow.emit(it) }
}
}
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 having a separate fun with collect you can have:

val isSelfUserUnderLegalHoldFlow = observeLegalHoldStateForSelfUser()
    .map { it is LegalHoldStateForSelfUser.Enabled }
    .flowOn(dispatcher.io())
    .shareIn(viewModelScope, SharingStarted.WhileSubscribed(), 1)

isSearchActive = it[0],
searchQueryTextState = searchQueryTextState
isSearchActive = it[0] as Boolean,
searchQueryTextState = it[1]?.let {
Copy link
Contributor

Choose a reason for hiding this comment

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

Question: Are there chances of getting an IndexOutOfBounds here ? Asking just in case we can make it safer (for example using a Pair instead of a List?), otherwise it looks good to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
echoes: unplanned Any work item that isn’t part of the product or technical roadmap. size/M
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants