From e888e7e8827e265b914825e228ebb0236d5f103f Mon Sep 17 00:00:00 2001 From: Pavlo Ratushnyi Date: Wed, 15 May 2024 14:19:29 +0200 Subject: [PATCH] Introduce LoadingStrategy.CacheOnly --- README.md | 6 +-- dfd/gradle.properties | 2 +- dod-wrapper/gradle.properties | 2 +- dod/gradle.properties | 2 +- .../rxdata/dod/DataObservableDelegate.kt | 19 +++++-- .../com/revolut/rxdata/dod/LoadingStrategy.kt | 29 ++++------ .../rxdata/dod/DataObservableDelegateTest.kt | 54 +++++++++++++++++++ flow-extensions/gradle.properties | 2 +- model/gradle.properties | 2 +- rx-extensions/gradle.properties | 2 +- scheduler/gradle.properties | 2 +- 11 files changed, 88 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 23f8af2..51fd83a 100644 --- a/README.md +++ b/README.md @@ -21,9 +21,9 @@ And then to the module level `build.gradle.kts`: ``` dependencies { - implementation 'com.revolut.rxdata:dod:1.5.16' - implementation 'com.revolut.rxdata:core:1.5.16' - implementation 'com.revolut.rxdata:scheduler:1.5.16' + implementation 'com.revolut.rxdata:dod:1.5.17' + implementation 'com.revolut.rxdata:core:1.5.17' + implementation 'com.revolut.rxdata:scheduler:1.5.17' } ``` diff --git a/dfd/gradle.properties b/dfd/gradle.properties index 2dd64fb..526b6aa 100644 --- a/dfd/gradle.properties +++ b/dfd/gradle.properties @@ -1,5 +1,5 @@ POM_ARTIFACT_ID=dfd -VERSION_NAME=1.5.16 +VERSION_NAME=1.5.17 POM_NAME=dfd POM_PACKAGING=jar GROUP=com.revolut.flowdata diff --git a/dod-wrapper/gradle.properties b/dod-wrapper/gradle.properties index 4c2e956..540c118 100644 --- a/dod-wrapper/gradle.properties +++ b/dod-wrapper/gradle.properties @@ -1,5 +1,5 @@ POM_ARTIFACT_ID=dod-wrapper -VERSION_NAME=1.5.16 +VERSION_NAME=1.5.17 POM_NAME=dod-wrapper POM_PACKAGING=jar GROUP=com.revolut.rxdata diff --git a/dod/gradle.properties b/dod/gradle.properties index d0565b5..e6a85eb 100644 --- a/dod/gradle.properties +++ b/dod/gradle.properties @@ -1,5 +1,5 @@ POM_ARTIFACT_ID=dod -VERSION_NAME=1.5.16 +VERSION_NAME=1.5.17 POM_NAME=dod POM_PACKAGING=jar GROUP=com.revolut.rxdata diff --git a/dod/src/main/java/com/revolut/rxdata/dod/DataObservableDelegate.kt b/dod/src/main/java/com/revolut/rxdata/dod/DataObservableDelegate.kt index 45e7658..3dc4123 100644 --- a/dod/src/main/java/com/revolut/rxdata/dod/DataObservableDelegate.kt +++ b/dod/src/main/java/com/revolut/rxdata/dod/DataObservableDelegate.kt @@ -107,10 +107,14 @@ class DataObservableDelegate constructor( val memCache = fromMemory(params) val memoryIsEmpty = memCache == null val subject = subject(params) - val loading = loadingStrategy.refreshMemory - || memoryIsEmpty - || failedNetworkRequests.containsKey(params) - || (memoryCacheIsFromStorage[params] == true && loadingStrategy.refreshStorage) + val hasFailedNetworkRequest = failedNetworkRequests.containsKey(params) + val memCacheFromStorage = memoryCacheIsFromStorage[params] == true + val loading = when (loadingStrategy) { + LoadingStrategy.Auto -> memoryIsEmpty || memCacheFromStorage || hasFailedNetworkRequest + LoadingStrategy.CacheOnly -> false + LoadingStrategy.ForceReload -> true + LoadingStrategy.LazyReload -> memoryIsEmpty || hasFailedNetworkRequest + } val observable: Observable> = if (memCache != null) { concat( @@ -125,7 +129,12 @@ class DataObservableDelegate constructor( } else { sharedStorageRequest.getOrLoad(params) .flatMapObservable { cached -> - val needToFetchFromNetwork = loadingStrategy.refreshStorage || cached.content == null + val needToFetchFromNetwork = when (loadingStrategy) { + LoadingStrategy.Auto -> true + LoadingStrategy.CacheOnly -> false + LoadingStrategy.ForceReload -> true + LoadingStrategy.LazyReload -> cached.content == null + } val cachedObservable = if (needToFetchFromNetwork) { just(cached) } else { diff --git a/dod/src/main/java/com/revolut/rxdata/dod/LoadingStrategy.kt b/dod/src/main/java/com/revolut/rxdata/dod/LoadingStrategy.kt index f9516d6..03e0ffe 100644 --- a/dod/src/main/java/com/revolut/rxdata/dod/LoadingStrategy.kt +++ b/dod/src/main/java/com/revolut/rxdata/dod/LoadingStrategy.kt @@ -2,35 +2,26 @@ package com.revolut.rxdata.dod /** * [DataObservableDelegate] observation loading strategy - * - * @param refreshMemory - if true data will be fetched from network even if there is something in the memory - * @param refreshStorage - if true data will be fetched from network even if there is something in the storage */ -sealed class LoadingStrategy( - internal val refreshMemory: Boolean, - internal val refreshStorage: Boolean, -) { +sealed class LoadingStrategy { + /** * data will be fetched from the Network even if the data exists in the cache */ - object ForceReload: LoadingStrategy( - refreshMemory = true, - refreshStorage = true, - ) + object ForceReload: LoadingStrategy() /** * data will not be fetched from the Network if the data exists in the memory cache */ - object Auto: LoadingStrategy( - refreshMemory = false, - refreshStorage = true, - ) + object Auto: LoadingStrategy() /** * data will not be fetched from the Network if the data exists in the cache memory or storage */ - object LazyReload: LoadingStrategy( - refreshMemory = false, - refreshStorage = false, - ) + object LazyReload: LoadingStrategy() + + /** + * data will not be fetched from the Network even if there is no data in the cache + */ + object CacheOnly : LoadingStrategy() } \ No newline at end of file diff --git a/dod/src/test/java/com/revolut/rxdata/dod/DataObservableDelegateTest.kt b/dod/src/test/java/com/revolut/rxdata/dod/DataObservableDelegateTest.kt index 0ad20b4..852eacd 100644 --- a/dod/src/test/java/com/revolut/rxdata/dod/DataObservableDelegateTest.kt +++ b/dod/src/test/java/com/revolut/rxdata/dod/DataObservableDelegateTest.kt @@ -939,4 +939,58 @@ class DataObservableDelegateTest : BaseDataObservableDelegateTest() { verify(fromNetwork, times(0)).invoke(eq(params)) } + + @Test + fun `WHEN fromMemory has value AND LoadingStrategy is CacheOnly THEN subscriber receives memory value AND network request not triggered `() { + memCache[params] = cachedDomain + + val testObserver = + dataObservableDelegate.observe(params = params, loadingStrategy = LoadingStrategy.CacheOnly).test() + + testObserver.assertValueCount(1) + testObserver.assertValueAt(0, Data(content = cachedDomain, error = null, loading = false)) + + ioScheduler.triggerActions() + + verifyNoMoreInteractions(fromNetwork) + } + + @Test + fun `WHEN fromMemory returns null, fromStorage has value AND LoadingStrategy is CacheOnly THEN subscriber receives storage value AND network request not triggered `() { + whenever(fromMemory.invoke(eq(params))).thenReturn(null) + storage[params] = cachedDomain + + val testObserver = + dataObservableDelegate.observe(params = params, loadingStrategy = LoadingStrategy.CacheOnly).test() + + testObserver.assertValueCount(1) + testObserver.assertValueAt(0, Data(content = null, error = null, loading = true)) + ioScheduler.triggerActions() + + testObserver.assertValueCount(2) + testObserver.assertValueAt(1, Data(content = cachedDomain, error = null, loading = false)) + + ioScheduler.triggerActions() + + verifyNoMoreInteractions(fromNetwork) + } + + @Test + fun `WHEN fromMemory returns null, fromStorage returns null AND LoadingStrategy is CacheOnly THEN subscriber does not receive value AND network request not triggered`() { + whenever(fromNetwork.invoke(eq(params))).thenReturn(null) + whenever(fromMemory.invoke(eq(params))).thenReturn(null) + val testObserver = + dataObservableDelegate.observe(params = params, loadingStrategy = LoadingStrategy.CacheOnly).test() + + testObserver.assertValueCount(1) + testObserver.assertValueAt(0, Data(content = null, error = null, loading = true)) + ioScheduler.triggerActions() + + testObserver.assertValueCount(2) + testObserver.assertValueAt(1, Data(content = null, error = null, loading = false)) + + ioScheduler.triggerActions() + + verifyNoMoreInteractions(fromNetwork) + } } diff --git a/flow-extensions/gradle.properties b/flow-extensions/gradle.properties index 3e2ba1c..b5d8171 100644 --- a/flow-extensions/gradle.properties +++ b/flow-extensions/gradle.properties @@ -1,5 +1,5 @@ POM_ARTIFACT_ID=extensions -VERSION_NAME=1.5.16 +VERSION_NAME=1.5.17 POM_NAME=flow-core POM_PACKAGING=jar GROUP=com.revolut.flowdata diff --git a/model/gradle.properties b/model/gradle.properties index 48195a3..4d2a2c1 100644 --- a/model/gradle.properties +++ b/model/gradle.properties @@ -1,5 +1,5 @@ POM_ARTIFACT_ID=model -VERSION_NAME=1.5.16 +VERSION_NAME=1.5.17 POM_NAME=data POM_PACKAGING=jar GROUP=com.revolut.data diff --git a/rx-extensions/gradle.properties b/rx-extensions/gradle.properties index d880a32..5d75701 100644 --- a/rx-extensions/gradle.properties +++ b/rx-extensions/gradle.properties @@ -1,5 +1,5 @@ POM_ARTIFACT_ID=extensions -VERSION_NAME=1.5.16 +VERSION_NAME=1.5.17 POM_NAME=core POM_PACKAGING=jar GROUP=com.revolut.rxdata diff --git a/scheduler/gradle.properties b/scheduler/gradle.properties index 5749797..211f8fe 100644 --- a/scheduler/gradle.properties +++ b/scheduler/gradle.properties @@ -1,5 +1,5 @@ POM_ARTIFACT_ID=scheduler -VERSION_NAME=1.5.16 +VERSION_NAME=1.5.17 POM_NAME=scheduler POM_PACKAGING=aar GROUP=com.revolut.rxdata