Merge pull request #2201 from mstrofnone/fix/largecache-concurrent-modification

fix(quartz): snapshot LargeCache entries in forEach to prevent ConcurrentModificationException
This commit is contained in:
Vitor Pamplona
2026-04-10 08:10:44 -04:00
committed by GitHub
2 changed files with 6 additions and 2 deletions
@@ -85,7 +85,10 @@ actual class LargeCache<K, V> : ICacheOperations<K, V> {
actual override fun size(): Int = concurrentMap.size
actual override fun forEach(consumer: ICacheBiConsumer<K, V>) {
concurrentMap.forEach { consumer.accept(it.key, it.value) }
// Take a snapshot of entries to avoid ConcurrentModificationException
// when the map is modified during iteration (e.g., NostrClient.syncFilters
// iterating while subscriptions are added from another coroutine).
concurrentMap.entries.toList().forEach { consumer.accept(it.key, it.value) }
}
actual override fun filter(consumer: CacheCollectors.BiFilter<K, V>): List<V> =
@@ -88,7 +88,8 @@ actual class LargeCache<K, V> : ICacheOperations<K, V> {
actual override fun size(): Int = withMap { it.size }
actual override fun forEach(consumer: ICacheBiConsumer<K, V>) {
withMap { map -> map.forEach { consumer.accept(it.key, it.value) } }
// Snapshot entries to avoid ConcurrentModificationException
withMap { map -> map.entries.toList() }.forEach { consumer.accept(it.key, it.value) }
}
actual override fun filter(consumer: CacheCollectors.BiFilter<K, V>): List<V> = withMap { map -> map.filter { consumer.filter(it.key, it.value) }.values.toList() }