diff --git a/normalized-cache-sqlite/api/android/normalized-cache-sqlite.api b/normalized-cache-sqlite/api/android/normalized-cache-sqlite.api index 8adc0fe0..a22cf517 100644 --- a/normalized-cache-sqlite/api/android/normalized-cache-sqlite.api +++ b/normalized-cache-sqlite/api/android/normalized-cache-sqlite.api @@ -18,6 +18,7 @@ public final class com/apollographql/cache/normalized/sql/SqlNormalizedCache : c public fun merge (Ljava/util/Collection;Lcom/apollographql/cache/normalized/api/CacheHeaders;Lcom/apollographql/cache/normalized/api/RecordMerger;)Ljava/util/Set; public fun remove (Ljava/util/Collection;Z)I public fun remove-eNSUWrY (Ljava/lang/String;Z)Z + public fun removeByTypes (Ljava/util/Collection;)I public fun trim (JF)J } @@ -39,15 +40,17 @@ public final class com/apollographql/cache/normalized/sql/VersionKt { } public final class com/apollographql/cache/normalized/sql/internal/record/Record { - public fun (Ljava/lang/String;[BJ)V + public fun (Ljava/lang/String;Ljava/lang/String;[BJ)V public final fun component1 ()Ljava/lang/String; - public final fun component2 ()[B - public final fun component3 ()J - public final fun copy (Ljava/lang/String;[BJ)Lcom/apollographql/cache/normalized/sql/internal/record/Record; - public static synthetic fun copy$default (Lcom/apollographql/cache/normalized/sql/internal/record/Record;Ljava/lang/String;[BJILjava/lang/Object;)Lcom/apollographql/cache/normalized/sql/internal/record/Record; + public final fun component2 ()Ljava/lang/String; + public final fun component3 ()[B + public final fun component4 ()J + public final fun copy (Ljava/lang/String;Ljava/lang/String;[BJ)Lcom/apollographql/cache/normalized/sql/internal/record/Record; + public static synthetic fun copy$default (Lcom/apollographql/cache/normalized/sql/internal/record/Record;Ljava/lang/String;Ljava/lang/String;[BJILjava/lang/Object;)Lcom/apollographql/cache/normalized/sql/internal/record/Record; public fun equals (Ljava/lang/Object;)Z public final fun getKey ()Ljava/lang/String; public final fun getRecord ()[B + public final fun getType ()Ljava/lang/String; public final fun getUpdated_date ()J public fun hashCode ()I public fun toString ()Ljava/lang/String; @@ -59,36 +62,41 @@ public final class com/apollographql/cache/normalized/sql/internal/record/Record public final fun count ()Lapp/cash/sqldelight/Query; public final fun deleteAllRecords ()V public final fun deleteRecords (Ljava/util/Collection;)V - public final fun insertOrUpdateRecord (Ljava/lang/String;[BJ)V + public final fun deleteRecordsByTypes (Ljava/util/Collection;)V + public final fun insertOrUpdateRecord (Ljava/lang/String;Ljava/lang/String;[BJ)V public final fun selectAllRecords ()Lapp/cash/sqldelight/Query; - public final fun selectAllRecords (Lkotlin/jvm/functions/Function2;)Lapp/cash/sqldelight/Query; + public final fun selectAllRecords (Lkotlin/jvm/functions/Function3;)Lapp/cash/sqldelight/Query; public final fun selectRecords (Ljava/util/Collection;)Lapp/cash/sqldelight/Query; - public final fun selectRecords (Ljava/util/Collection;Lkotlin/jvm/functions/Function2;)Lapp/cash/sqldelight/Query; + public final fun selectRecords (Ljava/util/Collection;Lkotlin/jvm/functions/Function3;)Lapp/cash/sqldelight/Query; public final fun trimByUpdatedDate (J)V } public final class com/apollographql/cache/normalized/sql/internal/record/SelectAllRecords { - public fun (Ljava/lang/String;[B)V + public fun (Ljava/lang/String;Ljava/lang/String;[B)V public final fun component1 ()Ljava/lang/String; - public final fun component2 ()[B - public final fun copy (Ljava/lang/String;[B)Lcom/apollographql/cache/normalized/sql/internal/record/SelectAllRecords; - public static synthetic fun copy$default (Lcom/apollographql/cache/normalized/sql/internal/record/SelectAllRecords;Ljava/lang/String;[BILjava/lang/Object;)Lcom/apollographql/cache/normalized/sql/internal/record/SelectAllRecords; + public final fun component2 ()Ljava/lang/String; + public final fun component3 ()[B + public final fun copy (Ljava/lang/String;Ljava/lang/String;[B)Lcom/apollographql/cache/normalized/sql/internal/record/SelectAllRecords; + public static synthetic fun copy$default (Lcom/apollographql/cache/normalized/sql/internal/record/SelectAllRecords;Ljava/lang/String;Ljava/lang/String;[BILjava/lang/Object;)Lcom/apollographql/cache/normalized/sql/internal/record/SelectAllRecords; public fun equals (Ljava/lang/Object;)Z public final fun getKey ()Ljava/lang/String; public final fun getRecord ()[B + public final fun getType ()Ljava/lang/String; public fun hashCode ()I public fun toString ()Ljava/lang/String; } public final class com/apollographql/cache/normalized/sql/internal/record/SelectRecords { - public fun (Ljava/lang/String;[B)V + public fun (Ljava/lang/String;Ljava/lang/String;[B)V public final fun component1 ()Ljava/lang/String; - public final fun component2 ()[B - public final fun copy (Ljava/lang/String;[B)Lcom/apollographql/cache/normalized/sql/internal/record/SelectRecords; - public static synthetic fun copy$default (Lcom/apollographql/cache/normalized/sql/internal/record/SelectRecords;Ljava/lang/String;[BILjava/lang/Object;)Lcom/apollographql/cache/normalized/sql/internal/record/SelectRecords; + public final fun component2 ()Ljava/lang/String; + public final fun component3 ()[B + public final fun copy (Ljava/lang/String;Ljava/lang/String;[B)Lcom/apollographql/cache/normalized/sql/internal/record/SelectRecords; + public static synthetic fun copy$default (Lcom/apollographql/cache/normalized/sql/internal/record/SelectRecords;Ljava/lang/String;Ljava/lang/String;[BILjava/lang/Object;)Lcom/apollographql/cache/normalized/sql/internal/record/SelectRecords; public fun equals (Ljava/lang/Object;)Z public final fun getKey ()Ljava/lang/String; public final fun getRecord ()[B + public final fun getType ()Ljava/lang/String; public fun hashCode ()I public fun toString ()Ljava/lang/String; } diff --git a/normalized-cache-sqlite/api/jvm/normalized-cache-sqlite.api b/normalized-cache-sqlite/api/jvm/normalized-cache-sqlite.api index de11d7e4..0c9529c1 100644 --- a/normalized-cache-sqlite/api/jvm/normalized-cache-sqlite.api +++ b/normalized-cache-sqlite/api/jvm/normalized-cache-sqlite.api @@ -7,6 +7,7 @@ public final class com/apollographql/cache/normalized/sql/SqlNormalizedCache : c public fun merge (Ljava/util/Collection;Lcom/apollographql/cache/normalized/api/CacheHeaders;Lcom/apollographql/cache/normalized/api/RecordMerger;)Ljava/util/Set; public fun remove (Ljava/util/Collection;Z)I public fun remove-eNSUWrY (Ljava/lang/String;Z)Z + public fun removeByTypes (Ljava/util/Collection;)I public fun trim (JF)J } @@ -24,15 +25,17 @@ public final class com/apollographql/cache/normalized/sql/VersionKt { } public final class com/apollographql/cache/normalized/sql/internal/record/Record { - public fun (Ljava/lang/String;[BJ)V + public fun (Ljava/lang/String;Ljava/lang/String;[BJ)V public final fun component1 ()Ljava/lang/String; - public final fun component2 ()[B - public final fun component3 ()J - public final fun copy (Ljava/lang/String;[BJ)Lcom/apollographql/cache/normalized/sql/internal/record/Record; - public static synthetic fun copy$default (Lcom/apollographql/cache/normalized/sql/internal/record/Record;Ljava/lang/String;[BJILjava/lang/Object;)Lcom/apollographql/cache/normalized/sql/internal/record/Record; + public final fun component2 ()Ljava/lang/String; + public final fun component3 ()[B + public final fun component4 ()J + public final fun copy (Ljava/lang/String;Ljava/lang/String;[BJ)Lcom/apollographql/cache/normalized/sql/internal/record/Record; + public static synthetic fun copy$default (Lcom/apollographql/cache/normalized/sql/internal/record/Record;Ljava/lang/String;Ljava/lang/String;[BJILjava/lang/Object;)Lcom/apollographql/cache/normalized/sql/internal/record/Record; public fun equals (Ljava/lang/Object;)Z public final fun getKey ()Ljava/lang/String; public final fun getRecord ()[B + public final fun getType ()Ljava/lang/String; public final fun getUpdated_date ()J public fun hashCode ()I public fun toString ()Ljava/lang/String; @@ -44,36 +47,41 @@ public final class com/apollographql/cache/normalized/sql/internal/record/Record public final fun count ()Lapp/cash/sqldelight/Query; public final fun deleteAllRecords ()V public final fun deleteRecords (Ljava/util/Collection;)V - public final fun insertOrUpdateRecord (Ljava/lang/String;[BJ)V + public final fun deleteRecordsByTypes (Ljava/util/Collection;)V + public final fun insertOrUpdateRecord (Ljava/lang/String;Ljava/lang/String;[BJ)V public final fun selectAllRecords ()Lapp/cash/sqldelight/Query; - public final fun selectAllRecords (Lkotlin/jvm/functions/Function2;)Lapp/cash/sqldelight/Query; + public final fun selectAllRecords (Lkotlin/jvm/functions/Function3;)Lapp/cash/sqldelight/Query; public final fun selectRecords (Ljava/util/Collection;)Lapp/cash/sqldelight/Query; - public final fun selectRecords (Ljava/util/Collection;Lkotlin/jvm/functions/Function2;)Lapp/cash/sqldelight/Query; + public final fun selectRecords (Ljava/util/Collection;Lkotlin/jvm/functions/Function3;)Lapp/cash/sqldelight/Query; public final fun trimByUpdatedDate (J)V } public final class com/apollographql/cache/normalized/sql/internal/record/SelectAllRecords { - public fun (Ljava/lang/String;[B)V + public fun (Ljava/lang/String;Ljava/lang/String;[B)V public final fun component1 ()Ljava/lang/String; - public final fun component2 ()[B - public final fun copy (Ljava/lang/String;[B)Lcom/apollographql/cache/normalized/sql/internal/record/SelectAllRecords; - public static synthetic fun copy$default (Lcom/apollographql/cache/normalized/sql/internal/record/SelectAllRecords;Ljava/lang/String;[BILjava/lang/Object;)Lcom/apollographql/cache/normalized/sql/internal/record/SelectAllRecords; + public final fun component2 ()Ljava/lang/String; + public final fun component3 ()[B + public final fun copy (Ljava/lang/String;Ljava/lang/String;[B)Lcom/apollographql/cache/normalized/sql/internal/record/SelectAllRecords; + public static synthetic fun copy$default (Lcom/apollographql/cache/normalized/sql/internal/record/SelectAllRecords;Ljava/lang/String;Ljava/lang/String;[BILjava/lang/Object;)Lcom/apollographql/cache/normalized/sql/internal/record/SelectAllRecords; public fun equals (Ljava/lang/Object;)Z public final fun getKey ()Ljava/lang/String; public final fun getRecord ()[B + public final fun getType ()Ljava/lang/String; public fun hashCode ()I public fun toString ()Ljava/lang/String; } public final class com/apollographql/cache/normalized/sql/internal/record/SelectRecords { - public fun (Ljava/lang/String;[B)V + public fun (Ljava/lang/String;Ljava/lang/String;[B)V public final fun component1 ()Ljava/lang/String; - public final fun component2 ()[B - public final fun copy (Ljava/lang/String;[B)Lcom/apollographql/cache/normalized/sql/internal/record/SelectRecords; - public static synthetic fun copy$default (Lcom/apollographql/cache/normalized/sql/internal/record/SelectRecords;Ljava/lang/String;[BILjava/lang/Object;)Lcom/apollographql/cache/normalized/sql/internal/record/SelectRecords; + public final fun component2 ()Ljava/lang/String; + public final fun component3 ()[B + public final fun copy (Ljava/lang/String;Ljava/lang/String;[B)Lcom/apollographql/cache/normalized/sql/internal/record/SelectRecords; + public static synthetic fun copy$default (Lcom/apollographql/cache/normalized/sql/internal/record/SelectRecords;Ljava/lang/String;Ljava/lang/String;[BILjava/lang/Object;)Lcom/apollographql/cache/normalized/sql/internal/record/SelectRecords; public fun equals (Ljava/lang/Object;)Z public final fun getKey ()Ljava/lang/String; public final fun getRecord ()[B + public final fun getType ()Ljava/lang/String; public fun hashCode ()I public fun toString ()Ljava/lang/String; } diff --git a/normalized-cache-sqlite/api/normalized-cache-sqlite.klib.api b/normalized-cache-sqlite/api/normalized-cache-sqlite.klib.api index 7f22099b..a2814883 100644 --- a/normalized-cache-sqlite/api/normalized-cache-sqlite.klib.api +++ b/normalized-cache-sqlite/api/normalized-cache-sqlite.klib.api @@ -19,19 +19,22 @@ abstract interface com.apollographql.cache.normalized.sql.internal.record/SqlRec } final class com.apollographql.cache.normalized.sql.internal.record/Record { // com.apollographql.cache.normalized.sql.internal.record/Record|null[0] - constructor (kotlin/String, kotlin/ByteArray, kotlin/Long) // com.apollographql.cache.normalized.sql.internal.record/Record.|(kotlin.String;kotlin.ByteArray;kotlin.Long){}[0] + constructor (kotlin/String, kotlin/String, kotlin/ByteArray, kotlin/Long) // com.apollographql.cache.normalized.sql.internal.record/Record.|(kotlin.String;kotlin.String;kotlin.ByteArray;kotlin.Long){}[0] final val key // com.apollographql.cache.normalized.sql.internal.record/Record.key|{}key[0] final fun (): kotlin/String // com.apollographql.cache.normalized.sql.internal.record/Record.key.|(){}[0] final val record // com.apollographql.cache.normalized.sql.internal.record/Record.record|{}record[0] final fun (): kotlin/ByteArray // com.apollographql.cache.normalized.sql.internal.record/Record.record.|(){}[0] + final val type // com.apollographql.cache.normalized.sql.internal.record/Record.type|{}type[0] + final fun (): kotlin/String // com.apollographql.cache.normalized.sql.internal.record/Record.type.|(){}[0] final val updated_date // com.apollographql.cache.normalized.sql.internal.record/Record.updated_date|{}updated_date[0] final fun (): kotlin/Long // com.apollographql.cache.normalized.sql.internal.record/Record.updated_date.|(){}[0] final fun component1(): kotlin/String // com.apollographql.cache.normalized.sql.internal.record/Record.component1|component1(){}[0] - final fun component2(): kotlin/ByteArray // com.apollographql.cache.normalized.sql.internal.record/Record.component2|component2(){}[0] - final fun component3(): kotlin/Long // com.apollographql.cache.normalized.sql.internal.record/Record.component3|component3(){}[0] - final fun copy(kotlin/String = ..., kotlin/ByteArray = ..., kotlin/Long = ...): com.apollographql.cache.normalized.sql.internal.record/Record // com.apollographql.cache.normalized.sql.internal.record/Record.copy|copy(kotlin.String;kotlin.ByteArray;kotlin.Long){}[0] + final fun component2(): kotlin/String // com.apollographql.cache.normalized.sql.internal.record/Record.component2|component2(){}[0] + final fun component3(): kotlin/ByteArray // com.apollographql.cache.normalized.sql.internal.record/Record.component3|component3(){}[0] + final fun component4(): kotlin/Long // com.apollographql.cache.normalized.sql.internal.record/Record.component4|component4(){}[0] + final fun copy(kotlin/String = ..., kotlin/String = ..., kotlin/ByteArray = ..., kotlin/Long = ...): com.apollographql.cache.normalized.sql.internal.record/Record // com.apollographql.cache.normalized.sql.internal.record/Record.copy|copy(kotlin.String;kotlin.String;kotlin.ByteArray;kotlin.Long){}[0] final fun equals(kotlin/Any?): kotlin/Boolean // com.apollographql.cache.normalized.sql.internal.record/Record.equals|equals(kotlin.Any?){}[0] final fun hashCode(): kotlin/Int // com.apollographql.cache.normalized.sql.internal.record/Record.hashCode|hashCode(){}[0] final fun toString(): kotlin/String // com.apollographql.cache.normalized.sql.internal.record/Record.toString|toString(){}[0] @@ -40,45 +43,52 @@ final class com.apollographql.cache.normalized.sql.internal.record/Record { // c final class com.apollographql.cache.normalized.sql.internal.record/RecordQueries : app.cash.sqldelight/TransacterImpl { // com.apollographql.cache.normalized.sql.internal.record/RecordQueries|null[0] constructor (app.cash.sqldelight.db/SqlDriver) // com.apollographql.cache.normalized.sql.internal.record/RecordQueries.|(app.cash.sqldelight.db.SqlDriver){}[0] - final fun <#A1: kotlin/Any> selectAllRecords(kotlin/Function2): app.cash.sqldelight/Query<#A1> // com.apollographql.cache.normalized.sql.internal.record/RecordQueries.selectAllRecords|selectAllRecords(kotlin.Function2){0§}[0] - final fun <#A1: kotlin/Any> selectRecords(kotlin.collections/Collection, kotlin/Function2): app.cash.sqldelight/Query<#A1> // com.apollographql.cache.normalized.sql.internal.record/RecordQueries.selectRecords|selectRecords(kotlin.collections.Collection;kotlin.Function2){0§}[0] + final fun <#A1: kotlin/Any> selectAllRecords(kotlin/Function3): app.cash.sqldelight/Query<#A1> // com.apollographql.cache.normalized.sql.internal.record/RecordQueries.selectAllRecords|selectAllRecords(kotlin.Function3){0§}[0] + final fun <#A1: kotlin/Any> selectRecords(kotlin.collections/Collection, kotlin/Function3): app.cash.sqldelight/Query<#A1> // com.apollographql.cache.normalized.sql.internal.record/RecordQueries.selectRecords|selectRecords(kotlin.collections.Collection;kotlin.Function3){0§}[0] final fun changes(): app.cash.sqldelight/ExecutableQuery // com.apollographql.cache.normalized.sql.internal.record/RecordQueries.changes|changes(){}[0] final fun count(): app.cash.sqldelight/Query // com.apollographql.cache.normalized.sql.internal.record/RecordQueries.count|count(){}[0] final fun deleteAllRecords() // com.apollographql.cache.normalized.sql.internal.record/RecordQueries.deleteAllRecords|deleteAllRecords(){}[0] final fun deleteRecords(kotlin.collections/Collection) // com.apollographql.cache.normalized.sql.internal.record/RecordQueries.deleteRecords|deleteRecords(kotlin.collections.Collection){}[0] - final fun insertOrUpdateRecord(kotlin/String, kotlin/ByteArray, kotlin/Long) // com.apollographql.cache.normalized.sql.internal.record/RecordQueries.insertOrUpdateRecord|insertOrUpdateRecord(kotlin.String;kotlin.ByteArray;kotlin.Long){}[0] + final fun deleteRecordsByTypes(kotlin.collections/Collection) // com.apollographql.cache.normalized.sql.internal.record/RecordQueries.deleteRecordsByTypes|deleteRecordsByTypes(kotlin.collections.Collection){}[0] + final fun insertOrUpdateRecord(kotlin/String, kotlin/String, kotlin/ByteArray, kotlin/Long) // com.apollographql.cache.normalized.sql.internal.record/RecordQueries.insertOrUpdateRecord|insertOrUpdateRecord(kotlin.String;kotlin.String;kotlin.ByteArray;kotlin.Long){}[0] final fun selectAllRecords(): app.cash.sqldelight/Query // com.apollographql.cache.normalized.sql.internal.record/RecordQueries.selectAllRecords|selectAllRecords(){}[0] final fun selectRecords(kotlin.collections/Collection): app.cash.sqldelight/Query // com.apollographql.cache.normalized.sql.internal.record/RecordQueries.selectRecords|selectRecords(kotlin.collections.Collection){}[0] final fun trimByUpdatedDate(kotlin/Long) // com.apollographql.cache.normalized.sql.internal.record/RecordQueries.trimByUpdatedDate|trimByUpdatedDate(kotlin.Long){}[0] } final class com.apollographql.cache.normalized.sql.internal.record/SelectAllRecords { // com.apollographql.cache.normalized.sql.internal.record/SelectAllRecords|null[0] - constructor (kotlin/String, kotlin/ByteArray) // com.apollographql.cache.normalized.sql.internal.record/SelectAllRecords.|(kotlin.String;kotlin.ByteArray){}[0] + constructor (kotlin/String, kotlin/String, kotlin/ByteArray) // com.apollographql.cache.normalized.sql.internal.record/SelectAllRecords.|(kotlin.String;kotlin.String;kotlin.ByteArray){}[0] final val key // com.apollographql.cache.normalized.sql.internal.record/SelectAllRecords.key|{}key[0] final fun (): kotlin/String // com.apollographql.cache.normalized.sql.internal.record/SelectAllRecords.key.|(){}[0] final val record // com.apollographql.cache.normalized.sql.internal.record/SelectAllRecords.record|{}record[0] final fun (): kotlin/ByteArray // com.apollographql.cache.normalized.sql.internal.record/SelectAllRecords.record.|(){}[0] + final val type // com.apollographql.cache.normalized.sql.internal.record/SelectAllRecords.type|{}type[0] + final fun (): kotlin/String // com.apollographql.cache.normalized.sql.internal.record/SelectAllRecords.type.|(){}[0] final fun component1(): kotlin/String // com.apollographql.cache.normalized.sql.internal.record/SelectAllRecords.component1|component1(){}[0] - final fun component2(): kotlin/ByteArray // com.apollographql.cache.normalized.sql.internal.record/SelectAllRecords.component2|component2(){}[0] - final fun copy(kotlin/String = ..., kotlin/ByteArray = ...): com.apollographql.cache.normalized.sql.internal.record/SelectAllRecords // com.apollographql.cache.normalized.sql.internal.record/SelectAllRecords.copy|copy(kotlin.String;kotlin.ByteArray){}[0] + final fun component2(): kotlin/String // com.apollographql.cache.normalized.sql.internal.record/SelectAllRecords.component2|component2(){}[0] + final fun component3(): kotlin/ByteArray // com.apollographql.cache.normalized.sql.internal.record/SelectAllRecords.component3|component3(){}[0] + final fun copy(kotlin/String = ..., kotlin/String = ..., kotlin/ByteArray = ...): com.apollographql.cache.normalized.sql.internal.record/SelectAllRecords // com.apollographql.cache.normalized.sql.internal.record/SelectAllRecords.copy|copy(kotlin.String;kotlin.String;kotlin.ByteArray){}[0] final fun equals(kotlin/Any?): kotlin/Boolean // com.apollographql.cache.normalized.sql.internal.record/SelectAllRecords.equals|equals(kotlin.Any?){}[0] final fun hashCode(): kotlin/Int // com.apollographql.cache.normalized.sql.internal.record/SelectAllRecords.hashCode|hashCode(){}[0] final fun toString(): kotlin/String // com.apollographql.cache.normalized.sql.internal.record/SelectAllRecords.toString|toString(){}[0] } final class com.apollographql.cache.normalized.sql.internal.record/SelectRecords { // com.apollographql.cache.normalized.sql.internal.record/SelectRecords|null[0] - constructor (kotlin/String, kotlin/ByteArray) // com.apollographql.cache.normalized.sql.internal.record/SelectRecords.|(kotlin.String;kotlin.ByteArray){}[0] + constructor (kotlin/String, kotlin/String, kotlin/ByteArray) // com.apollographql.cache.normalized.sql.internal.record/SelectRecords.|(kotlin.String;kotlin.String;kotlin.ByteArray){}[0] final val key // com.apollographql.cache.normalized.sql.internal.record/SelectRecords.key|{}key[0] final fun (): kotlin/String // com.apollographql.cache.normalized.sql.internal.record/SelectRecords.key.|(){}[0] final val record // com.apollographql.cache.normalized.sql.internal.record/SelectRecords.record|{}record[0] final fun (): kotlin/ByteArray // com.apollographql.cache.normalized.sql.internal.record/SelectRecords.record.|(){}[0] + final val type // com.apollographql.cache.normalized.sql.internal.record/SelectRecords.type|{}type[0] + final fun (): kotlin/String // com.apollographql.cache.normalized.sql.internal.record/SelectRecords.type.|(){}[0] final fun component1(): kotlin/String // com.apollographql.cache.normalized.sql.internal.record/SelectRecords.component1|component1(){}[0] - final fun component2(): kotlin/ByteArray // com.apollographql.cache.normalized.sql.internal.record/SelectRecords.component2|component2(){}[0] - final fun copy(kotlin/String = ..., kotlin/ByteArray = ...): com.apollographql.cache.normalized.sql.internal.record/SelectRecords // com.apollographql.cache.normalized.sql.internal.record/SelectRecords.copy|copy(kotlin.String;kotlin.ByteArray){}[0] + final fun component2(): kotlin/String // com.apollographql.cache.normalized.sql.internal.record/SelectRecords.component2|component2(){}[0] + final fun component3(): kotlin/ByteArray // com.apollographql.cache.normalized.sql.internal.record/SelectRecords.component3|component3(){}[0] + final fun copy(kotlin/String = ..., kotlin/String = ..., kotlin/ByteArray = ...): com.apollographql.cache.normalized.sql.internal.record/SelectRecords // com.apollographql.cache.normalized.sql.internal.record/SelectRecords.copy|copy(kotlin.String;kotlin.String;kotlin.ByteArray){}[0] final fun equals(kotlin/Any?): kotlin/Boolean // com.apollographql.cache.normalized.sql.internal.record/SelectRecords.equals|equals(kotlin.Any?){}[0] final fun hashCode(): kotlin/Int // com.apollographql.cache.normalized.sql.internal.record/SelectRecords.hashCode|hashCode(){}[0] final fun toString(): kotlin/String // com.apollographql.cache.normalized.sql.internal.record/SelectRecords.toString|toString(){}[0] @@ -93,6 +103,7 @@ final class com.apollographql.cache.normalized.sql/SqlNormalizedCache : com.apol final fun merge(kotlin.collections/Collection, com.apollographql.cache.normalized.api/CacheHeaders, com.apollographql.cache.normalized.api/RecordMerger): kotlin.collections/Set // com.apollographql.cache.normalized.sql/SqlNormalizedCache.merge|merge(kotlin.collections.Collection;com.apollographql.cache.normalized.api.CacheHeaders;com.apollographql.cache.normalized.api.RecordMerger){}[0] final fun remove(com.apollographql.cache.normalized.api/CacheKey, kotlin/Boolean): kotlin/Boolean // com.apollographql.cache.normalized.sql/SqlNormalizedCache.remove|remove(com.apollographql.cache.normalized.api.CacheKey;kotlin.Boolean){}[0] final fun remove(kotlin.collections/Collection, kotlin/Boolean): kotlin/Int // com.apollographql.cache.normalized.sql/SqlNormalizedCache.remove|remove(kotlin.collections.Collection;kotlin.Boolean){}[0] + final fun removeByTypes(kotlin.collections/Collection): kotlin/Int // com.apollographql.cache.normalized.sql/SqlNormalizedCache.removeByTypes|removeByTypes(kotlin.collections.Collection){}[0] final fun trim(kotlin/Long, kotlin/Float): kotlin/Long // com.apollographql.cache.normalized.sql/SqlNormalizedCache.trim|trim(kotlin.Long;kotlin.Float){}[0] } diff --git a/normalized-cache-sqlite/sqldelight/record/schema/4.db b/normalized-cache-sqlite/sqldelight/record/schema/4.db new file mode 100644 index 00000000..be9cb570 Binary files /dev/null and b/normalized-cache-sqlite/sqldelight/record/schema/4.db differ diff --git a/normalized-cache-sqlite/src/commonMain/kotlin/com/apollographql/cache/normalized/sql/SqlNormalizedCache.kt b/normalized-cache-sqlite/src/commonMain/kotlin/com/apollographql/cache/normalized/sql/SqlNormalizedCache.kt index 131f7b72..eaff8f76 100644 --- a/normalized-cache-sqlite/src/commonMain/kotlin/com/apollographql/cache/normalized/sql/SqlNormalizedCache.kt +++ b/normalized-cache-sqlite/src/commonMain/kotlin/com/apollographql/cache/normalized/sql/SqlNormalizedCache.kt @@ -48,6 +48,12 @@ class SqlNormalizedCache internal constructor( } } + override fun removeByTypes(types: Collection): Int { + return recordDatabase.transaction { + internalDeleteRecordsByTypes(types) + } + } + override fun merge(record: Record, cacheHeaders: CacheHeaders, recordMerger: RecordMerger): Set { return merge(records = listOf(record), cacheHeaders = cacheHeaders, recordMerger = recordMerger) } @@ -95,6 +101,16 @@ class SqlNormalizedCache internal constructor( } } + /** + * Assumes an enclosing transaction + */ + private fun internalDeleteRecordsByTypes(types: Collection): Int { + return (types).chunked(parametersMax).sumOf { chunkedKeys -> + recordDatabase.deleteRecordsByTypes(chunkedKeys) + recordDatabase.changes().toInt() + } + } + /** * Updates records. * The [records] are merged using the given [recordMerger], requiring to load the existing records from the db first. @@ -121,7 +137,7 @@ class SqlNormalizedCache internal constructor( } /** - * Loads a list of records, making sure to not query more than 999 at a time + * Loads a list of records, making sure to not query more than [parametersMax] at a time * to help with the SQLite limitations */ private fun selectRecords(keys: Collection): List { diff --git a/normalized-cache-sqlite/src/commonMain/kotlin/com/apollographql/cache/normalized/sql/internal/RecordDatabase.kt b/normalized-cache-sqlite/src/commonMain/kotlin/com/apollographql/cache/normalized/sql/internal/RecordDatabase.kt index 1dedc13a..8b1cd559 100644 --- a/normalized-cache-sqlite/src/commonMain/kotlin/com/apollographql/cache/normalized/sql/internal/RecordDatabase.kt +++ b/normalized-cache-sqlite/src/commonMain/kotlin/com/apollographql/cache/normalized/sql/internal/RecordDatabase.kt @@ -18,28 +18,52 @@ internal class RecordDatabase(private val driver: SqlDriver) { } /** - * @param keys the keys of the records to select, size must be <= 999 + * @param keys the keys of the records to delete. Size must be under the max size of the SQL IN clause. */ fun selectRecords(keys: Collection): List { - return recordQueries.selectRecords(keys).executeAsList().map { RecordSerializer.deserialize(it.key, it.record) } + return recordQueries.selectRecords(keys).executeAsList().map { + RecordSerializer.deserialize( + key = it.key, + type = it.type, + bytes = it.record, + ) + } } fun selectAllRecords(): List { - return recordQueries.selectAllRecords().executeAsList().map { RecordSerializer.deserialize(it.key, it.record) } + return recordQueries.selectAllRecords().executeAsList().map { + RecordSerializer.deserialize( + key = it.key, + type = it.type, + bytes = it.record, + ) + } } fun insertOrUpdateRecord(record: Record) { - recordQueries.insertOrUpdateRecord(key = record.key.key, record = RecordSerializer.serialize(record), updated_date = currentTimeMillis()) + recordQueries.insertOrUpdateRecord( + key = record.key.key, + type = record.type, + record = RecordSerializer.serialize(record), + updated_date = currentTimeMillis(), + ) } /** - * @param keys the keys of the records to delete, size must be <= 999 + * @param keys the keys of the records to delete. Size must be under the max size of the SQL IN clause. */ fun deleteRecords(keys: Collection) { recordQueries.deleteRecords(keys) } + /** + * @param types the types of the records to delete. Size must be under the max size of the SQL IN clause. + */ + fun deleteRecordsByTypes(types: Collection) { + recordQueries.deleteRecordsByTypes(types) + } + fun deleteAllRecords() { recordQueries.deleteAllRecords() } diff --git a/normalized-cache-sqlite/src/commonMain/kotlin/com/apollographql/cache/normalized/sql/internal/RecordSerializer.kt b/normalized-cache-sqlite/src/commonMain/kotlin/com/apollographql/cache/normalized/sql/internal/RecordSerializer.kt index 178e1951..a286cfd4 100644 --- a/normalized-cache-sqlite/src/commonMain/kotlin/com/apollographql/cache/normalized/sql/internal/RecordSerializer.kt +++ b/normalized-cache-sqlite/src/commonMain/kotlin/com/apollographql/cache/normalized/sql/internal/RecordSerializer.kt @@ -26,7 +26,7 @@ internal object RecordSerializer { return buffer.readByteArray() } - fun deserialize(key: String, bytes: ByteArray): Record { + fun deserialize(key: String, type: String, bytes: ByteArray): Record { val buffer = Buffer().write(bytes) val fields = buffer.readMap() val metadataSize = buffer._readInt() @@ -39,6 +39,7 @@ internal object RecordSerializer { }.mapKeys { (k, _) -> knownMetadataKeysInverted[k] ?: k } return Record( key = CacheKey(key), + type = type, fields = fields, mutationId = null, metadata = metadata diff --git a/normalized-cache-sqlite/src/commonMain/sqldelight/record/com/apollographql/cache/normalized/sql/internal/record/record.sq b/normalized-cache-sqlite/src/commonMain/sqldelight/record/com/apollographql/cache/normalized/sql/internal/record/record.sq index f5345ce6..43cb0e3b 100644 --- a/normalized-cache-sqlite/src/commonMain/sqldelight/record/com/apollographql/cache/normalized/sql/internal/record/record.sq +++ b/normalized-cache-sqlite/src/commonMain/sqldelight/record/com/apollographql/cache/normalized/sql/internal/record/record.sq @@ -1,5 +1,6 @@ CREATE TABLE record ( key TEXT NOT NULL, + type TEXT NOT NULL, record BLOB NOT NULL, updated_date INTEGER NOT NULL, PRIMARY KEY (key) ON CONFLICT REPLACE @@ -7,17 +8,20 @@ CREATE TABLE record ( WITHOUT ROWID; selectRecords: -SELECT key, record FROM record WHERE key IN ?; +SELECT key, type, record FROM record WHERE key IN ?; selectAllRecords: -SELECT key, record FROM record; +SELECT key, type, record FROM record; insertOrUpdateRecord: -INSERT INTO record (key, record, updated_date) VALUES (?, ?, ?); +INSERT INTO record (key, type, record, updated_date) VALUES (?, ?, ?, ?); deleteRecords: DELETE FROM record WHERE key IN ?; +deleteRecordsByTypes: +DELETE FROM record WHERE type IN ?; + deleteAllRecords: DELETE FROM record; diff --git a/normalized-cache-sqlite/src/commonMain/sqldelight/record/com/migrations/3.sqm b/normalized-cache-sqlite/src/commonMain/sqldelight/record/com/migrations/3.sqm new file mode 100644 index 00000000..709edfa7 --- /dev/null +++ b/normalized-cache-sqlite/src/commonMain/sqldelight/record/com/migrations/3.sqm @@ -0,0 +1,3 @@ +-- Version 3 is the 'record' schema without the type column - add it + +ALTER TABLE record ADD COLUMN type TEXT NOT NULL DEFAULT ''; diff --git a/normalized-cache-sqlite/src/commonTest/kotlin/com/apollographql/cache/normalized/sql/SqlNormalizedCacheTest.kt b/normalized-cache-sqlite/src/commonTest/kotlin/com/apollographql/cache/normalized/sql/SqlNormalizedCacheTest.kt index 64b4285b..013d0691 100644 --- a/normalized-cache-sqlite/src/commonTest/kotlin/com/apollographql/cache/normalized/sql/SqlNormalizedCacheTest.kt +++ b/normalized-cache-sqlite/src/commonTest/kotlin/com/apollographql/cache/normalized/sql/SqlNormalizedCacheTest.kt @@ -80,6 +80,7 @@ class SqlNormalizedCacheTest { cache.merge( record = Record( key = STANDARD_KEY, + type = "Type", fields = mapOf( "fieldKey" to "valueUpdated", "newFieldKey" to true, @@ -100,6 +101,7 @@ class SqlNormalizedCacheTest { cache.merge( record = Record( key = STANDARD_KEY, + type = "Type", fields = mapOf( "fieldKey" to "valueUpdated", "newFieldKey" to true, @@ -127,6 +129,7 @@ class SqlNormalizedCacheTest { cache.merge( record = Record( key = STANDARD_KEY, + type = "Type", fields = emptyMap(), ), cacheHeaders = CacheHeaders.builder().addHeader(ApolloCacheHeaders.DO_NOT_STORE, "true").build(), @@ -141,6 +144,7 @@ class SqlNormalizedCacheTest { val changedKeys = cache.merge( record = Record( key = STANDARD_KEY, + type = "Type", fields = mapOf( "fieldKey" to "valueUpdated", "newFieldKey" to true, @@ -162,6 +166,7 @@ class SqlNormalizedCacheTest { cache.merge( record = Record( key = STANDARD_KEY, + type = "Type", fields = mapOf( "fieldKey" to "valueUpdated", "newFieldKey" to true, @@ -192,6 +197,7 @@ class SqlNormalizedCacheTest { badCache.merge( record = Record( key = STANDARD_KEY, + type = "Type", fields = mapOf( "fieldKey" to "valueUpdated", "newFieldKey" to true, @@ -210,6 +216,7 @@ class SqlNormalizedCacheTest { cache.merge( record = Record( key = CacheKey("selfRefKey"), + type = "Type", fields = mapOf( "field1" to "value1", "selfRef" to CacheKey("selfRefKey"), @@ -232,6 +239,7 @@ class SqlNormalizedCacheTest { cache.merge( record = Record( key = CacheKey("key1"), + type = "Type", fields = mapOf( "field1" to "value1", "refToKey2" to CacheKey("key2"), @@ -244,6 +252,7 @@ class SqlNormalizedCacheTest { cache.merge( record = Record( key = CacheKey("key2"), + type = "Type", fields = mapOf( "field1" to "value2", "refToKey1" to CacheKey("key1"), @@ -304,6 +313,7 @@ class SqlNormalizedCacheTest { cache.merge( record = Record( key = key, + type = "Type", fields = mapOf( "field1" to "value1", "field2" to "value2", diff --git a/normalized-cache-sqlite/src/commonTest/kotlin/com/apollographql/cache/normalized/sql/TrimTest.kt b/normalized-cache-sqlite/src/commonTest/kotlin/com/apollographql/cache/normalized/sql/TrimTest.kt index c224136a..8e789c57 100644 --- a/normalized-cache-sqlite/src/commonTest/kotlin/com/apollographql/cache/normalized/sql/TrimTest.kt +++ b/normalized-cache-sqlite/src/commonTest/kotlin/com/apollographql/cache/normalized/sql/TrimTest.kt @@ -19,6 +19,7 @@ class TrimTest { val oldRecord = Record( key = CacheKey("old"), + type = "Type", fields = mapOf("key" to "value"), mutationId = null, metadata = emptyMap() @@ -28,6 +29,7 @@ class TrimTest { val newRecords = 0.until(2 * 1024).map { Record( key = CacheKey("new$it"), + type = "Type", fields = mapOf("key" to largeString), mutationId = null, metadata = emptyMap() diff --git a/normalized-cache/api/normalized-cache.api b/normalized-cache/api/normalized-cache.api index b6eb8c96..97a771e4 100644 --- a/normalized-cache/api/normalized-cache.api +++ b/normalized-cache/api/normalized-cache.api @@ -11,6 +11,7 @@ public abstract interface class com/apollographql/cache/normalized/ApolloStore { public abstract fun readOperation (Lcom/apollographql/apollo/api/Operation;Lcom/apollographql/apollo/api/CustomScalarAdapters;Lcom/apollographql/cache/normalized/api/CacheHeaders;)Lcom/apollographql/apollo/api/ApolloResponse; public abstract fun remove (Ljava/util/List;Z)I public abstract fun remove-eNSUWrY (Ljava/lang/String;Z)Z + public abstract fun removeByTypes (Ljava/util/List;)I public abstract fun rollbackOptimisticUpdates (Ljava/util/UUID;)Ljava/util/Set; public abstract fun trim (JF)J public abstract fun writeFragment-1qdIjGk (Lcom/apollographql/apollo/api/Fragment;Ljava/lang/String;Lcom/apollographql/apollo/api/Fragment$Data;Lcom/apollographql/apollo/api/CustomScalarAdapters;Lcom/apollographql/cache/normalized/api/CacheHeaders;)Ljava/util/Set; @@ -202,6 +203,7 @@ public final class com/apollographql/cache/normalized/SimpleApolloStore { public static synthetic fun remove$default (Lcom/apollographql/cache/normalized/SimpleApolloStore;Ljava/util/List;ZILjava/lang/Object;)I public final fun remove-eNSUWrY (Ljava/lang/String;Z)Z public static synthetic fun remove-eNSUWrY$default (Lcom/apollographql/cache/normalized/SimpleApolloStore;Ljava/lang/String;ZILjava/lang/Object;)Z + public final fun removeByTypes (Ljava/util/List;)I public final fun rollbackOptimisticUpdates (Ljava/util/UUID;)Ljava/util/Set; public final fun trim (JF)J public static synthetic fun trim$default (Lcom/apollographql/cache/normalized/SimpleApolloStore;JFILjava/lang/Object;)J @@ -495,6 +497,7 @@ public abstract interface class com/apollographql/cache/normalized/api/Normalize public static fun prettifyDump (Ljava/util/Map;)Ljava/lang/String; public abstract fun remove (Ljava/util/Collection;Z)I public abstract fun remove-eNSUWrY (Ljava/lang/String;Z)Z + public abstract fun removeByTypes (Ljava/util/Collection;)I public abstract fun trim (JF)J } @@ -520,8 +523,8 @@ public abstract interface class com/apollographql/cache/normalized/api/ReadOnlyN public final class com/apollographql/cache/normalized/api/Record : java/util/Map, kotlin/jvm/internal/markers/KMappedMarker { public static final field Companion Lcom/apollographql/cache/normalized/api/Record$Companion; - public synthetic fun (Ljava/lang/String;Ljava/util/Map;Ljava/util/UUID;Ljava/util/Map;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public synthetic fun (Ljava/lang/String;Ljava/util/Map;Ljava/util/UUID;Ljava/util/Map;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Ljava/util/UUID;Ljava/util/Map;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Ljava/util/UUID;Ljava/util/Map;Lkotlin/jvm/internal/DefaultConstructorMarker;)V public fun clear ()V public synthetic fun compute (Ljava/lang/Object;Ljava/util/function/BiFunction;)Ljava/lang/Object; public fun compute (Ljava/lang/String;Ljava/util/function/BiFunction;)Ljava/lang/Object; @@ -544,6 +547,7 @@ public final class com/apollographql/cache/normalized/api/Record : java/util/Map public final fun getMutationId ()Ljava/util/UUID; public fun getSize ()I public final fun getSizeInBytes ()I + public final fun getType ()Ljava/lang/String; public fun getValues ()Ljava/util/Collection; public fun isEmpty ()Z public final fun keySet ()Ljava/util/Set; @@ -634,6 +638,7 @@ public final class com/apollographql/cache/normalized/memory/MemoryCache : com/a public fun merge (Ljava/util/Collection;Lcom/apollographql/cache/normalized/api/CacheHeaders;Lcom/apollographql/cache/normalized/api/RecordMerger;)Ljava/util/Set; public fun remove (Ljava/util/Collection;Z)I public fun remove-eNSUWrY (Ljava/lang/String;Z)Z + public fun removeByTypes (Ljava/util/Collection;)I public fun trim (JF)J } diff --git a/normalized-cache/api/normalized-cache.klib.api b/normalized-cache/api/normalized-cache.klib.api index e119a291..ad720cf2 100644 --- a/normalized-cache/api/normalized-cache.klib.api +++ b/normalized-cache/api/normalized-cache.klib.api @@ -59,6 +59,7 @@ abstract interface com.apollographql.cache.normalized.api/NormalizedCache : com. abstract fun merge(kotlin.collections/Collection, com.apollographql.cache.normalized.api/CacheHeaders, com.apollographql.cache.normalized.api/RecordMerger): kotlin.collections/Set // com.apollographql.cache.normalized.api/NormalizedCache.merge|merge(kotlin.collections.Collection;com.apollographql.cache.normalized.api.CacheHeaders;com.apollographql.cache.normalized.api.RecordMerger){}[0] abstract fun remove(com.apollographql.cache.normalized.api/CacheKey, kotlin/Boolean): kotlin/Boolean // com.apollographql.cache.normalized.api/NormalizedCache.remove|remove(com.apollographql.cache.normalized.api.CacheKey;kotlin.Boolean){}[0] abstract fun remove(kotlin.collections/Collection, kotlin/Boolean): kotlin/Int // com.apollographql.cache.normalized.api/NormalizedCache.remove|remove(kotlin.collections.Collection;kotlin.Boolean){}[0] + abstract fun removeByTypes(kotlin.collections/Collection): kotlin/Int // com.apollographql.cache.normalized.api/NormalizedCache.removeByTypes|removeByTypes(kotlin.collections.Collection){}[0] open fun trim(kotlin/Long, kotlin/Float = ...): kotlin/Long // com.apollographql.cache.normalized.api/NormalizedCache.trim|trim(kotlin.Long;kotlin.Float){}[0] final object Companion { // com.apollographql.cache.normalized.api/NormalizedCache.Companion|null[0] @@ -94,6 +95,7 @@ abstract interface com.apollographql.cache.normalized/ApolloStore { // com.apoll abstract fun dump(): kotlin.collections/Map, kotlin.collections/Map> // com.apollographql.cache.normalized/ApolloStore.dump|dump(){}[0] abstract fun remove(com.apollographql.cache.normalized.api/CacheKey, kotlin/Boolean = ...): kotlin/Boolean // com.apollographql.cache.normalized/ApolloStore.remove|remove(com.apollographql.cache.normalized.api.CacheKey;kotlin.Boolean){}[0] abstract fun remove(kotlin.collections/List, kotlin/Boolean = ...): kotlin/Int // com.apollographql.cache.normalized/ApolloStore.remove|remove(kotlin.collections.List;kotlin.Boolean){}[0] + abstract fun removeByTypes(kotlin.collections/List): kotlin/Int // com.apollographql.cache.normalized/ApolloStore.removeByTypes|removeByTypes(kotlin.collections.List){}[0] abstract fun rollbackOptimisticUpdates(com.benasher44.uuid/Uuid): kotlin.collections/Set // com.apollographql.cache.normalized/ApolloStore.rollbackOptimisticUpdates|rollbackOptimisticUpdates(com.benasher44.uuid.Uuid){}[0] abstract fun trim(kotlin/Long, kotlin/Float = ...): kotlin/Long // com.apollographql.cache.normalized/ApolloStore.trim|trim(kotlin.Long;kotlin.Float){}[0] abstract suspend fun publish(kotlin.collections/Set) // com.apollographql.cache.normalized/ApolloStore.publish|publish(kotlin.collections.Set){}[0] @@ -305,7 +307,7 @@ final class com.apollographql.cache.normalized.api/MetadataGeneratorContext { // } final class com.apollographql.cache.normalized.api/Record : kotlin.collections/Map { // com.apollographql.cache.normalized.api/Record|null[0] - constructor (com.apollographql.cache.normalized.api/CacheKey, kotlin.collections/Map, com.benasher44.uuid/Uuid? = ..., kotlin.collections/Map> = ...) // com.apollographql.cache.normalized.api/Record.|(com.apollographql.cache.normalized.api.CacheKey;kotlin.collections.Map;com.benasher44.uuid.Uuid?;kotlin.collections.Map>){}[0] + constructor (com.apollographql.cache.normalized.api/CacheKey, kotlin/String, kotlin.collections/Map, com.benasher44.uuid/Uuid? = ..., kotlin.collections/Map> = ...) // com.apollographql.cache.normalized.api/Record.|(com.apollographql.cache.normalized.api.CacheKey;kotlin.String;kotlin.collections.Map;com.benasher44.uuid.Uuid?;kotlin.collections.Map>){}[0] final val entries // com.apollographql.cache.normalized.api/Record.entries|{}entries[0] final fun (): kotlin.collections/Set> // com.apollographql.cache.normalized.api/Record.entries.|(){}[0] @@ -323,6 +325,8 @@ final class com.apollographql.cache.normalized.api/Record : kotlin.collections/M final fun (): kotlin/Int // com.apollographql.cache.normalized.api/Record.size.|(){}[0] final val sizeInBytes // com.apollographql.cache.normalized.api/Record.sizeInBytes|{}sizeInBytes[0] final fun (): kotlin/Int // com.apollographql.cache.normalized.api/Record.sizeInBytes.|(){}[0] + final val type // com.apollographql.cache.normalized.api/Record.type|{}type[0] + final fun (): kotlin/String // com.apollographql.cache.normalized.api/Record.type.|(){}[0] final val values // com.apollographql.cache.normalized.api/Record.values|{}values[0] final fun (): kotlin.collections/Collection // com.apollographql.cache.normalized.api/Record.values.|(){}[0] @@ -392,6 +396,7 @@ final class com.apollographql.cache.normalized.memory/MemoryCache : com.apollogr final fun merge(kotlin.collections/Collection, com.apollographql.cache.normalized.api/CacheHeaders, com.apollographql.cache.normalized.api/RecordMerger): kotlin.collections/Set // com.apollographql.cache.normalized.memory/MemoryCache.merge|merge(kotlin.collections.Collection;com.apollographql.cache.normalized.api.CacheHeaders;com.apollographql.cache.normalized.api.RecordMerger){}[0] final fun remove(com.apollographql.cache.normalized.api/CacheKey, kotlin/Boolean): kotlin/Boolean // com.apollographql.cache.normalized.memory/MemoryCache.remove|remove(com.apollographql.cache.normalized.api.CacheKey;kotlin.Boolean){}[0] final fun remove(kotlin.collections/Collection, kotlin/Boolean): kotlin/Int // com.apollographql.cache.normalized.memory/MemoryCache.remove|remove(kotlin.collections.Collection;kotlin.Boolean){}[0] + final fun removeByTypes(kotlin.collections/Collection): kotlin/Int // com.apollographql.cache.normalized.memory/MemoryCache.removeByTypes|removeByTypes(kotlin.collections.Collection){}[0] final fun trim(kotlin/Long, kotlin/Float): kotlin/Long // com.apollographql.cache.normalized.memory/MemoryCache.trim|trim(kotlin.Long;kotlin.Float){}[0] } @@ -490,6 +495,7 @@ final class com.apollographql.cache.normalized/SimpleApolloStore { // com.apollo final fun dump(): kotlin.collections/Map, kotlin.collections/Map> // com.apollographql.cache.normalized/SimpleApolloStore.dump|dump(){}[0] final fun remove(com.apollographql.cache.normalized.api/CacheKey, kotlin/Boolean = ...): kotlin/Boolean // com.apollographql.cache.normalized/SimpleApolloStore.remove|remove(com.apollographql.cache.normalized.api.CacheKey;kotlin.Boolean){}[0] final fun remove(kotlin.collections/List, kotlin/Boolean = ...): kotlin/Int // com.apollographql.cache.normalized/SimpleApolloStore.remove|remove(kotlin.collections.List;kotlin.Boolean){}[0] + final fun removeByTypes(kotlin.collections/List): kotlin/Int // com.apollographql.cache.normalized/SimpleApolloStore.removeByTypes|removeByTypes(kotlin.collections.List){}[0] final fun rollbackOptimisticUpdates(com.benasher44.uuid/Uuid): kotlin.collections/Set // com.apollographql.cache.normalized/SimpleApolloStore.rollbackOptimisticUpdates|rollbackOptimisticUpdates(com.benasher44.uuid.Uuid){}[0] final fun trim(kotlin/Long, kotlin/Float = ...): kotlin/Long // com.apollographql.cache.normalized/SimpleApolloStore.trim|trim(kotlin.Long;kotlin.Float){}[0] final suspend fun publish(kotlin.collections/Set) // com.apollographql.cache.normalized/SimpleApolloStore.publish|publish(kotlin.collections.Set){}[0] diff --git a/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/ApolloStore.kt b/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/ApolloStore.kt index 0ece78f2..f6eda0d4 100644 --- a/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/ApolloStore.kt +++ b/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/ApolloStore.kt @@ -241,6 +241,16 @@ interface ApolloStore { */ fun remove(cacheKeys: List, cascade: Boolean = true): Int + /** + * Removes records by their types. + * + * This is a synchronous operation that might block if the underlying cache is doing IO. + * + * @param types the types of the records to remove + * @return the number of records that have been removed + */ + fun removeByTypes(types: List): Int + /** * Trims the store if its size exceeds [maxSizeBytes]. The amount of data to remove is determined by [trimFactor]. * The oldest records are removed according to their updated date. diff --git a/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/GarbageCollection.kt b/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/GarbageCollection.kt index ef670d0c..828f237a 100644 --- a/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/GarbageCollection.kt +++ b/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/GarbageCollection.kt @@ -280,6 +280,7 @@ private operator fun Record.minus(key: String): Record { return Record( key = this.key, fields = this.fields - key, + type = this.type, metadata = this.metadata - key, ) } diff --git a/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/SimpleApolloStore.kt b/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/SimpleApolloStore.kt index 5721dd6f..00d3e597 100644 --- a/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/SimpleApolloStore.kt +++ b/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/SimpleApolloStore.kt @@ -151,6 +151,11 @@ class SimpleApolloStore( */ fun remove(cacheKeys: List, cascade: Boolean = true): Int = apolloStore.remove(cacheKeys, cascade) + /** + * @see ApolloStore.removeByTypes + */ + fun removeByTypes(types: List): Int = apolloStore.removeByTypes(types) + /** * @see ApolloStore.trim */ diff --git a/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/api/NormalizedCache.kt b/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/api/NormalizedCache.kt index cfcf1387..ffa9fed6 100644 --- a/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/api/NormalizedCache.kt +++ b/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/api/NormalizedCache.kt @@ -19,10 +19,10 @@ import kotlin.reflect.KClass */ interface NormalizedCache : ReadOnlyNormalizedCache { /** - * @param record The [Record] to merge. - * @param cacheHeaders The [CacheHeaders] associated with the request which generated this record. - * @param recordMerger The [RecordMerger] to use when merging the record. - * @return A set of record field keys that have changed. This set is returned by [RecordMerger.merge]. + * @param record the [Record] to merge. + * @param cacheHeaders the [CacheHeaders] associated with the request which generated this record. + * @param recordMerger the [RecordMerger] to use when merging the record. + * @return a set of record field keys that have changed. This set is returned by [RecordMerger.merge]. */ fun merge( record: Record, @@ -34,10 +34,10 @@ interface NormalizedCache : ReadOnlyNormalizedCache { * Calls through to [NormalizedCache.merge]. Implementations should override this method * if the underlying storage technology can offer an optimized manner to store multiple records. * - * @param records The collection of Records to merge. - * @param cacheHeaders The [CacheHeaders] associated with the request which generated this record. - * @param recordMerger The [RecordMerger] to use when merging the records. - * @return A set of record field keys that have changed. This set is returned by [RecordMerger.merge]. + * @param records the collection of Records to merge. + * @param cacheHeaders the [CacheHeaders] associated with the request which generated this record. + * @param recordMerger the [RecordMerger] to use when merging the records. + * @return a set of record field keys that have changed. This set is returned by [RecordMerger.merge]. */ fun merge( records: Collection, @@ -52,11 +52,11 @@ interface NormalizedCache : ReadOnlyNormalizedCache { fun clearAll() /** - * Remove a record and potentially its referenced records from this cache and all chained caches + * Removes a record and potentially its referenced records from this cache and all chained caches. * - * @param cacheKey of record to be removed - * @param cascade remove referenced records if true - * @return `true` if at least one record was successfully removed, `false` otherwise + * @param cacheKey the key of the record to remove. + * @param cascade whether to remove referenced records. + * @return `true` if at least one record was successfully removed, `false` otherwise. */ fun remove(cacheKey: CacheKey, cascade: Boolean): Boolean @@ -64,12 +64,21 @@ interface NormalizedCache : ReadOnlyNormalizedCache { * Calls through to [NormalizedCache.remove]. Implementations should override this method * if the underlying storage technology can offer an optimized manner to remove multiple records. * - * @param cacheKeys of records to be removed - * @param cascade remove referenced records if true - * @return the number of records removed + * @param cacheKeys the keys of the records to remove. + * @param cascade whether to remove referenced records. + * @return the number of removed records. */ fun remove(cacheKeys: Collection, cascade: Boolean): Int + /** + * Removes records by types. + * + * @param types the types of the records to remove. + * @param cascade whether to remove referenced records. + * @return the number of removed records. + */ + fun removeByTypes(types: Collection): Int + /** * Trims the cache if its size exceeds [maxSizeBytes]. The amount of data to remove is determined by [trimFactor]. * The oldest records are removed according to their updated date. diff --git a/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/api/Record.kt b/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/api/Record.kt index a6ee7c94..e9157a73 100644 --- a/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/api/Record.kt +++ b/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/api/Record.kt @@ -11,6 +11,7 @@ import com.benasher44.uuid.Uuid */ class Record( val key: CacheKey, + val type: String, val fields: Map, val mutationId: Uuid? = null, @@ -84,6 +85,7 @@ fun Record.withDates(receivedDate: String?, expirationDate: String?): Record { return Record( key = key, fields = fields, + type = type, mutationId = mutationId, metadata = metadata + fields.mapValues { (key, _) -> metadata[key].orEmpty() + buildMap { diff --git a/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/api/RecordMerger.kt b/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/api/RecordMerger.kt index 6808b32c..6d62050b 100644 --- a/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/api/RecordMerger.kt +++ b/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/api/RecordMerger.kt @@ -47,6 +47,7 @@ object DefaultRecordMerger : RecordMerger { return Record( key = existing.key, + type = incoming.type, fields = mergedFields, mutationId = incoming.mutationId, metadata = existing.metadata.mergedWith(incoming.metadata), @@ -128,6 +129,7 @@ class FieldRecordMerger(private val fieldMerger: FieldMerger) : RecordMerger { return Record( key = existing.key, + type = incoming.type, fields = mergedFields, mutationId = incoming.mutationId, metadata = mergedMetadata, diff --git a/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/internal/CacheBatchReader.kt b/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/internal/CacheBatchReader.kt index ab79ee6d..19e5ee6a 100644 --- a/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/internal/CacheBatchReader.kt +++ b/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/internal/CacheBatchReader.kt @@ -124,7 +124,7 @@ internal class CacheBatchReader( if (record == null) { if (pendingReference.key.isRootKey()) { // This happens the very first time we read the cache - record = Record(pendingReference.key, emptyMap()) + record = Record(pendingReference.key, "Query", emptyMap()) } else { if (returnPartialResponses) { data[pendingReference.path] = @@ -324,8 +324,7 @@ internal class CacheBatchReader( .build() } - @Suppress("UNCHECKED_CAST") - internal fun Any?.hasErrors(): Boolean { + private fun Any?.hasErrors(): Boolean { val queue = ArrayDeque() queue.add(this) while (queue.isNotEmpty()) { diff --git a/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/internal/DefaultApolloStore.kt b/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/internal/DefaultApolloStore.kt index d4e4e99b..cce82ba9 100644 --- a/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/internal/DefaultApolloStore.kt +++ b/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/internal/DefaultApolloStore.kt @@ -104,6 +104,10 @@ internal class DefaultApolloStore( return cache.remove(cacheKeys, cascade) } + override fun removeByTypes(types: List): Int { + return cache.removeByTypes(types) + } + override fun normalize( executable: Executable, dataWithErrors: DataWithErrors, @@ -264,6 +268,7 @@ internal class DefaultApolloStore( ).values.map { record -> Record( key = record.key, + type = record.type, fields = record.fields, mutationId = mutationId ) @@ -291,6 +296,7 @@ internal class DefaultApolloStore( ).values.map { record -> Record( key = record.key, + type = record.type, fields = record.fields, mutationId = mutationId ) diff --git a/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/internal/Normalizer.kt b/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/internal/Normalizer.kt index b15ce5ff..d6ec5a4e 100644 --- a/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/internal/Normalizer.kt +++ b/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/internal/Normalizer.kt @@ -156,6 +156,7 @@ internal class Normalizer( val metadata = fields.mapValues { it.value.metadata }.filterValues { it.isNotEmpty() } val record = Record( key = cacheKey, + type = obj["__typename"] as? String ?: parentType.name, fields = fieldValues, mutationId = null, metadata = metadata, diff --git a/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/internal/OptimisticNormalizedCache.kt b/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/internal/OptimisticNormalizedCache.kt index 880e2dd8..4ee65a8f 100644 --- a/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/internal/OptimisticNormalizedCache.kt +++ b/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/internal/OptimisticNormalizedCache.kt @@ -46,6 +46,10 @@ internal class OptimisticNormalizedCache(private val wrapped: NormalizedCache) : return wrapped.remove(cacheKeys, cascade) + internalRemove(cacheKeys, cascade) } + override fun removeByTypes(types: Collection): Int { + return wrapped.removeByTypes(types) + internalRemove(recordJournals.filterValues { it.current.type in types }.keys, false) + } + override fun trim(maxSizeBytes: Long, trimFactor: Float): Long { return wrapped.trim(maxSizeBytes, trimFactor) } diff --git a/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/memory/MemoryCache.kt b/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/memory/MemoryCache.kt index 41fdaed4..b5d87f12 100644 --- a/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/memory/MemoryCache.kt +++ b/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/memory/MemoryCache.kt @@ -76,8 +76,16 @@ class MemoryCache( override fun remove(cacheKeys: Collection, cascade: Boolean): Int { return lockWrite { - val total = internalRemove(cacheKeys, cascade) - nextCache?.remove(cacheKeys, cascade) + var total = internalRemove(cacheKeys, cascade) + total += nextCache?.remove(cacheKeys, cascade) ?: 0 + total + } + } + + override fun removeByTypes(types: Collection): Int { + return lockWrite { + var total = internalRemove(lruCache.asMap().filterValues { it.type in types }.keys, false) + total += nextCache?.removeByTypes(types) ?: 0 total } } diff --git a/normalized-cache/src/commonTest/kotlin/com/apollographql/cache/normalized/DefaultRecordMergerTest.kt b/normalized-cache/src/commonTest/kotlin/com/apollographql/cache/normalized/DefaultRecordMergerTest.kt index f303cd1a..50685b6e 100644 --- a/normalized-cache/src/commonTest/kotlin/com/apollographql/cache/normalized/DefaultRecordMergerTest.kt +++ b/normalized-cache/src/commonTest/kotlin/com/apollographql/cache/normalized/DefaultRecordMergerTest.kt @@ -13,6 +13,7 @@ class DefaultRecordMergerTest { fun mergeMetaData() { val existing = Record( key = CacheKey("key"), + type = "Type", fields = mapOf( "field1" to "value1", "field2" to "value2" @@ -32,6 +33,7 @@ class DefaultRecordMergerTest { val incoming = Record( key = CacheKey("key"), + type = "Type", fields = mapOf( "field1" to "value1.incoming", "field3" to "value3", @@ -53,6 +55,7 @@ class DefaultRecordMergerTest { val expected = Record( key = CacheKey("key"), + type = "Type", fields = mapOf( "field1" to "value1.incoming", "field2" to "value2", diff --git a/normalized-cache/src/commonTest/kotlin/com/apollographql/cache/normalized/MemoryCacheTest.kt b/normalized-cache/src/commonTest/kotlin/com/apollographql/cache/normalized/MemoryCacheTest.kt index b2fbb5b1..eafa3feb 100644 --- a/normalized-cache/src/commonTest/kotlin/com/apollographql/cache/normalized/MemoryCacheTest.kt +++ b/normalized-cache/src/commonTest/kotlin/com/apollographql/cache/normalized/MemoryCacheTest.kt @@ -98,6 +98,7 @@ class MemoryCacheTest { val updatedRestRecord1 = Record( fields = testRecord1.fields.plus("field3" to "value3"), key = testRecord1.key, + type = "Type", mutationId = testRecord1.mutationId ) @@ -224,6 +225,7 @@ class MemoryCacheTest { val record1 = Record( key = CacheKey("id_1"), + type = "Type", fields = mapOf( "a" to "stringValueA", "b" to "stringValueB" @@ -232,6 +234,7 @@ class MemoryCacheTest { val record2 = Record( key = CacheKey("id_2"), + type = "Type", fields = mapOf( "a" to CacheKey("id_1"), ) @@ -250,6 +253,7 @@ class MemoryCacheTest { val record1 = Record( key = CacheKey("id_1"), + type = "Type", fields = mapOf( "a" to "stringValueA", "b" to "stringValueB" @@ -258,6 +262,7 @@ class MemoryCacheTest { val record2 = Record( key = CacheKey("id_2"), + type = "Type", fields = mapOf( "a" to CacheKey("id_1"), ) @@ -287,6 +292,7 @@ class MemoryCacheTest { private fun createTestRecord(id: String): Record { return Record( key = CacheKey("key$id"), + type = "Type", fields = mapOf( "field1" to "stringValueA$id", "field2" to "stringValueB$id" diff --git a/normalized-cache/src/commonTest/kotlin/com/apollographql/cache/normalized/RecordWeigherTest.kt b/normalized-cache/src/commonTest/kotlin/com/apollographql/cache/normalized/RecordWeigherTest.kt index 51cac0df..efbf78c7 100644 --- a/normalized-cache/src/commonTest/kotlin/com/apollographql/cache/normalized/RecordWeigherTest.kt +++ b/normalized-cache/src/commonTest/kotlin/com/apollographql/cache/normalized/RecordWeigherTest.kt @@ -20,6 +20,7 @@ class RecordWeigherTest { val expectedScalarList = listOf("scalarOne", "scalarTwo") val record = Record( key = CacheKey("root"), + type = "Type", fields = mapOf( "double" to expectedDouble, "string" to expectedStringValue, diff --git a/tests/migration/src/commonTest/kotlin/MigrationTest.kt b/tests/migration/src/commonTest/kotlin/MigrationTest.kt index eeb6c37d..87a2a1c0 100644 --- a/tests/migration/src/commonTest/kotlin/MigrationTest.kt +++ b/tests/migration/src/commonTest/kotlin/MigrationTest.kt @@ -170,6 +170,7 @@ private fun LegacyNormalizedCache.allRecords(): List { private fun LegacyRecord.toRecord(): Record = Record( key = CacheKey(key), + type = "Unknown", fields = fields.mapValues { (_, value) -> value.toRecordValue() }, mutationId = mutationId ) diff --git a/tests/normalization-tests/src/concurrentTest/kotlin/com/example/SqlNormalizationTest.kt b/tests/normalization-tests/src/concurrentTest/kotlin/com/example/SqlNormalizationTest.kt index 72a5d1b6..22885bfb 100644 --- a/tests/normalization-tests/src/concurrentTest/kotlin/com/example/SqlNormalizationTest.kt +++ b/tests/normalization-tests/src/concurrentTest/kotlin/com/example/SqlNormalizationTest.kt @@ -4,10 +4,10 @@ import com.apollographql.apollo.ApolloClient import com.apollographql.cache.normalized.FetchPolicy import com.apollographql.cache.normalized.allRecords import com.apollographql.cache.normalized.api.CacheKey -import com.apollographql.cache.normalized.apolloStore import com.apollographql.cache.normalized.fetchPolicy import com.apollographql.cache.normalized.normalizedCache import com.apollographql.cache.normalized.sql.SqlNormalizedCacheFactory +import com.apollographql.cache.normalized.store import com.apollographql.cache.normalized.testing.append import com.apollographql.cache.normalized.testing.runTest import com.apollographql.mockserver.MockServer @@ -25,7 +25,7 @@ class SqlNormalizationTest { .normalizedCache(SqlNormalizedCacheFactory()) .build() - apolloClient.apolloStore.clearAll() + apolloClient.store.clearAll() mockserver.enqueueString( // language=JSON """ @@ -55,7 +55,7 @@ class SqlNormalizationTest { ) apolloClient.mutation(CreateUserMutation("John")).fetchPolicy(FetchPolicy.NetworkOnly).execute() - apolloClient.apolloStore.accessCache { normalizedCache -> + apolloClient.store.accessCache { normalizedCache -> assertContentEquals( listOf( CacheKey.MUTATION_ROOT, diff --git a/tests/normalized-cache/src/commonTest/kotlin/MemoryCacheTest.kt b/tests/normalized-cache/src/commonTest/kotlin/MemoryCacheTest.kt index aa78d58a..f1afb7ad 100644 --- a/tests/normalized-cache/src/commonTest/kotlin/MemoryCacheTest.kt +++ b/tests/normalized-cache/src/commonTest/kotlin/MemoryCacheTest.kt @@ -16,6 +16,7 @@ class MemoryCacheTest { fun testDoesNotExpireBeforeMillis() = runTest { val record = Record( key = CacheKey("key"), + type = "Type", fields = mapOf( "field" to "value" ) diff --git a/tests/normalized-cache/src/commonTest/kotlin/NormalizerTest.kt b/tests/normalized-cache/src/commonTest/kotlin/NormalizerTest.kt index 2b411063..204e5d0d 100644 --- a/tests/normalized-cache/src/commonTest/kotlin/NormalizerTest.kt +++ b/tests/normalized-cache/src/commonTest/kotlin/NormalizerTest.kt @@ -60,12 +60,14 @@ class NormalizerTest { fun testMergeNull() { val record = Record( key = CacheKey("Key"), + type = "Type", fields = mapOf("field1" to "value1"), ) normalizedCache.merge(listOf(record), CacheHeaders.NONE, DefaultRecordMerger) val newRecord = Record( key = CacheKey("Key"), + type = "Type", fields = mapOf("field2" to null), ) @@ -268,6 +270,17 @@ class NormalizerTest { assertTrue(records[CacheKey("hero({\"episode\":\"EMPIRE\"})").append("friendsConnection")]!!.isEmpty()) } + @Test + fun testTypes() { + val records = records(HeroParentTypeDependentFieldQuery(Episode.JEDI), "HeroParentTypeDependentFieldHumanResponse.json") + assertEquals("Query", records[CacheKey.QUERY_ROOT]?.type) + assertTrue(records.values.filter { it["name"] == "Han Solo" }.all { it.type == "Human" }) + assertTrue(records.values.filter { it["name"] == "Leia Organa" }.all { it.type == "Human" }) + assertTrue(records.values.filter { it["name"] == "Luke Skywalker" }.all { it.type == "Human" }) + assertTrue(records.values.filter { it["name"] == "C-3PO" }.all { it.type == "Droid" }) + assertTrue(records.values.filter { it["name"] == "R2-D2" }.all { it.type == "Droid" }) + } + companion object { internal fun records( operation: Operation, diff --git a/tests/normalized-cache/src/commonTest/kotlin/ThreadTests.kt b/tests/normalized-cache/src/commonTest/kotlin/ThreadTests.kt index 684c1c88..cd7f0f91 100644 --- a/tests/normalized-cache/src/commonTest/kotlin/ThreadTests.kt +++ b/tests/normalized-cache/src/commonTest/kotlin/ThreadTests.kt @@ -62,6 +62,13 @@ class ThreadTests { return delegate.remove(cacheKeys, cascade) } + override fun removeByTypes(types: Collection): Int { + check(currentThreadId() != mainThreadId) { + "Cache access on main thread" + } + return delegate.removeByTypes(types) + } + override fun loadRecord(key: CacheKey, cacheHeaders: CacheHeaders): Record? { check(currentThreadId() != mainThreadId) { "Cache access on main thread" diff --git a/tests/partial-results/src/commonTest/kotlin/test/CachePartialResultTest.kt b/tests/partial-results/src/commonTest/kotlin/test/CachePartialResultTest.kt index 2b7f3f3f..1ec05e72 100644 --- a/tests/partial-results/src/commonTest/kotlin/test/CachePartialResultTest.kt +++ b/tests/partial-results/src/commonTest/kotlin/test/CachePartialResultTest.kt @@ -544,7 +544,7 @@ class CachePartialResultTest { apolloClient.store.accessCache { cache -> val record = cache.loadRecord(CacheKey("User:1"), CacheHeaders.NONE)!! cache.remove(CacheKey("User:1"), false) - cache.merge(Record(record.key, record.fields - "category"), CacheHeaders.NONE, DefaultRecordMerger) + cache.merge(Record(record.key, "Type", record.fields - "category"), CacheHeaders.NONE, DefaultRecordMerger) } val cacheMissResult = apolloClient.query(UserByCategoryQuery(Category(2, "Second"))) .fetchPolicyInterceptor(PartialCacheOnlyInterceptor) diff --git a/tests/remove-by-types/build.gradle.kts b/tests/remove-by-types/build.gradle.kts new file mode 100644 index 00000000..0d9ef7be --- /dev/null +++ b/tests/remove-by-types/build.gradle.kts @@ -0,0 +1,42 @@ +plugins { + alias(libs.plugins.kotlin.multiplatform) + alias(libs.plugins.apollo) +} + +kotlin { + configureKmp( + withJs = false, + withWasm = false, + withAndroid = false, + withApple = AppleTargets.Host, + ) + + sourceSets { + getByName("commonMain") { + dependencies { + implementation(libs.apollo.runtime) + implementation("com.apollographql.cache:normalized-cache-sqlite") + } + } + + getByName("commonTest") { + dependencies { + implementation("com.apollographql.cache:test-utils") + implementation(libs.apollo.mockserver) + implementation(libs.kotlin.test) + } + } + + getByName("jvmTest") { + dependencies { + implementation(libs.slf4j.nop) + } + } + } +} + +apollo { + service("service") { + packageName.set("test") + } +} diff --git a/tests/remove-by-types/src/commonMain/graphql/operation.graphql b/tests/remove-by-types/src/commonMain/graphql/operation.graphql new file mode 100644 index 00000000..ee32f9ef --- /dev/null +++ b/tests/remove-by-types/src/commonMain/graphql/operation.graphql @@ -0,0 +1,14 @@ +query MediaListQuery { + medias { + id + ... on Image { + width + } + ... on Video { + duration + } + ... on Audio { + sampleRate + } + } +} diff --git a/tests/remove-by-types/src/commonMain/graphql/schema.graphqls b/tests/remove-by-types/src/commonMain/graphql/schema.graphqls new file mode 100644 index 00000000..73a8a367 --- /dev/null +++ b/tests/remove-by-types/src/commonMain/graphql/schema.graphqls @@ -0,0 +1,36 @@ +type Query { + medias: [Media!]! +} + +interface Media { + id: ID! + name: String! + description: String + url: String! +} + +type Image implements Media { + id: ID! + name: String! + description: String + url: String! + width: Int! + height: Int! +} + +type Video implements Media { + id: ID! + name: String! + description: String + url: String! + duration: Int! +} + +type Audio implements Media { + id: ID! + name: String! + description: String + url: String! + duration: Int! + sampleRate: Int! +} diff --git a/tests/remove-by-types/src/commonTest/kotlin/test/RemoveByTypesTest.kt b/tests/remove-by-types/src/commonTest/kotlin/test/RemoveByTypesTest.kt new file mode 100644 index 00000000..5a4e23ea --- /dev/null +++ b/tests/remove-by-types/src/commonTest/kotlin/test/RemoveByTypesTest.kt @@ -0,0 +1,113 @@ +package test + +import com.apollographql.apollo.ApolloClient +import com.apollographql.cache.normalized.ApolloStore +import com.apollographql.cache.normalized.FetchPolicy +import com.apollographql.cache.normalized.allRecords +import com.apollographql.cache.normalized.fetchPolicy +import com.apollographql.cache.normalized.memory.MemoryCacheFactory +import com.apollographql.cache.normalized.sql.SqlNormalizedCacheFactory +import com.apollographql.cache.normalized.store +import com.apollographql.cache.normalized.testing.runTest +import com.apollographql.mockserver.MockServer +import com.apollographql.mockserver.enqueueString +import okio.use +import kotlin.test.Test +import kotlin.test.assertTrue + +class RemoveByTypesTest { + private lateinit var mockServer: MockServer + + private fun setUp() { + mockServer = MockServer() + } + + private fun tearDown() { + mockServer.close() + } + + private val memoryStore = ApolloStore(MemoryCacheFactory()) + + private val sqlStore = ApolloStore(SqlNormalizedCacheFactory()).also { it.clearAll() } + + private val memoryThenSqlStore = ApolloStore(MemoryCacheFactory().chain(SqlNormalizedCacheFactory())).also { it.clearAll() } + + @Test + fun removeByTypesMemory() = runTest(before = { setUp() }, after = { tearDown() }) { + removeByTypes(memoryStore) + } + + @Test + fun removeByTypesSql() = runTest(before = { setUp() }, after = { tearDown() }) { + removeByTypes(sqlStore) + } + + @Test + fun removeByTypesMemoryThenSql() = runTest(before = { setUp() }, after = { tearDown() }) { + removeByTypes(memoryThenSqlStore) + } + + private suspend fun removeByTypes(store: ApolloStore) { + mockServer.enqueueString( + // language=JSON + """ + { + "data": { + "medias": [ + { + "id": "1", + "__typename": "Image", + "width": 1920 + }, + { + "id": "2", + "__typename": "Image", + "width": 1280 + }, + { + "id": "3", + "__typename": "Video", + "duration": 120 + }, + { + "id": "4", + "__typename": "Video", + "duration": 60 + }, + { + "id": "5", + "__typename": "Audio", + "sampleRate": 44100 + }, + { + "id": "6", + "__typename": "Audio", + "sampleRate": 48000 + } + ] + } + } + """ + ) + ApolloClient.Builder() + .serverUrl(mockServer.url()) + .store(store) + .build() + .use { apolloClient -> + apolloClient.query(MediaListQuery()) + .fetchPolicy(FetchPolicy.NetworkOnly) + .execute() + apolloClient.store.accessCache { cache -> + assertTrue(cache.allRecords().any { it.value.type == "Image" }) + assertTrue(cache.allRecords().any { it.value.type == "Video" }) + assertTrue(cache.allRecords().any { it.value.type == "Audio" }) + } + apolloClient.store.removeByTypes(listOf("Image", "Video")) + apolloClient.store.accessCache { cache -> + assertTrue(cache.allRecords().none { it.value.type == "Image" }) + assertTrue(cache.allRecords().none { it.value.type == "Video" }) + assertTrue(cache.allRecords().any { it.value.type == "Audio" }) + } + } + } +}