-
Notifications
You must be signed in to change notification settings - Fork 739
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
Fixing IllegalStateException: You should authenticate before using this
when restoring app
#6710
Fixing IllegalStateException: You should authenticate before using this
when restoring app
#6710
Conversation
… to attempt to restore session when they're not yet created in memory
} | ||
|
||
fun getSafeActiveSession(): Session? { | ||
return activeSessionReference.get() | ||
return runBlocking { getOrInitializeSession(startSync = true) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is the crash fix, we'll always attempt to initialise the session (including perform a migration if needed)
the hope is that most users will only perform a migration via the MainActivity
flow (tapping the launcher icon/notification) which will give them a loading bar, however it's possible the ROMs/OEMs can restore the activity and application directly
* @return the initialized Session or null when no authenticated sessions are available. | ||
*/ | ||
suspend fun tryInitialize(readCurrentSession: () -> Session?, initializer: (Session) -> Unit): Session? { | ||
return withContext(INITIALIZER_CONTEXT) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the initialisation is thread safe and will block or wait for any in progress initialisers to complete, this means that ideally all access to ActiveSessionHolder
should be off the main thread to avoid possible ANRs, however this is quite a large refactor
the most common flow will be via the MainActivity
which is off the main thread
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe safer to use a semaphore instead of a single thread dispatcher?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will give it a try 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
works well! 💯 9114630
@@ -204,7 +198,7 @@ class VectorMessagingReceiver : MessagingReceiver() { | |||
} | |||
} | |||
|
|||
private fun getEventFastLane(session: Session, pushData: PushData) { | |||
private suspend fun getEventFastLane(session: Session, pushData: PushData) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reuses the suspension
@@ -80,18 +87,27 @@ class ActiveSessionHolder @Inject constructor( | |||
} | |||
|
|||
fun hasActiveSession(): Boolean { | |||
return activeSessionReference.get() != null | |||
return activeSessionReference.get() != null || authenticationService.hasAuthenticatedSessions() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
an active session is now a in memory instance or cached authenticated session
this should become async with the hasAuthenticatedSessions
being on the IO dispatcher, however as the active session is cached in memory almost straight away in most cases I've opt'd to avoid the breaking change (will hopefully be included in the realm-kotlin changes! 🤞 )
?: throw IllegalStateException("You should authenticate before using this") | ||
} | ||
|
||
suspend fun getOrInitializeSession(startSync: Boolean): Session? { | ||
return activeSessionReference.get() ?: sessionInitializer.tryInitialize(readCurrentSession = { activeSessionReference.get() }) { session -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we're eagerly reading from the in-memory cache to avoid a potential thread switch but it has the side effect of needing to query the in-memory value again within the initializer thread
} | ||
|
||
fun getSafeActiveSession(): Session? { | ||
return activeSessionReference.get() | ||
return runBlocking { getOrInitializeSession(startSync = true) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ideally getActiveSession
and getSafeActiveSession
would be suspending instead of using runBlocking
however the change needed is much bigger than the scope of this PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some small remarks otherwise LGTM
@@ -55,11 +55,15 @@ class StartAppViewModel @AssistedInject constructor( | |||
handleLongProcessing() | |||
viewModelScope.launch(Dispatchers.IO) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you take care of inject Dispatchers instead of using directly IO?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will do 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* @return the initialized Session or null when no authenticated sessions are available. | ||
*/ | ||
suspend fun tryInitialize(readCurrentSession: () -> Session?, initializer: (Session) -> Unit): Session? { | ||
return withContext(INITIALIZER_CONTEXT) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe safer to use a semaphore instead of a single thread dispatcher?
- avoids the need for a dedicated long living thread instance
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All good, thanks!
SonarCloud Quality Gate failed. |
Type of change
Content
Session
instance if we have a cached authenticated session.Motivation and context
Fixes #6709 - crash when launching the app
MainActivity
, however we can't guarantee this screen will appear first as the system may attempt to restore other screens directly along with the Application at the same timeScreenshots / GIFs
*With a manual process restart after 5 seconds~
Tests
Add the following block to
HomeActivity
to force the process to be restarted with the current launch intentTested devices