diff --git a/app/src/main/java/gq/kirmanak/mealient/data/recipes/impl/RecipePagingSourceFactory.kt b/app/src/main/java/gq/kirmanak/mealient/data/recipes/impl/RecipePagingSourceFactory.kt index a3c14e6..0e7499d 100644 --- a/app/src/main/java/gq/kirmanak/mealient/data/recipes/impl/RecipePagingSourceFactory.kt +++ b/app/src/main/java/gq/kirmanak/mealient/data/recipes/impl/RecipePagingSourceFactory.kt @@ -4,6 +4,7 @@ import androidx.paging.PagingSource import gq.kirmanak.mealient.data.recipes.db.RecipeStorage import gq.kirmanak.mealient.data.recipes.db.entity.RecipeSummaryEntity import timber.log.Timber +import java.util.concurrent.ConcurrentSkipListSet import javax.inject.Inject import javax.inject.Singleton @@ -11,9 +12,9 @@ import javax.inject.Singleton class RecipePagingSourceFactory @Inject constructor( private val recipeStorage: RecipeStorage ) : () -> PagingSource { - private val sources: MutableList> = mutableListOf() + private val sources: MutableSet> = + ConcurrentSkipListSet(PagingSourceComparator) - @Synchronized override fun invoke(): PagingSource { Timber.v("invoke() called") val newSource = recipeStorage.queryRecipes() @@ -21,7 +22,6 @@ class RecipePagingSourceFactory @Inject constructor( return newSource } - @Synchronized fun invalidate() { Timber.v("invalidate() called") for (source in sources) { @@ -31,4 +31,15 @@ class RecipePagingSourceFactory @Inject constructor( } sources.removeAll { it.invalid } } + + private object PagingSourceComparator : Comparator> { + override fun compare( + left: PagingSource?, + right: PagingSource? + ): Int { + val leftHash = left?.hashCode() ?: 0 + val rightHash = right?.hashCode() ?: 0 + return leftHash - rightHash + } + } } \ No newline at end of file diff --git a/app/src/test/java/gq/kirmanak/mealient/data/recipes/impl/RecipePagingSourceFactoryTest.kt b/app/src/test/java/gq/kirmanak/mealient/data/recipes/impl/RecipePagingSourceFactoryTest.kt new file mode 100644 index 0000000..8c98a32 --- /dev/null +++ b/app/src/test/java/gq/kirmanak/mealient/data/recipes/impl/RecipePagingSourceFactoryTest.kt @@ -0,0 +1,35 @@ +package gq.kirmanak.mealient.data.recipes.impl + +import dagger.hilt.android.testing.HiltAndroidTest +import gq.kirmanak.mealient.data.recipes.db.RecipeStorage +import gq.kirmanak.mealient.test.HiltRobolectricTest +import kotlinx.coroutines.* +import org.junit.Before +import org.junit.Test +import javax.inject.Inject + +@ExperimentalCoroutinesApi +@HiltAndroidTest +class RecipePagingSourceFactoryTest : HiltRobolectricTest() { + @Inject + lateinit var storage: RecipeStorage + lateinit var subject: RecipePagingSourceFactory + + @Before + fun setUp() { + subject = RecipePagingSourceFactory(storage) + } + + @Test + fun `when modifying concurrently then doesn't throw`(): Unit = runBlocking { + (0..100).map { + async(Dispatchers.Default) { + for (i in 0..100) { + subject.invalidate() + subject.invoke() + } + } + }.awaitAll() + } + +} \ No newline at end of file