Update PeopleInSpaceRepo to use KMP-NativeCoroutines

This commit is contained in:
Rick Clephas 2021-11-06 12:32:53 +01:00
parent a41f29dcbc
commit 163882c121

View file

@ -1,6 +1,7 @@
package com.surrus.common.repository package com.surrus.common.repository
import co.touchlab.kermit.Kermit import co.touchlab.kermit.Kermit
import com.rickclephas.kmp.nativecoroutines.NativeCoroutineScope
import com.squareup.sqldelight.runtime.coroutines.asFlow import com.squareup.sqldelight.runtime.coroutines.asFlow
import com.squareup.sqldelight.runtime.coroutines.mapToList import com.squareup.sqldelight.runtime.coroutines.mapToList
import com.surrus.common.di.PeopleInSpaceDatabaseWrapper import com.surrus.common.di.PeopleInSpaceDatabaseWrapper
@ -11,7 +12,6 @@ import kotlinx.coroutines.*
import kotlinx.coroutines.flow.* import kotlinx.coroutines.flow.*
import org.koin.core.component.KoinComponent import org.koin.core.component.KoinComponent
import org.koin.core.component.inject import org.koin.core.component.inject
import kotlin.coroutines.CoroutineContext
interface PeopleInSpaceRepositoryInterface { interface PeopleInSpaceRepositoryInterface {
fun fetchPeopleAsFlow(): Flow<List<Assignment>> fun fetchPeopleAsFlow(): Flow<List<Assignment>>
@ -24,12 +24,11 @@ class PeopleInSpaceRepository : KoinComponent, PeopleInSpaceRepositoryInterface
private val peopleInSpaceApi: PeopleInSpaceApi by inject() private val peopleInSpaceApi: PeopleInSpaceApi by inject()
private val logger: Kermit by inject() private val logger: Kermit by inject()
@NativeCoroutineScope
private val coroutineScope: CoroutineScope = MainScope() private val coroutineScope: CoroutineScope = MainScope()
private val peopleInSpaceDatabase: PeopleInSpaceDatabaseWrapper by inject() private val peopleInSpaceDatabase: PeopleInSpaceDatabaseWrapper by inject()
private val peopleInSpaceQueries = peopleInSpaceDatabase.instance?.peopleInSpaceQueries private val peopleInSpaceQueries = peopleInSpaceDatabase.instance?.peopleInSpaceQueries
var peopleJob: Job? = null
init { init {
coroutineScope.launch { coroutineScope.launch {
fetchAndStorePeople() fetchAndStorePeople()
@ -74,51 +73,22 @@ class PeopleInSpaceRepository : KoinComponent, PeopleInSpaceRepositoryInterface
// Used by web client atm // Used by web client atm
override suspend fun fetchPeople(): List<Assignment> = peopleInSpaceApi.fetchPeople().people override suspend fun fetchPeople(): List<Assignment> = peopleInSpaceApi.fetchPeople().people
// called from Kotlin/Native clients override fun pollISSPosition(): Flow<IssPosition> {
fun startObservingPeopleUpdates(success: (List<Assignment>) -> Unit) { // The returned will be frozen in Kotlin Native. We can't freeze the Koin internals
logger.d { "startObservingPeopleUpdates" } // so we'll use local variables to prevent the Koin internals from freezing.
peopleJob = coroutineScope.launch { val api = peopleInSpaceApi
fetchPeopleAsFlow().collect { val logger = logger
success(it) return flow {
}
}
}
fun stopObservingPeopleUpdates() {
logger.d { "stopObservingPeopleUpdates, peopleJob = $peopleJob" }
peopleJob?.cancel()
}
override fun pollISSPosition(): Flow<IssPosition> = flow {
while (true) { while (true) {
val position = peopleInSpaceApi.fetchISSPosition().iss_position val position = api.fetchISSPosition().iss_position
emit(position) emit(position)
logger.d("PeopleInSpaceRepository") { position.toString() } logger.d("PeopleInSpaceRepository") { position.toString() }
delay(POLL_INTERVAL) delay(POLL_INTERVAL)
} }
} }
val iosScope: CoroutineScope = object : CoroutineScope {
override val coroutineContext: CoroutineContext
get() = SupervisorJob() + Dispatchers.Main
} }
fun iosPollISSPosition() = KotlinNativeFlowWrapper(pollISSPosition())
companion object { companion object {
private const val POLL_INTERVAL = 10000L private const val POLL_INTERVAL = 10000L
} }
} }
class KotlinNativeFlowWrapper<T>(private val flow: Flow<T>) {
fun subscribe(
scope: CoroutineScope,
onEach: (item: T) -> Unit,
onComplete: () -> Unit,
onThrow: (error: Throwable) -> Unit
) = flow
.onEach { onEach(it) }
.catch { onThrow(it) }
.onCompletion { onComplete() }
.launchIn(scope)
}