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 crash about several DataStores using the same file #2312

Merged
merged 5 commits into from
Jan 30, 2024

Conversation

jmartinesp
Copy link
Member

Type of change

  • Feature
  • Bugfix
  • Technical
  • Other :

Content

  • Fix crash about several DataStores using the same file
    • Create @SessionCoroutineScope annotation to pass a session-managed coroutine scope to the DI.
    • Expose this scope from MatrixClient.
    • Rework SessionPreferencesStore file creation a bit. Use this coroutine scope to initialize the data store, so it's stopped when the scope is cancelled.
  • Make sure the whole item in advanced settings screen triggers the toggle action, to be consistent with the rest of the app.

Motivation and context

Fixes #2308 (I hope).

Tests

To be honest, I'm not 100% sure how to trigger this issue. I tried logging out and in again, which was my theory for why this was happening, but sadly I couldn't reproduce the issue.

Tested devices

  • Physical
  • Emulator
  • OS version(s): 14

Checklist

- Create `@SessionCoroutineScope` annotation to pass a session-managed coroutine scope to the DI.
- Expose this scope from `MatrixClient`.
- Rework DataStore file creation a bit.
@jmartinesp jmartinesp requested a review from a team as a code owner January 29, 2024 09:46
Copy link
Contributor

github-actions bot commented Jan 29, 2024

📱 Scan the QR code below to install the build (arm64 only) for this PR.
QR code
If you can't scan the QR code you can install the build via this link: https://i.diawi.com/MTvZYk

@jmartinesp jmartinesp force-pushed the fix/jme/multiple-data-stores-crash branch from 0a54f82 to bc47708 Compare January 29, 2024 10:43
@jmartinesp jmartinesp force-pushed the fix/jme/multiple-data-stores-crash branch from bc47708 to 0963aae Compare January 29, 2024 11:12
Copy link

codecov bot commented Jan 29, 2024

Codecov Report

Attention: 12 lines in your changes are missing coverage. Please review.

Comparison is base (5b0268a) 70.08% compared to head (b731e2e) 70.06%.
Report is 13 commits behind head on develop.

Files Patch % Lines
...ences/impl/store/DefaultSessionPreferencesStore.kt 0.00% 5 Missing ⚠️
...mpl/store/DefaultSessionPreferencesStoreFactory.kt 0.00% 5 Missing ⚠️
...preferences/impl/store/SessionPreferencesModule.kt 0.00% 2 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #2312      +/-   ##
===========================================
- Coverage    70.08%   70.06%   -0.02%     
===========================================
  Files         1353     1355       +2     
  Lines        33247    33256       +9     
  Branches      6877     6877              
===========================================
+ Hits         23301    23302       +1     
- Misses        6638     6646       +8     
  Partials      3308     3308              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Member

@ganfra ganfra left a comment

Choose a reason for hiding this comment

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

One remark otherwise LGTM

