Skip to content

Commit 6a06344

Browse files
Adam Sharemartinbonnin
andauthored
Move serialization outside of cache lock (#5101)
Co-authored-by: Martin Bonnin <[email protected]>
1 parent 88b5739 commit 6a06344

File tree

8 files changed

+262
-144
lines changed

8 files changed

+262
-144
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.apollographql.apollo3.cache.normalized.api
2+
3+
import com.apollographql.apollo3.annotations.ApolloInternal
4+
5+
/**
6+
* Data read from the cache that can be represented as a JSON map.
7+
*
8+
* @see [toData]
9+
*/
10+
@ApolloInternal
11+
interface CacheData {
12+
fun toMap(): Map<String, Any?>
13+
}

libraries/apollo-normalized-cache-api-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/api/OperationCacheExtensions.kt

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package com.apollographql.apollo3.cache.normalized.api
22

3+
import com.apollographql.apollo3.annotations.ApolloDeprecatedSince
34
import com.apollographql.apollo3.annotations.ApolloExperimental
5+
import com.apollographql.apollo3.annotations.ApolloInternal
6+
import com.apollographql.apollo3.api.CompositeAdapter
47
import com.apollographql.apollo3.api.CustomScalarAdapters
58
import com.apollographql.apollo3.api.Executable
69
import com.apollographql.apollo3.api.Operation
@@ -57,13 +60,12 @@ fun <D : Executable.Data> Executable<D>.normalize(
5760
.normalize(writer.root() as Map<String, Any?>, rootField().selections, rootField().type.rawType())
5861
}
5962

60-
6163
fun <D : Executable.Data> Executable<D>.readDataFromCache(
6264
customScalarAdapters: CustomScalarAdapters,
6365
cache: ReadOnlyNormalizedCache,
6466
cacheResolver: CacheResolver,
6567
cacheHeaders: CacheHeaders,
66-
) = readInternal(
68+
): D = readDataFromCache(
6769
cacheKey = CacheKey.rootKey(),
6870
customScalarAdapters = customScalarAdapters,
6971
cache = cache,
@@ -77,6 +79,35 @@ fun <D : Executable.Data> Executable<D>.readDataFromCache(
7779
cache: ReadOnlyNormalizedCache,
7880
cacheResolver: CacheResolver,
7981
cacheHeaders: CacheHeaders,
82+
): D = readInternal(
83+
cacheKey = cacheKey,
84+
customScalarAdapters = customScalarAdapters,
85+
cache = cache,
86+
cacheResolver = cacheResolver,
87+
cacheHeaders = cacheHeaders,
88+
).toData(adapter(), customScalarAdapters)
89+
90+
fun <D : Executable.Data> Executable<D>.readDataFromCache(
91+
cacheKey: CacheKey,
92+
customScalarAdapters: CustomScalarAdapters,
93+
cache: ReadOnlyNormalizedCache,
94+
cacheResolver: ApolloResolver,
95+
cacheHeaders: CacheHeaders,
96+
): D = readInternal(
97+
cacheKey = cacheKey,
98+
customScalarAdapters = customScalarAdapters,
99+
cache = cache,
100+
cacheResolver = cacheResolver,
101+
cacheHeaders = cacheHeaders,
102+
).toData(adapter(), customScalarAdapters)
103+
104+
@ApolloInternal
105+
fun <D : Executable.Data> Executable<D>.readDataFromCacheInternal(
106+
cacheKey: CacheKey,
107+
customScalarAdapters: CustomScalarAdapters,
108+
cache: ReadOnlyNormalizedCache,
109+
cacheResolver: CacheResolver,
110+
cacheHeaders: CacheHeaders,
80111
) = readInternal(
81112
cacheKey = cacheKey,
82113
customScalarAdapters = customScalarAdapters,
@@ -85,7 +116,8 @@ fun <D : Executable.Data> Executable<D>.readDataFromCache(
85116
cacheHeaders = cacheHeaders,
86117
)
87118

88-
fun <D : Executable.Data> Executable<D>.readDataFromCache(
119+
@ApolloInternal
120+
fun <D : Executable.Data> Executable<D>.readDataFromCacheInternal(
89121
cacheKey: CacheKey,
90122
customScalarAdapters: CustomScalarAdapters,
91123
cache: ReadOnlyNormalizedCache,
@@ -106,25 +138,31 @@ private fun <D : Executable.Data> Executable<D>.readInternal(
106138
cache: ReadOnlyNormalizedCache,
107139
cacheResolver: Any,
108140
cacheHeaders: CacheHeaders,
109-
): D {
110-
val map = CacheBatchReader(
141+
): CacheData {
142+
return CacheBatchReader(
111143
cache = cache,
112144
cacheHeaders = cacheHeaders,
113145
cacheResolver = cacheResolver,
114146
variables = variables(customScalarAdapters, true),
115147
rootKey = cacheKey.key,
116148
rootSelections = rootField().selections,
117149
rootTypename = rootField().type.rawType().name
118-
).toMap()
119-
120-
val reader = MapJsonReader(
121-
root = map,
122-
)
123-
return adapter().fromJson(reader, customScalarAdapters)
150+
).collectData()
124151
}
125152

126153
fun Collection<Record>?.dependentKeys(): Set<String> {
127154
return this?.flatMap {
128155
it.fieldKeys()
129156
}?.toSet() ?: emptySet()
130157
}
158+
159+
@ApolloInternal
160+
fun <D: Executable.Data> CacheData.toData(
161+
adapter: CompositeAdapter<D>,
162+
customScalarAdapters: CustomScalarAdapters,
163+
): D {
164+
val reader = MapJsonReader(
165+
root = toMap(),
166+
)
167+
return adapter.fromJson(reader, customScalarAdapters)
168+
}

libraries/apollo-normalized-cache-api-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/api/internal/CacheBatchReader.kt

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
package com.apollographql.apollo3.cache.normalized.api.internal
22

3-
import com.apollographql.apollo3.annotations.ApolloInternal
43
import com.apollographql.apollo3.api.CompiledField
54
import com.apollographql.apollo3.api.CompiledFragment
65
import com.apollographql.apollo3.api.CompiledSelection
76
import com.apollographql.apollo3.api.Executable
87
import com.apollographql.apollo3.cache.normalized.api.ApolloResolver
8+
import com.apollographql.apollo3.cache.normalized.api.CacheData
99
import com.apollographql.apollo3.cache.normalized.api.CacheHeaders
1010
import com.apollographql.apollo3.cache.normalized.api.CacheKey
1111
import com.apollographql.apollo3.cache.normalized.api.CacheResolver
@@ -83,7 +83,7 @@ internal class CacheBatchReader(
8383
}
8484
}
8585

86-
fun toMap(): Map<String, Any?> {
86+
fun collectData(): CacheData {
8787
pendingReferences.add(
8888
PendingReference(
8989
key = rootKey,
@@ -132,8 +132,7 @@ internal class CacheBatchReader(
132132
}
133133
}
134134

135-
@Suppress("UNCHECKED_CAST")
136-
return data[emptyList()].replaceCacheKeys(emptyList()) as Map<String, Any?>
135+
return CacheBatchReaderData(data)
137136
}
138137

139138
/**
@@ -180,27 +179,35 @@ internal class CacheBatchReader(
180179
}
181180
}
182181

183-
private fun Any?.replaceCacheKeys(path: List<Any>): Any? {
184-
return when (this) {
185-
is CacheKey -> {
186-
data[path].replaceCacheKeys(path)
187-
}
188-
is List<*> -> {
189-
mapIndexed { index, src ->
190-
src.replaceCacheKeys(path + index)
182+
private data class CacheBatchReaderData(
183+
private val data: Map<List<Any>, Map<String, Any?>>,
184+
): CacheData {
185+
@Suppress("UNCHECKED_CAST")
186+
override fun toMap(): Map<String, Any?> {
187+
return data[emptyList()].replaceCacheKeys(emptyList()) as Map<String, Any?>
188+
}
189+
190+
private fun Any?.replaceCacheKeys(path: List<Any>): Any? {
191+
return when (this) {
192+
is CacheKey -> {
193+
data[path].replaceCacheKeys(path)
191194
}
192-
}
193-
is Map<*, *> -> {
194-
// This will traverse Map custom scalars but this is ok as it shouldn't contain any CacheKey
195-
mapValues {
196-
it.value.replaceCacheKeys(path + (it.key as String))
195+
is List<*> -> {
196+
mapIndexed { index, src ->
197+
src.replaceCacheKeys(path + index)
198+
}
199+
}
200+
is Map<*, *> -> {
201+
// This will traverse Map custom scalars but this is ok as it shouldn't contain any CacheKey
202+
mapValues {
203+
it.value.replaceCacheKeys(path + (it.key as String))
204+
}
205+
}
206+
else -> {
207+
// Scalar value
208+
this
197209
}
198-
}
199-
else -> {
200-
// Scalar value
201-
this
202210
}
203211
}
204212
}
205213
}
206-
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.apollographql.apollo3.cache.normalized.api
2+
3+
import com.apollographql.apollo3.annotations.ApolloInternal
4+
5+
/**
6+
* Data read from the cache that can be represented as a JSON map.
7+
*
8+
* @see [toData]
9+
*/
10+
@ApolloInternal
11+
interface CacheData {
12+
fun toMap(): Map<String, Any?>
13+
}

libraries/apollo-normalized-cache-api/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/api/OperationCacheExtensions.kt

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.apollographql.apollo3.cache.normalized.api
22

3+
import com.apollographql.apollo3.annotations.ApolloInternal
4+
import com.apollographql.apollo3.api.CompositeAdapter
35
import com.apollographql.apollo3.api.CustomScalarAdapters
46
import com.apollographql.apollo3.api.Executable
57
import com.apollographql.apollo3.api.Fragment
@@ -12,7 +14,6 @@ import com.apollographql.apollo3.api.variables
1214
import com.apollographql.apollo3.cache.normalized.api.internal.CacheBatchReader
1315
import com.apollographql.apollo3.cache.normalized.api.internal.Normalizer
1416

15-
1617
fun <D : Operation.Data> Operation<D>.normalize(
1718
data: D,
1819
customScalarAdapters: CustomScalarAdapters,
@@ -38,6 +39,34 @@ fun <D : Executable.Data> Executable<D>.readDataFromCache(
3839
cache: ReadOnlyNormalizedCache,
3940
cacheResolver: CacheResolver,
4041
cacheHeaders: CacheHeaders,
42+
):D = readInternal(
43+
cacheKey = CacheKey.rootKey(),
44+
customScalarAdapters = customScalarAdapters,
45+
cache = cache,
46+
cacheResolver = cacheResolver,
47+
cacheHeaders = cacheHeaders,
48+
).toData(adapter(), customScalarAdapters)
49+
50+
fun <D : Fragment.Data> Fragment<D>.readDataFromCache(
51+
cacheKey: CacheKey,
52+
customScalarAdapters: CustomScalarAdapters,
53+
cache: ReadOnlyNormalizedCache,
54+
cacheResolver: CacheResolver,
55+
cacheHeaders: CacheHeaders,
56+
): D = readInternal(
57+
cacheKey = cacheKey,
58+
customScalarAdapters = customScalarAdapters,
59+
cache = cache,
60+
cacheResolver = cacheResolver,
61+
cacheHeaders = cacheHeaders,
62+
).toData(adapter(), customScalarAdapters)
63+
64+
@ApolloInternal
65+
fun <D : Executable.Data> Executable<D>.readDataFromCacheInternal(
66+
customScalarAdapters: CustomScalarAdapters,
67+
cache: ReadOnlyNormalizedCache,
68+
cacheResolver: CacheResolver,
69+
cacheHeaders: CacheHeaders,
4170
) = readInternal(
4271
cacheKey = CacheKey.rootKey(),
4372
customScalarAdapters = customScalarAdapters,
@@ -46,7 +75,8 @@ fun <D : Executable.Data> Executable<D>.readDataFromCache(
4675
cacheHeaders = cacheHeaders,
4776
)
4877

49-
fun <D : Fragment.Data> Fragment<D>.readDataFromCache(
78+
@ApolloInternal
79+
fun <D : Fragment.Data> Fragment<D>.readDataFromCacheInternal(
5080
cacheKey: CacheKey,
5181
customScalarAdapters: CustomScalarAdapters,
5282
cache: ReadOnlyNormalizedCache,
@@ -66,25 +96,31 @@ private fun <D : Executable.Data> Executable<D>.readInternal(
6696
cache: ReadOnlyNormalizedCache,
6797
cacheResolver: CacheResolver,
6898
cacheHeaders: CacheHeaders,
69-
): D {
70-
val map = CacheBatchReader(
99+
): CacheData {
100+
return CacheBatchReader(
71101
cache = cache,
72102
cacheHeaders = cacheHeaders,
73103
cacheResolver = cacheResolver,
74104
variables = variables(customScalarAdapters, true),
75105
rootKey = cacheKey.key,
76106
rootSelections = rootField().selections,
77107
rootTypename = rootField().type.rawType().name
78-
).toMap()
79-
80-
val reader = MapJsonReader(
81-
root = map,
82-
)
83-
return adapter().fromJson(reader, customScalarAdapters)
108+
).collectData()
84109
}
85110

86111
fun Collection<Record>?.dependentKeys(): Set<String> {
87112
return this?.flatMap {
88113
it.fieldKeys()
89114
}?.toSet() ?: emptySet()
90115
}
116+
117+
@ApolloInternal
118+
fun <D: Executable.Data> CacheData.toData(
119+
adapter: CompositeAdapter<D>,
120+
customScalarAdapters: CustomScalarAdapters,
121+
): D {
122+
val reader = MapJsonReader(
123+
root = toMap(),
124+
)
125+
return adapter.fromJson(reader, customScalarAdapters)
126+
}

0 commit comments

Comments
 (0)