Skip to content

Commit

Permalink
Add ApolloStore.ALL_KEYS to notify all watchers (#6337)
Browse files Browse the repository at this point in the history
  • Loading branch information
BoD authored Dec 20, 2024
1 parent bdb6dac commit a6a8fac
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
public abstract interface class com/apollographql/apollo/cache/normalized/ApolloStore {
public static final field Companion Lcom/apollographql/apollo/cache/normalized/ApolloStore$Companion;
public abstract fun accessCache (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
public abstract fun clearAll ()Z
public abstract fun dispose ()V
Expand Down Expand Up @@ -31,6 +32,10 @@ public abstract interface class com/apollographql/apollo/cache/normalized/Apollo
public static synthetic fun writeOptimisticUpdatesSync$default (Lcom/apollographql/apollo/cache/normalized/ApolloStore;Lcom/apollographql/apollo/api/Operation;Lcom/apollographql/apollo/api/Operation$Data;Ljava/util/UUID;Lcom/apollographql/apollo/api/CustomScalarAdapters;ILjava/lang/Object;)Ljava/util/Set;
}

public final class com/apollographql/apollo/cache/normalized/ApolloStore$Companion {
public final fun getALL_KEYS ()Lkotlin/collections/AbstractSet;
}

public final class com/apollographql/apollo/cache/normalized/ApolloStoreKt {
public static final fun ApolloStore (Lcom/apollographql/apollo/cache/normalized/api/NormalizedCacheFactory;Lcom/apollographql/apollo/cache/normalized/api/CacheKeyGenerator;Lcom/apollographql/apollo/cache/normalized/api/CacheResolver;)Lcom/apollographql/apollo/cache/normalized/ApolloStore;
public static synthetic fun ApolloStore$default (Lcom/apollographql/apollo/cache/normalized/api/NormalizedCacheFactory;Lcom/apollographql/apollo/cache/normalized/api/CacheKeyGenerator;Lcom/apollographql/apollo/cache/normalized/api/CacheResolver;ILjava/lang/Object;)Lcom/apollographql/apollo/cache/normalized/ApolloStore;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ abstract interface com.apollographql.apollo.cache.normalized/ApolloStore { // co
abstract suspend fun <#A1: com.apollographql.apollo.api/Operation.Data> writeOptimisticUpdates(com.apollographql.apollo.api/Operation<#A1>, #A1, com.benasher44.uuid/Uuid, com.apollographql.apollo.api/CustomScalarAdapters = ..., kotlin/Boolean = ...): kotlin.collections/Set<kotlin/String> // com.apollographql.apollo.cache.normalized/ApolloStore.writeOptimisticUpdates|writeOptimisticUpdates(com.apollographql.apollo.api.Operation<0:0>;0:0;com.benasher44.uuid.Uuid;com.apollographql.apollo.api.CustomScalarAdapters;kotlin.Boolean){0§<com.apollographql.apollo.api.Operation.Data>}[0]
abstract suspend fun publish(kotlin.collections/Set<kotlin/String>) // com.apollographql.apollo.cache.normalized/ApolloStore.publish|publish(kotlin.collections.Set<kotlin.String>){}[0]
abstract suspend fun rollbackOptimisticUpdates(com.benasher44.uuid/Uuid, kotlin/Boolean = ...): kotlin.collections/Set<kotlin/String> // com.apollographql.apollo.cache.normalized/ApolloStore.rollbackOptimisticUpdates|rollbackOptimisticUpdates(com.benasher44.uuid.Uuid;kotlin.Boolean){}[0]

final object Companion { // com.apollographql.apollo.cache.normalized/ApolloStore.Companion|null[0]
final val ALL_KEYS // com.apollographql.apollo.cache.normalized/ApolloStore.Companion.ALL_KEYS|{}ALL_KEYS[0]
final fun <get-ALL_KEYS>(): kotlin.collections/AbstractSet<kotlin/String> // com.apollographql.apollo.cache.normalized/ApolloStore.Companion.ALL_KEYS.<get-ALL_KEYS>|<get-ALL_KEYS>(){}[0]
}
}

final class com.apollographql.apollo.cache.normalized/CacheInfo : com.apollographql.apollo.api/ExecutionContext.Element { // com.apollographql.apollo.cache.normalized/CacheInfo|null[0]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,19 @@ import kotlin.reflect.KClass
interface ApolloStore {
/**
* Exposes the keys of records that have changed.
* A special key [ALL_KEYS] is used to indicate that all records have changed.
*/
val changedKeys: SharedFlow<Set<String>>

companion object {
val ALL_KEYS = object : AbstractSet<String>() {
override val size = 0
override fun iterator() = emptySet<String>().iterator()
override fun equals(other: Any?) = other === this
override fun hashCode() = 0
}
}

/**
* Read GraphQL operation from store.
* This is a synchronous operation that might block if the underlying cache is doing IO
Expand Down Expand Up @@ -239,6 +249,9 @@ interface ApolloStore {

/**
* @param keys A set of keys of [Record] which have changed.
*
* Pass [ALL_KEYS] to indicate that all records have changed, for instance after a [clearAll] operation.
*
*/
suspend fun publish(keys: Set<String>)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ internal class DefaultApolloStore(
private val lock = Lock()

override suspend fun publish(keys: Set<String>) {
if (keys.isEmpty()) {
if (keys.isEmpty() && keys !== ApolloStore.ALL_KEYS) {
return
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ internal class WatcherInterceptor(val store: ApolloStore) : ApolloInterceptor, A
emit(Unit)
}
.filter { changedKeys ->
if (changedKeys !is Set<*>) {
return@filter true
}
watchedKeys == null || changedKeys.intersect(watchedKeys!!).isNotEmpty()
changedKeys !is Set<*> ||
changedKeys === ApolloStore.ALL_KEYS ||
watchedKeys == null ||
changedKeys.intersect(watchedKeys!!).isNotEmpty()
}.map {
if (it == Unit) {
flowOf(ApolloResponse.Builder(request.operation, request.requestUuid).exception(WatcherSentinel).build())
Expand Down
22 changes: 22 additions & 0 deletions tests/integration-tests/src/commonTest/kotlin/test/WatcherTest.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package test

import IdCacheKeyGenerator
import app.cash.turbine.test
import com.apollographql.apollo.ApolloClient
import com.apollographql.apollo.api.ApolloResponse
import com.apollographql.apollo.api.CustomScalarAdapters
Expand Down Expand Up @@ -635,6 +636,27 @@ class WatcherTest {
job.cancel()
}

@Test
fun publishAllKeys() = runTest(before = { setUp() }) {
val query = EpisodeHeroNameQuery(Episode.EMPIRE)
apolloClient.query(query)
.fetchPolicy(FetchPolicy.CacheOnly)
.watch()
.test {
// Start empty
assertIs<CacheMissException>(awaitItem().exception)

// Add data to the cache
apolloClient.enqueueTestResponse(query, episodeHeroNameData)
apolloClient.query(query).fetchPolicy(FetchPolicy.NetworkOnly).execute()
assertEquals("R2-D2", awaitItem().data?.hero?.name)

// Clear the cache
store.clearAll()
store.publish(ApolloStore.ALL_KEYS)
assertIs<CacheMissException>(awaitItem().exception)
}
}
}

internal suspend fun <D> Channel<D>.assertCount(count: Int) {
Expand Down

0 comments on commit a6a8fac

Please sign in to comment.