@@ -33,6 +35,10 @@ interface SessionComponent : NodeFactoriesBindings {
interface Builder {
@BindsInstance
fun client(matrixClient: MatrixClient): Builder

@BindsInstance
Copy link
Member

Choose a reason for hiding this comment

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

Why using @BindsInstance here? I'd just use @Provides

Copy link
Member Author

Choose a reason for hiding this comment

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

Won't @Provides need the function to be implemented?

Copy link
Member

Choose a reason for hiding this comment

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

We already have lots of @provides in the SessionMatrixModule. I'd use the builder only for things we got from the outer world.

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh, now I see what you mean. Yeah, a provides is better here.

@jmartinesp jmartinesp added the Run-Maestro Starts a Maestro Cloud session to run integration tests label Jan 29, 2024
@github-actions github-actions bot removed the Run-Maestro Starts a Maestro Cloud session to run integration tests label Jan 29, 2024
@bmarty
Copy link
Member

bmarty commented Jan 29, 2024

@jmartinesp I can repro the crash on the latest nightly systematically by:

  • opening the app
  • open a timeline
  • clicking back twice to show the device home
  • opening a room timeline from a notification.

But they are other recipes, for instance:

  • open a room
  • click back twice
  • open the app again
  • sometimes it crashes the app.

@@ -0,0 +1 @@
Fix 'There are multiple DataStores active for the same file' crashes
Copy link
Member

Choose a reason for hiding this comment

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

I am tempted to say that it's not necessary to add a file for the changelog, since the crash was not on the previous release.

@jmartinesp
Copy link
Member Author

@bmarty thanks for the reproducible steps! Sadly, it seems like the fix does not really fix the issue then... I'll keep trying.

…ncesStoreFactory` until we figure out what went wrong with the scoping
Copy link
Member

@bmarty bmarty left a comment

Choose a reason for hiding this comment

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

Glad to see that the issue is fixed!
I have some more remarks before we can merge this PR.

@ContributesTo(SessionScope::class)
object SessionPreferencesModule {
@Provides
@SingleIn(SessionScope::class)
Copy link
Member

Choose a reason for hiding this comment

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

I think @SingleIn(SessionScope::class) is not necessary here. defaultSessionPreferencesStoreFactory is already handling the concurrency access.

Copy link
Member Author

Choose a reason for hiding this comment

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

True, I was just keeping it there in case we can solve the underlying issue and remove DefaultSessionPreferencesStoreFactory. But it doesn't do anything at the moment, so we can remove it.

@SingleIn(SessionScope::class)
fun providesSessionPreferencesStore(
defaultSessionPreferencesStoreFactory: DefaultSessionPreferencesStoreFactory,
currentSessionIdHolder: CurrentSessionIdHolder,
Copy link
Member

Choose a reason for hiding this comment

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

Since this object has the scope SessionScope, can we inject directly the sessionId: String instead of the CurrentSessionIdHolder?

Oh actually CurrentSessionIdHolder is not what I though. It's not really a Holder, but more an accessor (or a provider). I think it will be simpler to provide the sessionId in SessionMatrixModule like some other fields and remove CurrentSessionIdHolder. Out of scope of this PR though.

Copy link
Member Author

Choose a reason for hiding this comment

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

I think it will be simpler to provide the sessionId in SessionMatrixModule like some other fields and remove CurrentSessionIdHolder. Out of scope of this PR though.

The problem is Anvil/Dagger doesn't understand that a SessionId is since it's Java based, for the DI library it's just a String and it won't allow you to inject it anywhere. That's why we had to create the holder wrapper. But maybe its name can be misleading.

Copy link
Member

Choose a reason for hiding this comment

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

We had annotations to be able to inject Strings in the previous project and it was quite handy.

) {
private val cache = ConcurrentHashMap<SessionId, DefaultSessionPreferencesStore>()

fun get(sessionId: SessionId, sessionCoroutineScope: CoroutineScope) = cache.getOrPut(sessionId) {
Copy link
Member

Choose a reason for hiding this comment

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

There is a warning here:
Declaration has type inferred from a platform call, which can lead to unchecked nullability issues. Specify type explicitly as nullable or non-nullable.

DefaultSessionPreferencesStore(context, sessionId, sessionCoroutineScope)
}

fun remove(sessionId: SessionId) = cache.remove(sessionId)
Copy link
Member

Choose a reason for hiding this comment

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

Not used?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, I might just remove this and clear until I create a way to clear these values in another PR (#2303 ?).


fun remove(sessionId: SessionId) = cache.remove(sessionId)

fun clear() = cache.clear()
Copy link
Member

Choose a reason for hiding this comment

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

Not used, but I do not see in which case we may want to have such method. So maybe just remove it?

Copy link

sonarcloud bot commented Jan 30, 2024

Quality Gate Passed Quality Gate passed

Kudos, no new issues were introduced!

0 New issues
0 Security Hotspots
No data about Coverage
0.0% Duplication on New Code

See analysis details on SonarCloud

Copy link
Member

@bmarty bmarty left a comment

Choose a reason for hiding this comment

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

Thanks for the update!

@jmartinesp jmartinesp added the Run-Maestro Starts a Maestro Cloud session to run integration tests label Jan 30, 2024
@github-actions github-actions bot removed the Run-Maestro Starts a Maestro Cloud session to run integration tests label Jan 30, 2024
@jmartinesp jmartinesp merged commit ede1dc0 into develop Jan 30, 2024
16 of 18 checks passed
@jmartinesp jmartinesp deleted the fix/jme/multiple-data-stores-crash branch January 30, 2024 10:10
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.

Lots of crashes with "There are multiple DataStores active for the same file"
3 participants