problem: block height cache doesn't evict when old blocks are added
rel: ce010e50
This commit is contained in:
@@ -104,6 +104,7 @@ dependencies {
|
|||||||
implementation 'org.apache.commons:commons-collections4:4.3'
|
implementation 'org.apache.commons:commons-collections4:4.3'
|
||||||
implementation 'javax.annotation:javax.annotation-api:1.3.2'
|
implementation 'javax.annotation:javax.annotation-api:1.3.2'
|
||||||
implementation 'org.bouncycastle:bcprov-jdk15on:1.61'
|
implementation 'org.bouncycastle:bcprov-jdk15on:1.61'
|
||||||
|
implementation 'com.github.ben-manes.caffeine:caffeine:2.8.5'
|
||||||
|
|
||||||
implementation "org.slf4j:slf4j-api:$slf4jVersion"
|
implementation "org.slf4j:slf4j-api:$slf4jVersion"
|
||||||
implementation "org.apache.logging.log4j:log4j-slf4j-impl:2.11.1"
|
implementation "org.apache.logging.log4j:log4j-slf4j-impl:2.11.1"
|
||||||
|
|||||||
@@ -15,41 +15,35 @@
|
|||||||
*/
|
*/
|
||||||
package io.emeraldpay.dshackle.cache
|
package io.emeraldpay.dshackle.cache
|
||||||
|
|
||||||
|
import com.github.benmanes.caffeine.cache.Caffeine
|
||||||
import io.emeraldpay.dshackle.data.BlockContainer
|
import io.emeraldpay.dshackle.data.BlockContainer
|
||||||
import io.emeraldpay.dshackle.data.BlockId
|
import io.emeraldpay.dshackle.data.BlockId
|
||||||
import io.emeraldpay.dshackle.reader.Reader
|
import io.emeraldpay.dshackle.reader.Reader
|
||||||
import org.slf4j.LoggerFactory
|
|
||||||
import reactor.core.publisher.Mono
|
import reactor.core.publisher.Mono
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Memory cache for blocks heights, keeps mapping height->hash.
|
* Memory cache for blocks heights, keeps mapping height->hash.
|
||||||
*/
|
*/
|
||||||
open class HeightCache(
|
open class HeightCache(
|
||||||
val maxSize: Int = 256
|
maxSize: Int = 512
|
||||||
) : Reader<Long, BlockId> {
|
) : Reader<Long, BlockId> {
|
||||||
|
|
||||||
companion object {
|
private val heights = Caffeine.newBuilder()
|
||||||
private val log = LoggerFactory.getLogger(HeightCache::class.java)
|
.maximumSize(maxSize.toLong())
|
||||||
}
|
.build<Long, BlockId>()
|
||||||
|
|
||||||
private val heights = ConcurrentHashMap<Long, BlockId>()
|
|
||||||
|
|
||||||
override fun read(key: Long): Mono<BlockId> {
|
override fun read(key: Long): Mono<BlockId> {
|
||||||
return Mono.justOrEmpty(heights[key])
|
return Mono.justOrEmpty(heights.getIfPresent(key))
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun add(block: BlockContainer): BlockId? {
|
open fun add(block: BlockContainer): BlockId? {
|
||||||
val existing = heights[block.height]
|
val previousId = heights.getIfPresent(block.height)
|
||||||
heights[block.height] = block.hash
|
heights.put(block.height, block.hash)
|
||||||
|
return previousId
|
||||||
// evict old numbers if full
|
|
||||||
var dropHeight = block.height - maxSize
|
|
||||||
while (heights.size > maxSize && dropHeight < block.height) {
|
|
||||||
heights.remove(dropHeight)
|
|
||||||
dropHeight++
|
|
||||||
}
|
|
||||||
|
|
||||||
return existing
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun purge() {
|
||||||
|
heights.cleanUp()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -72,6 +72,7 @@ class HeightCacheSpec extends Specification {
|
|||||||
block.timestamp = Instant.now()
|
block.timestamp = Instant.now()
|
||||||
cache.add(BlockContainer.from(block))
|
cache.add(BlockContainer.from(block))
|
||||||
}
|
}
|
||||||
|
cache.purge()
|
||||||
|
|
||||||
def act1 = cache.read(100).block()
|
def act1 = cache.read(100).block()
|
||||||
def act2 = cache.read(101).block()
|
def act2 = cache.read(101).block()
|
||||||
|
|||||||
Reference in New Issue
Block a user