Use SessionObserver instead of SessionStore to observe sessions
This commit is contained in:
committed by
Jorge Martin Espinosa
parent
221e18d139
commit
7eae3a16ae
@@ -11,41 +11,31 @@ package io.element.android.libraries.workmanager.impl
|
||||
import androidx.work.WorkManager
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.ContributesBinding
|
||||
import io.element.android.libraries.core.coroutine.withPreviousValue
|
||||
import io.element.android.libraries.di.annotations.AppCoroutineScope
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.sessionstorage.api.SessionStore
|
||||
import io.element.android.libraries.sessionstorage.api.observer.SessionListener
|
||||
import io.element.android.libraries.sessionstorage.api.observer.SessionObserver
|
||||
import io.element.android.libraries.workmanager.api.WorkManagerRequest
|
||||
import io.element.android.libraries.workmanager.api.WorkManagerRequestType
|
||||
import io.element.android.libraries.workmanager.api.WorkManagerScheduler
|
||||
import io.element.android.libraries.workmanager.api.workManagerTag
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import timber.log.Timber
|
||||
|
||||
@ContributesBinding(AppScope::class)
|
||||
class DefaultWorkManagerScheduler(
|
||||
lazyWorkManager: Lazy<WorkManager>,
|
||||
@AppCoroutineScope private val appCoroutineScope: CoroutineScope,
|
||||
sessionStore: SessionStore,
|
||||
sessionObserver: SessionObserver,
|
||||
) : WorkManagerScheduler {
|
||||
private val workManager by lazyWorkManager
|
||||
|
||||
init {
|
||||
// Observe session removals to cancel associated work automatically
|
||||
sessionStore.sessionsFlow()
|
||||
.map { sessions -> sessions.map { SessionId(it.userId) } }
|
||||
.withPreviousValue()
|
||||
.map { (prev, new) -> prev.orEmpty() - new.toSet() }
|
||||
.onEach { removedSessions ->
|
||||
for (sessionId in removedSessions) {
|
||||
Timber.d("Session removed for userId: $sessionId, cancelling associated workmanager requests")
|
||||
cancel(sessionId)
|
||||
}
|
||||
sessionObserver.addListener(object : SessionListener {
|
||||
override suspend fun onSessionDeleted(userId: String, wasLastSession: Boolean) {
|
||||
val sessionId = SessionId(userId)
|
||||
Timber.d("Session deleted for userId: $userId, cancelling associated workmanager requests")
|
||||
cancel(sessionId)
|
||||
}
|
||||
.launchIn(appCoroutineScope)
|
||||
})
|
||||
}
|
||||
|
||||
override fun submit(workManagerRequest: WorkManagerRequest) {
|
||||
|
||||
@@ -9,10 +9,8 @@ package io.element.android.libraries.workmanager.impl
|
||||
|
||||
import androidx.work.WorkManager
|
||||
import androidx.work.WorkRequest
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.sessionstorage.test.InMemorySessionStore
|
||||
import io.element.android.libraries.sessionstorage.test.aSessionData
|
||||
import io.element.android.libraries.sessionstorage.test.observer.FakeSessionObserver
|
||||
import io.element.android.libraries.workmanager.api.WorkManagerRequest
|
||||
import io.element.android.libraries.workmanager.api.WorkManagerRequestType
|
||||
import io.element.android.libraries.workmanager.api.workManagerTag
|
||||
@@ -30,40 +28,31 @@ class DefaultWorkManagerSchedulerTest {
|
||||
@Test
|
||||
fun `starts observing sessions on init to remove work for logged out sessions`() = runTest {
|
||||
val sessionId = "@session1:matrix.org"
|
||||
val sessionStore = InMemorySessionStore(initialList = listOf(aSessionData(sessionId = sessionId)))
|
||||
val sessionObserver = FakeSessionObserver()
|
||||
|
||||
val workManager = spyk<WorkManager>()
|
||||
|
||||
DefaultWorkManagerScheduler(
|
||||
lazyWorkManager = lazy { workManager },
|
||||
appCoroutineScope = backgroundScope,
|
||||
sessionStore = sessionStore,
|
||||
sessionObserver = sessionObserver,
|
||||
)
|
||||
|
||||
// We have a single initial session
|
||||
assertThat(sessionStore.numberOfSessions()).isEqualTo(1)
|
||||
|
||||
runCurrent()
|
||||
|
||||
// We remove the session
|
||||
sessionStore.removeSession(sessionId)
|
||||
sessionObserver.onSessionDeleted(sessionId)
|
||||
|
||||
runCurrent()
|
||||
|
||||
// The session is now gone and work associated with the session is cancelled
|
||||
assertThat(sessionStore.numberOfSessions()).isEqualTo(0)
|
||||
verify { workManager.cancelAllWorkByTag("notifications-$sessionId") }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `submit builds the request and enqueues it`() = runTest {
|
||||
val sessionStore = InMemorySessionStore()
|
||||
val workManager = spyk<WorkManager>()
|
||||
|
||||
val scheduler = DefaultWorkManagerScheduler(
|
||||
lazyWorkManager = lazy { workManager },
|
||||
appCoroutineScope = backgroundScope,
|
||||
sessionStore = sessionStore,
|
||||
sessionObserver = FakeSessionObserver(),
|
||||
)
|
||||
|
||||
scheduler.submit(FakeWorkManagerRequest())
|
||||
@@ -73,13 +62,11 @@ class DefaultWorkManagerSchedulerTest {
|
||||
|
||||
@Test
|
||||
fun `submit won't do anything if building the work request fails`() = runTest {
|
||||
val sessionStore = InMemorySessionStore()
|
||||
val workManager = spyk<WorkManager>()
|
||||
|
||||
val scheduler = DefaultWorkManagerScheduler(
|
||||
lazyWorkManager = lazy { workManager },
|
||||
appCoroutineScope = backgroundScope,
|
||||
sessionStore = sessionStore,
|
||||
sessionObserver = FakeSessionObserver(),
|
||||
)
|
||||
|
||||
scheduler.submit(FakeWorkManagerRequest(result = Result.failure(IllegalStateException("Test error"))))
|
||||
@@ -89,13 +76,11 @@ class DefaultWorkManagerSchedulerTest {
|
||||
|
||||
@Test
|
||||
fun `cancel will cancel all pending work for a session id`() = runTest {
|
||||
val sessionStore = InMemorySessionStore()
|
||||
val workManager = spyk<WorkManager>()
|
||||
|
||||
val scheduler = DefaultWorkManagerScheduler(
|
||||
lazyWorkManager = lazy { workManager },
|
||||
appCoroutineScope = backgroundScope,
|
||||
sessionStore = sessionStore,
|
||||
sessionObserver = FakeSessionObserver(),
|
||||
)
|
||||
|
||||
val sessionId = SessionId("@alice:matrix.org")
|
||||
|
||||
Reference in New Issue
Block a user