Wire Rust resume/pause work on app lifecycle changes

ET-4565
This commit is contained in:
Niccolò Forlini
2025-08-29 11:59:17 +02:00
parent 03023ef8aa
commit 2ef7b0e999
4 changed files with 38 additions and 8 deletions
@@ -46,6 +46,6 @@ internal class BackgroundExecutionInitializer : Initializer<Unit> {
@InstallIn(SingletonComponent::class)
interface BackgroundExecutionEntryPoint {
fun lifecycleObserver(): BackgroundExecutionLifecycleObserver
fun lifecycleObserver(): RustWorkLifecycleObserver
}
}
@@ -21,17 +21,29 @@ package ch.protonmail.android.initializer.background
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import ch.protonmail.android.mailsession.data.background.BackgroundExecutionWorkScheduler
import ch.protonmail.android.mailsession.data.repository.MailSessionRepository
import javax.inject.Inject
class BackgroundExecutionLifecycleObserver @Inject constructor(
class RustWorkLifecycleObserver @Inject constructor(
private val mailSessionRepository: MailSessionRepository,
private val backgroundExecutionWorkScheduler: BackgroundExecutionWorkScheduler
) : DefaultLifecycleObserver {
override fun onResume(owner: LifecycleOwner) {
backgroundExecutionWorkScheduler.cancelPendingWork()
resumeWork()
}
override fun onStop(owner: LifecycleOwner) {
pauseWork()
backgroundExecutionWorkScheduler.scheduleWork()
}
private fun pauseWork() {
mailSessionRepository.getMailSession().pauseWork()
}
private fun resumeWork() {
mailSessionRepository.getMailSession().resumeWork()
}
}
@@ -20,6 +20,7 @@ package ch.protonmail.android.initializer.background
import androidx.lifecycle.LifecycleOwner
import ch.protonmail.android.mailsession.data.background.BackgroundExecutionWorkScheduler
import ch.protonmail.android.mailsession.data.repository.MailSessionRepository
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.confirmVerified
@@ -30,34 +31,41 @@ import io.mockk.runs
import io.mockk.verify
import kotlin.test.Test
internal class BackgroundExecutionLifecycleObserverTest {
internal class RustWorkLifecycleObserverTest {
private val scheduler = mockk<BackgroundExecutionWorkScheduler>()
private val observer = BackgroundExecutionLifecycleObserver(scheduler)
private val mailSessionRepository = mockk<MailSessionRepository>()
private val observer = RustWorkLifecycleObserver(mailSessionRepository, scheduler)
private val lifecycleOwner = mockk<LifecycleOwner>()
@Test
fun `should cancel background work when onResume is triggered`() {
fun `should cancel background execution and resume work when onResume is triggered`() {
// Given
every { scheduler.cancelPendingWork() } just runs
every { mailSessionRepository.getMailSession().resumeWork() } just runs
// When
observer.onResume(lifecycleOwner)
// Then
verify(exactly = 1) { scheduler.cancelPendingWork() }
confirmVerified(scheduler)
coVerify(exactly = 1) { mailSessionRepository.getMailSession().resumeWork() }
confirmVerified(mailSessionRepository, scheduler)
}
@Test
fun `should schedule background work when onStop is triggered`() {
fun `should schedule background execution and pause work when onStop is triggered`() {
// Given
coEvery { scheduler.scheduleWork() } just runs
every { mailSessionRepository.getMailSession().pauseWork() } just runs
// When
observer.onStop(lifecycleOwner)
// Then
coVerify(exactly = 1) { scheduler.scheduleWork() }
confirmVerified(scheduler)
coVerify(exactly = 1) { mailSessionRepository.getMailSession().pauseWork() }
confirmVerified(mailSessionRepository, scheduler)
}
}
@@ -149,6 +149,16 @@ class MailSessionWrapper(private val mailSession: MailSession) {
fun startBackgroundTask(callback: BackgroundExecutionCallback) = mailSession.startBackgroundExecution(callback)
/**
* Used to pause work when the app is sent to the background.
*/
fun pauseWork() = mailSession.pauseWork()
/**
* Used to resume work when the app is brought back to the foreground.
*/
fun resumeWork() = mailSession.resumeWork()
suspend fun newLoginFlow(): Either<DataError, LoginFlowWrapper> {
return when (val result = mailSession.newLoginFlow()) {
is MailSessionNewLoginFlowResult.Ok -> LoginFlowWrapper(result.v1).right()