Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun remove (Ljava/util/Collection;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun remove-7OwBRqc (Ljava/lang/String;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun sizeOfRecord (Lcom/apollographql/cache/normalized/api/Record;)I
public fun trim (JFLkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun remove (Ljava/util/Collection;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun remove-7OwBRqc (Ljava/lang/String;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun sizeOfRecord (Lcom/apollographql/cache/normalized/api/Record;)I
public fun trim (JFLkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ final class com.apollographql.cache.normalized.sql.internal.record/SelectRecords
}

final class com.apollographql.cache.normalized.sql/SqlNormalizedCache : com.apollographql.cache.normalized.api/NormalizedCache { // com.apollographql.cache.normalized.sql/SqlNormalizedCache|null[0]
final fun sizeOfRecord(com.apollographql.cache.normalized.api/Record): kotlin/Int // com.apollographql.cache.normalized.sql/SqlNormalizedCache.sizeOfRecord|sizeOfRecord(com.apollographql.cache.normalized.api.Record){}[0]
final suspend fun clearAll() // com.apollographql.cache.normalized.sql/SqlNormalizedCache.clearAll|clearAll(){}[0]
final suspend fun dump(): kotlin.collections/Map<kotlin.reflect/KClass<*>, kotlin.collections/Map<com.apollographql.cache.normalized.api/CacheKey, com.apollographql.cache.normalized.api/Record>> // com.apollographql.cache.normalized.sql/SqlNormalizedCache.dump|dump(){}[0]
final suspend fun loadRecord(com.apollographql.cache.normalized.api/CacheKey, com.apollographql.cache.normalized.api/CacheHeaders): com.apollographql.cache.normalized.api/Record? // com.apollographql.cache.normalized.sql/SqlNormalizedCache.loadRecord|loadRecord(com.apollographql.cache.normalized.api.CacheKey;com.apollographql.cache.normalized.api.CacheHeaders){}[0]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import com.apollographql.cache.normalized.api.Record
import com.apollographql.cache.normalized.api.RecordMerger
import com.apollographql.cache.normalized.api.RecordMergerContext
import com.apollographql.cache.normalized.api.withDates
import com.apollographql.cache.normalized.api.withSizeInBytes
import com.apollographql.cache.normalized.sql.internal.RecordDatabase
import com.apollographql.cache.normalized.sql.internal.RecordSerializer
import com.apollographql.cache.normalized.sql.internal.parametersMax
import kotlin.reflect.KClass

Expand Down Expand Up @@ -80,7 +82,15 @@ class SqlNormalizedCache internal constructor(

override suspend fun dump(): Map<KClass<*>, Map<CacheKey, Record>> {
recordDatabase.init()
return mapOf(this::class to recordDatabase.selectAllRecords().associateBy { it.key })
return mapOf(
this::class to (recordDatabase.selectAllRecords().associateBy { it.key })
.mapValues { (_, record) -> record.withSizeInBytes(sizeOfRecord(record)) },
)
}

override fun sizeOfRecord(record: Record): Int {
val keySize = record.key.key.length
return keySize + RecordSerializer.serialize(record).size
}

private suspend fun getReferencedKeysRecursively(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,17 @@ internal object RecordSerializer {

in Byte.MIN_VALUE..Byte.MAX_VALUE -> {
writeByte(INT_BYTE)
writeByte(value.toInt())
writeByte(value)
}

in Short.MIN_VALUE..Short.MAX_VALUE -> {
writeByte(INT_SHORT)
writeShort(value.toInt())
writeShort(value)
}

else -> {
writeByte(INT_INT)
writeInt(value.toInt())
writeInt(value)
}
}
}
Expand Down Expand Up @@ -111,7 +111,7 @@ internal object RecordSerializer {

else -> {
writeByte(LONG_LONG)
writeLong(value.toLong())
writeLong(value)
}
}
}
Expand Down Expand Up @@ -146,17 +146,16 @@ internal object RecordSerializer {
}
}

is Int -> {
_writeInt(value)
}

is Long -> {
_writeLong(value)
}

is Double -> {
writeByte(DOUBLE)
writeLong(value.toBits())
is Number -> {
// Using `is` on numbers always return true in JS, so we use the class instead
when (value::class) {
Int::class -> _writeInt(value as Int)
Long::class -> _writeLong(value as Long)
else -> {
writeByte(DOUBLE)
writeLong((value as Double).toBits())
}
}
}

is JsonNumber -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import app.cash.sqldelight.db.QueryResult
import app.cash.sqldelight.db.SqlCursor
import app.cash.sqldelight.db.SqlDriver
import app.cash.sqldelight.db.SqlPreparedStatement
import com.apollographql.apollo.api.json.JsonNumber
import com.apollographql.apollo.exception.apolloExceptionHandler
import com.apollographql.cache.normalized.api.ApolloCacheHeaders
import com.apollographql.cache.normalized.api.CacheHeaders
Expand Down Expand Up @@ -258,6 +259,35 @@ class SqlNormalizedCacheTest {
assertNull(cache.loadRecord(CacheKey("key2"), CacheHeaders.NONE))
}

@Test
fun testSizeOfRecord() = runTest {
val expectedDouble = 1.23
val expectedLongValue = Long.MAX_VALUE
val expectedStringValue = "StringValue"
val expectedBooleanValue = true
val expectedNumberValue = JsonNumber("10")
val expectedCacheKey = CacheKey("foo")
val expectedCacheKeyList = listOf(CacheKey("bar"), CacheKey("baz"))
val expectedScalarList = listOf("scalarOne", "scalarTwo")
val record = Record(
key = CacheKey("root"),
fields = mapOf(
"double" to expectedDouble,
"string" to expectedStringValue,
"boolean" to expectedBooleanValue,
"long" to expectedLongValue,
"number" to expectedNumberValue,
"cacheReference" to expectedCacheKey,
"scalarList" to expectedScalarList,
"referenceList" to expectedCacheKeyList,
),
)

val normalizedCache = SqlNormalizedCacheFactory().create().apply { clearAll() }
val sizeOfRecord = normalizedCache.sizeOfRecord(record)
assertEquals(157, sizeOfRecord)
}

private val BadDriver = object : SqlDriver {
override fun close() {
throw IllegalStateException("bad cache")
Expand Down
10 changes: 9 additions & 1 deletion normalized-cache/api/normalized-cache.api
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,7 @@ public final class com/apollographql/cache/normalized/api/NormalizedCache$Compan
}

public final class com/apollographql/cache/normalized/api/NormalizedCache$DefaultImpls {
public static fun sizeOfRecord (Lcom/apollographql/cache/normalized/api/NormalizedCache;Lcom/apollographql/cache/normalized/api/Record;)I
public static fun trim (Lcom/apollographql/cache/normalized/api/NormalizedCache;JFLkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static synthetic fun trim$default (Lcom/apollographql/cache/normalized/api/NormalizedCache;JFLkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
}
Expand All @@ -624,12 +625,17 @@ public abstract interface class com/apollographql/cache/normalized/api/ReadOnlyN
public abstract fun dump (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun loadRecord-7OwBRqc (Ljava/lang/String;Lcom/apollographql/cache/normalized/api/CacheHeaders;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun loadRecords (Ljava/util/Collection;Lcom/apollographql/cache/normalized/api/CacheHeaders;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun sizeOfRecord (Lcom/apollographql/cache/normalized/api/Record;)I
}

public final class com/apollographql/cache/normalized/api/ReadOnlyNormalizedCache$DefaultImpls {
public static fun sizeOfRecord (Lcom/apollographql/cache/normalized/api/ReadOnlyNormalizedCache;Lcom/apollographql/cache/normalized/api/Record;)I
}

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 <init> (Ljava/lang/String;Ljava/util/Map;Ljava/util/UUID;Ljava/util/Map;IILkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/util/Map;Ljava/util/UUID;Ljava/util/Map;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (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;
Expand Down Expand Up @@ -683,6 +689,7 @@ public final class com/apollographql/cache/normalized/api/RecordKt {
public static final fun expirationDate (Lcom/apollographql/cache/normalized/api/Record;Ljava/lang/String;)Ljava/lang/Long;
public static final fun receivedDate (Lcom/apollographql/cache/normalized/api/Record;Ljava/lang/String;)Ljava/lang/Long;
public static final fun withDates (Lcom/apollographql/cache/normalized/api/Record;Ljava/lang/String;Ljava/lang/String;)Lcom/apollographql/cache/normalized/api/Record;
public static final fun withSizeInBytes (Lcom/apollographql/cache/normalized/api/Record;I)Lcom/apollographql/cache/normalized/api/Record;
}

public abstract interface class com/apollographql/cache/normalized/api/RecordMerger {
Expand Down Expand Up @@ -756,6 +763,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;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun remove (Ljava/util/Collection;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun remove-7OwBRqc (Ljava/lang/String;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun sizeOfRecord (Lcom/apollographql/cache/normalized/api/Record;)I
public fun trim (JFLkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

Expand Down
5 changes: 4 additions & 1 deletion normalized-cache/api/normalized-cache.klib.api
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ abstract interface com.apollographql.cache.normalized.api/ReadOnlyNormalizedCach
abstract suspend fun dump(): kotlin.collections/Map<kotlin.reflect/KClass<*>, kotlin.collections/Map<com.apollographql.cache.normalized.api/CacheKey, com.apollographql.cache.normalized.api/Record>> // com.apollographql.cache.normalized.api/ReadOnlyNormalizedCache.dump|dump(){}[0]
abstract suspend fun loadRecord(com.apollographql.cache.normalized.api/CacheKey, com.apollographql.cache.normalized.api/CacheHeaders): com.apollographql.cache.normalized.api/Record? // com.apollographql.cache.normalized.api/ReadOnlyNormalizedCache.loadRecord|loadRecord(com.apollographql.cache.normalized.api.CacheKey;com.apollographql.cache.normalized.api.CacheHeaders){}[0]
abstract suspend fun loadRecords(kotlin.collections/Collection<com.apollographql.cache.normalized.api/CacheKey>, com.apollographql.cache.normalized.api/CacheHeaders): kotlin.collections/Collection<com.apollographql.cache.normalized.api/Record> // com.apollographql.cache.normalized.api/ReadOnlyNormalizedCache.loadRecords|loadRecords(kotlin.collections.Collection<com.apollographql.cache.normalized.api.CacheKey>;com.apollographql.cache.normalized.api.CacheHeaders){}[0]
open fun sizeOfRecord(com.apollographql.cache.normalized.api/Record): kotlin/Int // com.apollographql.cache.normalized.api/ReadOnlyNormalizedCache.sizeOfRecord|sizeOfRecord(com.apollographql.cache.normalized.api.Record){}[0]
}

abstract interface com.apollographql.cache.normalized.api/RecordMerger { // com.apollographql.cache.normalized.api/RecordMerger|null[0]
Expand Down Expand Up @@ -318,7 +319,7 @@ final class com.apollographql.cache.normalized.api/MetadataGeneratorContext { //
}

final class com.apollographql.cache.normalized.api/Record : kotlin.collections/Map<kotlin/String, kotlin/Any?> { // com.apollographql.cache.normalized.api/Record|null[0]
constructor <init>(com.apollographql.cache.normalized.api/CacheKey, kotlin.collections/Map<kotlin/String, kotlin/Any?>, com.benasher44.uuid/Uuid? = ..., kotlin.collections/Map<kotlin/String, kotlin.collections/Map<kotlin/String, kotlin/Any?>> = ...) // com.apollographql.cache.normalized.api/Record.<init>|<init>(com.apollographql.cache.normalized.api.CacheKey;kotlin.collections.Map<kotlin.String,kotlin.Any?>;com.benasher44.uuid.Uuid?;kotlin.collections.Map<kotlin.String,kotlin.collections.Map<kotlin.String,kotlin.Any?>>){}[0]
constructor <init>(com.apollographql.cache.normalized.api/CacheKey, kotlin.collections/Map<kotlin/String, kotlin/Any?>, com.benasher44.uuid/Uuid? = ..., kotlin.collections/Map<kotlin/String, kotlin.collections/Map<kotlin/String, kotlin/Any?>> = ..., kotlin/Int = ...) // com.apollographql.cache.normalized.api/Record.<init>|<init>(com.apollographql.cache.normalized.api.CacheKey;kotlin.collections.Map<kotlin.String,kotlin.Any?>;com.benasher44.uuid.Uuid?;kotlin.collections.Map<kotlin.String,kotlin.collections.Map<kotlin.String,kotlin.Any?>>;kotlin.Int){}[0]

final val entries // com.apollographql.cache.normalized.api/Record.entries|{}entries[0]
final fun <get-entries>(): kotlin.collections/Set<kotlin.collections/Map.Entry<kotlin/String, kotlin/Any?>> // com.apollographql.cache.normalized.api/Record.entries.<get-entries>|<get-entries>(){}[0]
Expand Down Expand Up @@ -400,6 +401,7 @@ final class com.apollographql.cache.normalized.api/TypePolicyCacheKeyGenerator :
final class com.apollographql.cache.normalized.memory/MemoryCache : com.apollographql.cache.normalized.api/NormalizedCache { // com.apollographql.cache.normalized.memory/MemoryCache|null[0]
constructor <init>(com.apollographql.cache.normalized.api/NormalizedCache? = ..., kotlin/Int = ..., kotlin/Long = ...) // com.apollographql.cache.normalized.memory/MemoryCache.<init>|<init>(com.apollographql.cache.normalized.api.NormalizedCache?;kotlin.Int;kotlin.Long){}[0]

final fun sizeOfRecord(com.apollographql.cache.normalized.api/Record): kotlin/Int // com.apollographql.cache.normalized.memory/MemoryCache.sizeOfRecord|sizeOfRecord(com.apollographql.cache.normalized.api.Record){}[0]
final suspend fun clearAll() // com.apollographql.cache.normalized.memory/MemoryCache.clearAll|clearAll(){}[0]
final suspend fun dump(): kotlin.collections/Map<kotlin.reflect/KClass<*>, kotlin.collections/Map<com.apollographql.cache.normalized.api/CacheKey, com.apollographql.cache.normalized.api/Record>> // com.apollographql.cache.normalized.memory/MemoryCache.dump|dump(){}[0]
final suspend fun loadRecord(com.apollographql.cache.normalized.api/CacheKey, com.apollographql.cache.normalized.api/CacheHeaders): com.apollographql.cache.normalized.api/Record? // com.apollographql.cache.normalized.memory/MemoryCache.loadRecord|loadRecord(com.apollographql.cache.normalized.api.CacheKey;com.apollographql.cache.normalized.api.CacheHeaders){}[0]
Expand Down Expand Up @@ -673,6 +675,7 @@ final fun (com.apollographql.apollo/ApolloClient.Builder).com.apollographql.cach
final fun (com.apollographql.cache.normalized.api/Record).com.apollographql.cache.normalized.api/expirationDate(kotlin/String): kotlin/Long? // com.apollographql.cache.normalized.api/expirationDate|[email protected](kotlin.String){}[0]
final fun (com.apollographql.cache.normalized.api/Record).com.apollographql.cache.normalized.api/receivedDate(kotlin/String): kotlin/Long? // com.apollographql.cache.normalized.api/receivedDate|[email protected](kotlin.String){}[0]
final fun (com.apollographql.cache.normalized.api/Record).com.apollographql.cache.normalized.api/withDates(kotlin/String?, kotlin/String?): com.apollographql.cache.normalized.api/Record // com.apollographql.cache.normalized.api/withDates|[email protected](kotlin.String?;kotlin.String?){}[0]
final fun (com.apollographql.cache.normalized.api/Record).com.apollographql.cache.normalized.api/withSizeInBytes(kotlin/Int): com.apollographql.cache.normalized.api/Record // com.apollographql.cache.normalized.api/withSizeInBytes|[email protected](kotlin.Int){}[0]
final fun (com.apollographql.cache.normalized.api/ResolverContext).com.apollographql.cache.normalized.api/getFieldKey(): kotlin/String // com.apollographql.cache.normalized.api/getFieldKey|getFieldKey@com.apollographql.cache.normalized.api.ResolverContext(){}[0]
final fun (kotlin.collections/Collection<com.apollographql.cache.normalized.api/Record>?).com.apollographql.cache.normalized.api/dependentKeys(): kotlin.collections/Set<kotlin/String> // com.apollographql.cache.normalized.api/dependentKeys|[email protected]<com.apollographql.cache.normalized.api.Record>?(){}[0]
final fun (kotlin.collections/Map<com.apollographql.cache.normalized.api/CacheKey, com.apollographql.cache.normalized.api/Record>).com.apollographql.cache.normalized/getReachableCacheKeys(): kotlin.collections/Set<com.apollographql.cache.normalized.api/CacheKey> // com.apollographql.cache.normalized/getReachableCacheKeys|[email protected]<com.apollographql.cache.normalized.api.CacheKey,com.apollographql.cache.normalized.api.Record>(){}[0]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,10 @@ interface ReadOnlyNormalizedCache {
suspend fun loadRecords(keys: Collection<CacheKey>, cacheHeaders: CacheHeaders): Collection<Record>

suspend fun dump(): Map<@JvmSuppressWildcards KClass<*>, Map<CacheKey, Record>>

/**
* Returns the size in bytes of a [Record].
* This is an optional operation that can be implemented by the caches for debug purposes, otherwise it defaults to `-1`, meaning unknown size.
*/
fun sizeOfRecord(record: Record): Int = -1
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package com.apollographql.cache.normalized.api

import com.apollographql.apollo.annotations.ApolloInternal
import com.apollographql.apollo.api.json.ApolloJsonElement
import com.apollographql.cache.normalized.internal.RecordWeigher.calculateBytes
import com.benasher44.uuid.Uuid

/**
Expand All @@ -18,13 +17,13 @@ class Record(
* Arbitrary metadata that can be attached to each field.
*/
val metadata: Map<String, Map<String, ApolloJsonElement>> = emptyMap(),
) : Map<String, Any?> by fields {

val sizeInBytes: Int
get() {
return calculateBytes(this)
}

/**
* Size of the record in bytes. This is an optional field that can be set by the cache implementation for debug purposes, otherwise it
* defaults to `-1`, meaning unknown size.
*/
val sizeInBytes: Int = -1,
) : Map<String, Any?> by fields {
/**
* Returns a merge result record and a set of field keys which have changed, or were added.
* A field key incorporates any GraphQL arguments in addition to the field name.
Expand Down Expand Up @@ -98,11 +97,21 @@ fun Record.withDates(receivedDate: String?, expirationDate: String?): Record {
)
}

@ApolloInternal
fun Record.withSizeInBytes(sizeInBytes: Int): Record {
return Record(
key = key,
fields = fields,
mutationId = mutationId,
metadata = metadata,
sizeInBytes = sizeInBytes,
)
}

fun Record.receivedDate(field: String) = metadata[field]?.get(ApolloCacheHeaders.RECEIVED_DATE) as? Long

fun Record.expirationDate(field: String) = metadata[field]?.get(ApolloCacheHeaders.EXPIRATION_DATE) as? Long


/**
* A typealias for a type-unsafe Kotlin representation of a Record value. This typealias is
* mainly for internal documentation purposes and low-level manipulations and should
Expand Down
Loading