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