Skip to content

Commit af34016

Browse files
author
Oleksandr Dzhychko
committed
fix(model-datastructure): do not cache null values in PrefetchCache
1 parent 784de9c commit af34016

File tree

2 files changed

+55
-9
lines changed

2 files changed

+55
-9
lines changed

model-datastructure/src/commonMain/kotlin/org/modelix/model/lazy/PrefetchCache.kt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ class PrefetchCache(private val store: IDeserializingKeyValueStore) : IDeseriali
4343
entries[hash] as T?
4444
} else {
4545
val value = if (ifCached) store.getIfCached(hash, deserializer, isPrefetch) else store.get(hash, deserializer)
46-
entries[hash] = value
46+
if (value != null) {
47+
entries[hash] = value
48+
}
4749
value
4850
}
4951
}
@@ -64,7 +66,11 @@ class PrefetchCache(private val store: IDeserializingKeyValueStore) : IDeseriali
6466
val missingRegular = regular.filterNot { entries.containsKey(it.getHash()) }
6567
val missingPrefetch = prefetch.filterNot { entries.containsKey(it.getHash()) }
6668
val missingEntries = store.getAll(missingRegular, missingPrefetch)
67-
entries.putAll(missingEntries)
69+
for ((key, value) in missingEntries) {
70+
if (value != null) {
71+
entries[key] = value
72+
}
73+
}
6874
val regularAndPrefetch = regular.asSequence() + prefetch.asSequence()
6975
return regularAndPrefetch.associate { it.getHash() to entries[it.getHash()] as T? }
7076
}

model-datastructure/src/commonTest/kotlin/org/modelix/model/lazy/PrefetchCacheTest.kt

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import org.modelix.model.lazy.AccessTrackingStore
22
import org.modelix.model.lazy.NonCachingObjectStore
3+
import org.modelix.model.lazy.ObjectStoreCache
34
import org.modelix.model.lazy.PrefetchCache
45
import org.modelix.model.lazy.WrittenEntry
56
import org.modelix.model.persistent.CPNode
@@ -11,24 +12,39 @@ import kotlin.test.assertTrue
1112
class PrefetchCacheTest {
1213

1314
private val keyValueStore = MapBasedStore()
14-
private val accessTrackingKeyValueStore = AccessTrackingStore(keyValueStore)
15-
private val deserializingKeyValueStore = NonCachingObjectStore(accessTrackingKeyValueStore)
16-
private val prefetchCache = PrefetchCache(deserializingKeyValueStore)
1715

1816
@Test
19-
fun entriesAreCachedAfterGettingMultipleEntriesAsIterable() {
17+
fun nullValueIsNotCached() {
18+
val deserializingKeyValueStore = NonCachingObjectStore(keyValueStore)
19+
val prefetchCache = PrefetchCache(deserializingKeyValueStore)
20+
prefetchCache["key", { value -> value }]
21+
keyValueStore.put("key", "value")
22+
23+
val result = prefetchCache["key", { value -> value }]
24+
25+
assertEquals("value", result)
26+
}
27+
28+
@Test
29+
fun valuesAreCachedWhenGettingMultipleEntriesAsIterable() {
30+
val accessTrackingKeyValueStore = AccessTrackingStore(keyValueStore)
31+
val deserializingKeyValueStore = NonCachingObjectStore(accessTrackingKeyValueStore)
32+
val prefetchCache = PrefetchCache(deserializingKeyValueStore)
2033
keyValueStore.put("key", "value")
2134
prefetchCache.getAll(listOf("key")) { _, value -> value }
2235
accessTrackingKeyValueStore.accessedEntries.clear()
2336

2437
val result = prefetchCache.getAll(listOf("key")) { _, value -> value }
2538

26-
assertEquals(result, listOf("value"))
39+
assertEquals(listOf("value"), result)
2740
assertTrue(accessTrackingKeyValueStore.accessedEntries.isEmpty())
2841
}
2942

3043
@Test
31-
fun entriesAreCachedAfterGettingMultipleEntriesAsMap() {
44+
fun valuesAreCachedWhenGettingMultipleEntriesAsMap() {
45+
val accessTrackingKeyValueStore = AccessTrackingStore(keyValueStore)
46+
val deserializingKeyValueStore = NonCachingObjectStore(accessTrackingKeyValueStore)
47+
val prefetchCache = PrefetchCache(deserializingKeyValueStore)
3248
val regularKey = "regularKey"
3349
val prefetchKey = "prefetchKey"
3450
val nodeForRegularKey = CPNode.create(
@@ -47,7 +63,31 @@ class PrefetchCacheTest {
4763

4864
val result = prefetchCache.getAll(listOf(regularKeyReference), listOf(prefetchKeyReference))
4965

50-
assertEquals(result, mapOf(regularKey to nodeForRegularKey, prefetchKey to nodeForPrefetchKey))
66+
assertEquals(mapOf(regularKey to nodeForRegularKey, prefetchKey to nodeForPrefetchKey), result)
5167
assertTrue(accessTrackingKeyValueStore.accessedEntries.isEmpty())
5268
}
69+
70+
@Test
71+
fun nullValuesAreNotCachedWhenGettingMultipleEntriesAsMap() {
72+
val deserializingKeyValueStore = ObjectStoreCache(keyValueStore)
73+
val prefetchCache = PrefetchCache(deserializingKeyValueStore)
74+
val regularKey = "regularKey"
75+
val prefetchKey = "prefetchKey"
76+
val nodeForRegularKey = CPNode.create(
77+
2, null, 1, null, LongArray(0),
78+
emptyArray(), emptyArray(), emptyArray(), emptyArray(),
79+
)
80+
val nodeForPrefetchKey = CPNode.create(
81+
3, null, 1, null, LongArray(0),
82+
emptyArray(), emptyArray(), emptyArray(), emptyArray(),
83+
)
84+
val regularKeyReference = WrittenEntry(regularKey) { nodeForRegularKey }
85+
val prefetchKeyReference = WrittenEntry(prefetchKey) { nodeForPrefetchKey }
86+
prefetchCache.getAll(listOf(regularKeyReference), listOf(prefetchKeyReference))
87+
keyValueStore.putAll(mapOf(regularKey to nodeForRegularKey.serialize(), prefetchKey to nodeForPrefetchKey.serialize()))
88+
89+
val result = prefetchCache.getAll(listOf(regularKeyReference), listOf(prefetchKeyReference))
90+
91+
assertEquals(mapOf(regularKey to nodeForRegularKey, prefetchKey to nodeForPrefetchKey), result)
92+
}
5393
}

0 commit comments

Comments
 (0)