Skip to content

Setting IO dispatcher on repositories #274

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

Merged
merged 11 commits into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions app/src/main/java/com/toquete/boxbox/worker/SyncWorker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,14 @@ import androidx.work.CoroutineWorker
import androidx.work.NetworkType
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkerParameters
import com.toquete.boxbox.core.common.annotation.IoDispatcher
import com.toquete.boxbox.core.common.util.Syncable
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.withContext
import timber.log.Timber
import kotlin.coroutines.CoroutineContext

private val syncConstraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
Expand All @@ -20,14 +24,16 @@ private val syncConstraints = Constraints.Builder()
class SyncWorker @AssistedInject constructor(
@Assisted appContext: Context,
@Assisted workerParameters: WorkerParameters,
private val syncRepository: Syncable
private val syncRepository: Syncable,
@IoDispatcher private val dispatcher: CoroutineContext
) : CoroutineWorker(appContext, workerParameters) {

override suspend fun doWork(): Result {
return runCatching {
override suspend fun doWork(): Result = withContext(dispatcher) {
runCatching {
syncRepository.sync()
}.onFailure {
Timber.e(it)
}.onFailure { error ->
ensureActive()
Timber.e(error)
}.fold(
onSuccess = { Result.success() },
onFailure = { Result.retry() }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
package com.toquete.boxbox.data.circuitimages.repository

import com.toquete.boxbox.core.common.annotation.IoDispatcher
import com.toquete.boxbox.core.network.model.CircuitImageResponse
import com.toquete.boxbox.data.circuitimages.model.toEntity
import com.toquete.boxbox.data.circuitimages.source.local.CircuitImageLocalDataSource
import com.toquete.boxbox.data.circuitimages.source.remote.CircuitImageRemoteDataSource
import kotlinx.coroutines.withContext
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext

internal class DefaultCircuitImageRepository @Inject constructor(
private val remoteDataSource: CircuitImageRemoteDataSource,
private val localDataSource: CircuitImageLocalDataSource
private val localDataSource: CircuitImageLocalDataSource,
@IoDispatcher private val dispatcher: CoroutineContext
) : CircuitImageRepository {

override suspend fun sync() {
remoteDataSource.getCircuitImages()
.also { list ->
localDataSource.insertAll(list.map(CircuitImageResponse::toEntity))
}
withContext(dispatcher) {
val list = remoteDataSource.getCircuitImages()
localDataSource.insertAll(list.map(CircuitImageResponse::toEntity))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.toquete.boxbox.data.circuitimages.source.remote.CircuitImageRemoteDat
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.mockk
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.Test
import java.io.IOException
Expand All @@ -15,7 +16,8 @@ class DefaultCircuitImageRepositoryTest {

private val remoteDataSource: CircuitImageRemoteDataSource = mockk(relaxed = true)
private val localDataSource: CircuitImageLocalDataSource = mockk(relaxed = true)
private val repository = DefaultCircuitImageRepository(remoteDataSource, localDataSource)
private val testDispatcher = UnconfinedTestDispatcher()
private val repository = DefaultCircuitImageRepository(remoteDataSource, localDataSource, testDispatcher)

@Test
fun `sync should insert data in database when remote data is gotten successfully`() = runTest {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
package com.toquete.boxbox.data.constructorcolors.repository

import com.toquete.boxbox.core.common.annotation.IoDispatcher
import com.toquete.boxbox.core.network.model.ConstructorColorResponse
import com.toquete.boxbox.data.constructorcolors.model.toEntity
import com.toquete.boxbox.data.constructorcolors.source.local.ConstructorColorLocalDataSource
import com.toquete.boxbox.data.constructorcolors.source.remote.ConstructorColorRemoteDataSource
import kotlinx.coroutines.withContext
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext

internal class DefaultConstructorColorRepository @Inject constructor(
private val remoteDataSource: ConstructorColorRemoteDataSource,
private val localDataSource: ConstructorColorLocalDataSource
private val localDataSource: ConstructorColorLocalDataSource,
@IoDispatcher private val dispatcher: CoroutineContext
) : ConstructorColorRepository {

override suspend fun sync() {
remoteDataSource.getConstructorsColors()
.also { list ->
localDataSource.insertAll(list.map(ConstructorColorResponse::toEntity))
}
withContext(dispatcher) {
val list = remoteDataSource.getConstructorsColors()
localDataSource.insertAll(list.map(ConstructorColorResponse::toEntity))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.toquete.boxbox.data.constructorcolors.source.remote.ConstructorColorR
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.mockk
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.Test
import java.io.IOException
Expand All @@ -15,7 +16,8 @@ internal class DefaultConstructorColorRepositoryTest {

private val remoteDataSource: ConstructorColorRemoteDataSource = mockk(relaxed = true)
private val localDataSource: ConstructorColorLocalDataSource = mockk(relaxed = true)
private val repository = DefaultConstructorColorRepository(remoteDataSource, localDataSource)
private val testDispatcher = UnconfinedTestDispatcher()
private val repository = DefaultConstructorColorRepository(remoteDataSource, localDataSource, testDispatcher)

@Test
fun `sync should insert data in database when remote data is gotten successfully`() = runTest {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
package com.toquete.boxbox.data.constructorimages.repository

import com.toquete.boxbox.core.common.annotation.IoDispatcher
import com.toquete.boxbox.core.network.model.ConstructorImageResponse
import com.toquete.boxbox.data.constructorimages.model.toEntity
import com.toquete.boxbox.data.constructorimages.source.local.ConstructorImageLocalDataSource
import com.toquete.boxbox.data.constructorimages.source.remote.ConstructorImageRemoteDataSource
import kotlinx.coroutines.withContext
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext

internal class DefaultConstructorImageRepository @Inject constructor(
private val remoteDataSource: ConstructorImageRemoteDataSource,
private val localDataSource: ConstructorImageLocalDataSource
private val localDataSource: ConstructorImageLocalDataSource,
@IoDispatcher private val dispatcher: CoroutineContext
) : ConstructorImageRepository {

override suspend fun sync() {
remoteDataSource.getConstructorsImages()
.also { list ->
localDataSource.insertAll(list.map(ConstructorImageResponse::toEntity))
}
withContext(dispatcher) {
val list = remoteDataSource.getConstructorsImages()
localDataSource.insertAll(list.map(ConstructorImageResponse::toEntity))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.toquete.boxbox.data.constructorimages.source.remote.ConstructorImageR
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.mockk
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.Test
import java.io.IOException
Expand All @@ -15,7 +16,8 @@ class DefaultConstructorImageRepositoryTest {

private val remoteDataSource: ConstructorImageRemoteDataSource = mockk(relaxed = true)
private val localDataSource: ConstructorImageLocalDataSource = mockk(relaxed = true)
private val repository = DefaultConstructorImageRepository(remoteDataSource, localDataSource)
private val testDispatcher = UnconfinedTestDispatcher()
private val repository = DefaultConstructorImageRepository(remoteDataSource, localDataSource, testDispatcher)

@Test
fun `sync should insert data in database when remote data is gotten successfully`() = runTest {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.toquete.boxbox.data.constructorstandings.repository

import com.toquete.boxbox.core.common.annotation.IoDispatcher
import com.toquete.boxbox.core.database.model.FullConstructorStandingEntity
import com.toquete.boxbox.core.model.ConstructorStanding
import com.toquete.boxbox.core.network.model.ConstructorStandingResponse
Expand All @@ -8,23 +9,28 @@ import com.toquete.boxbox.data.constructorstandings.model.toEntity
import com.toquete.boxbox.data.constructorstandings.source.local.ConstructorStandingsLocalDataSource
import com.toquete.boxbox.data.constructorstandings.source.remote.ConstructorStandingsRemoteDataSource
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.withContext
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext

internal class DefaultConstructorStandingsRepository @Inject constructor(
private val remoteDataSource: ConstructorStandingsRemoteDataSource,
private val localDataSource: ConstructorStandingsLocalDataSource
private val localDataSource: ConstructorStandingsLocalDataSource,
@IoDispatcher private val dispatcher: CoroutineContext
) : ConstructorStandingsRepository {

override fun getConstructorStandings(): Flow<List<ConstructorStanding>> {
return localDataSource.getConstructorStandings()
.map { it.map(FullConstructorStandingEntity::toDomain) }
.flowOn(dispatcher)
}

override suspend fun sync() {
remoteDataSource.getConstructorStandings()
.also { list ->
localDataSource.insertAll(list.map(ConstructorStandingResponse::toEntity))
}
withContext(dispatcher) {
val list = remoteDataSource.getConstructorStandings()
localDataSource.insertAll(list.map(ConstructorStandingResponse::toEntity))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import io.mockk.every
import io.mockk.mockk
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.Test
import java.io.IOException
Expand All @@ -21,10 +22,12 @@ class DefaultConstructorStandingsRepositoryTest {

private val remoteDataSource: ConstructorStandingsRemoteDataSource = mockk(relaxed = true)
private val localDataSource: ConstructorStandingsLocalDataSource = mockk(relaxed = true)
private val testDispatcher = UnconfinedTestDispatcher()

private val repository = DefaultConstructorStandingsRepository(
remoteDataSource,
localDataSource
localDataSource,
testDispatcher
)

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
package com.toquete.boxbox.data.countries.repository

import com.toquete.boxbox.core.common.annotation.IoDispatcher
import com.toquete.boxbox.core.network.model.CountryResponse
import com.toquete.boxbox.data.countries.model.toEntity
import com.toquete.boxbox.data.countries.source.local.CountryLocalDataSource
import com.toquete.boxbox.data.countries.source.remote.CountryRemoteDataSource
import kotlinx.coroutines.withContext
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext

internal class DefaultCountryRepository @Inject constructor(
private val remoteDataSource: CountryRemoteDataSource,
private val localDataSource: CountryLocalDataSource
private val localDataSource: CountryLocalDataSource,
@IoDispatcher private val dispatcher: CoroutineContext
) : CountryRepository {

override suspend fun sync() {
remoteDataSource.getCountries()
.also { list ->
localDataSource.insertAll(list.map(CountryResponse::toEntity))
}
withContext(dispatcher) {
val list = remoteDataSource.getCountries()
localDataSource.insertAll(list.map(CountryResponse::toEntity))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.toquete.boxbox.data.countries.source.remote.CountryRemoteDataSource
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.mockk
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.Test
import java.io.IOException
Expand All @@ -15,7 +16,8 @@ class DefaultCountryRepositoryTest {

private val remoteDataSource: CountryRemoteDataSource = mockk(relaxed = true)
private val localDataSource: CountryLocalDataSource = mockk(relaxed = true)
private val repository = DefaultCountryRepository(remoteDataSource, localDataSource)
private val testDispatcher = UnconfinedTestDispatcher()
private val repository = DefaultCountryRepository(remoteDataSource, localDataSource, testDispatcher)

@Test
fun `sync should insert data in database when remote data is gotten successfully`() = runTest {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
package com.toquete.boxbox.data.driverimages.repository

import com.toquete.boxbox.core.common.annotation.IoDispatcher
import com.toquete.boxbox.core.network.model.DriverImageResponse
import com.toquete.boxbox.data.driverimages.model.toEntity
import com.toquete.boxbox.data.driverimages.source.local.DriverImageLocalDataSource
import com.toquete.boxbox.data.driverimages.source.remote.DriverImageRemoteDataSource
import kotlinx.coroutines.withContext
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext

internal class DefaultDriverImageRepository @Inject constructor(
private val remoteDataSource: DriverImageRemoteDataSource,
private val localDataSource: DriverImageLocalDataSource
private val localDataSource: DriverImageLocalDataSource,
@IoDispatcher private val dispatcher: CoroutineContext
) : DriverImageRepository {

override suspend fun sync() {
remoteDataSource.getDriversImages()
.also { list ->
localDataSource.insertAll(list.map(DriverImageResponse::toEntity))
}
withContext(dispatcher) {
val list = remoteDataSource.getDriversImages()
localDataSource.insertAll(list.map(DriverImageResponse::toEntity))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.toquete.boxbox.data.driverimages.source.remote.DriverImageRemoteDataS
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.mockk
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.Test
import java.io.IOException
Expand All @@ -15,7 +16,8 @@ class DefaultDriverImageRepositoryTest {

private val remoteDataSource: DriverImageRemoteDataSource = mockk(relaxed = true)
private val localDataSource: DriverImageLocalDataSource = mockk(relaxed = true)
private val repository = DefaultDriverImageRepository(remoteDataSource, localDataSource)
private val testDispatcher = UnconfinedTestDispatcher()
private val repository = DefaultDriverImageRepository(remoteDataSource, localDataSource, testDispatcher)

@Test
fun `sync should insert data in database when remote data is gotten successfully`() = runTest {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.toquete.boxbox.data.driverstandings.repository

import com.toquete.boxbox.core.common.annotation.IoDispatcher
import com.toquete.boxbox.core.database.model.FullDriverStandingEntity
import com.toquete.boxbox.core.model.DriverStanding
import com.toquete.boxbox.data.constructors.source.local.ConstructorsLocalDataSource
Expand All @@ -9,27 +10,32 @@ import com.toquete.boxbox.data.driverstandings.model.toEntity
import com.toquete.boxbox.data.driverstandings.source.local.DriverStandingsLocalDataSource
import com.toquete.boxbox.data.driverstandings.source.remote.DriverStandingsRemoteDataSource
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.withContext
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext

internal class DefaultDriverStandingsRepository @Inject constructor(
private val remoteDataSource: DriverStandingsRemoteDataSource,
private val localDataSource: DriverStandingsLocalDataSource,
private val driversLocalDataSource: DriversLocalDataSource,
private val constructorsLocalDataSource: ConstructorsLocalDataSource
private val constructorsLocalDataSource: ConstructorsLocalDataSource,
@IoDispatcher private val dispatcher: CoroutineContext
) : DriverStandingsRepository {

override fun getDriverStandings(): Flow<List<DriverStanding>> {
return localDataSource.getDriverStandings()
.map { it.map(FullDriverStandingEntity::toDomain) }
.flowOn(dispatcher)
}

override suspend fun sync() {
remoteDataSource.getDriverStandings()
.also { list ->
driversLocalDataSource.insertAll(list.map { it.driver.toEntity() })
constructorsLocalDataSource.insertAll(list.map { it.constructors.first().toEntity() })
localDataSource.insertAll(list.map { it.toEntity() })
}
withContext(dispatcher) {
val list = remoteDataSource.getDriverStandings()
driversLocalDataSource.insertAll(list.map { it.driver.toEntity() })
constructorsLocalDataSource.insertAll(list.map { it.constructors.first().toEntity() })
localDataSource.insertAll(list.map { it.toEntity() })
}
}
}
Loading
Loading