Turn off caches for main, fix cache not enrichment blocks (#160)
This commit is contained in:
@@ -39,6 +39,9 @@ open class BlocksMemCache(
|
|||||||
}
|
}
|
||||||
|
|
||||||
open fun add(block: BlockContainer) {
|
open fun add(block: BlockContainer) {
|
||||||
|
if (!block.enriched) {
|
||||||
|
return
|
||||||
|
}
|
||||||
mapping.put(block.hash, block)
|
mapping.put(block.hash, block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,8 @@ open class Caches(
|
|||||||
private val redisBlocksByHash: BlocksRedisCache?,
|
private val redisBlocksByHash: BlocksRedisCache?,
|
||||||
private val redisTxsByHash: TxRedisCache?,
|
private val redisTxsByHash: TxRedisCache?,
|
||||||
private val redisReceipts: ReceiptRedisCache?,
|
private val redisReceipts: ReceiptRedisCache?,
|
||||||
private val redisHeightByHashCache: HeightByHashRedisCache?
|
private val redisHeightByHashCache: HeightByHashRedisCache?,
|
||||||
|
private val cacheEnabled: Boolean
|
||||||
) {
|
) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -89,6 +90,9 @@ open class Caches(
|
|||||||
}
|
}
|
||||||
|
|
||||||
open fun cacheReceipt(tag: Tag, data: DefaultContainer<TransactionReceiptJson>) {
|
open fun cacheReceipt(tag: Tag, data: DefaultContainer<TransactionReceiptJson>) {
|
||||||
|
if (!cacheEnabled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
val currentHeight = head?.getCurrentHeight()
|
val currentHeight = head?.getCurrentHeight()
|
||||||
if (currentHeight != null && data.height != null && memReceipts.acceptsRecentBlocks(currentHeight - data.height)) {
|
if (currentHeight != null && data.height != null && memReceipts.acceptsRecentBlocks(currentHeight - data.height)) {
|
||||||
memReceipts.add(data).subscribe()
|
memReceipts.add(data).subscribe()
|
||||||
@@ -98,6 +102,9 @@ open class Caches(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun cache(tag: Tag, tx: TxContainer) {
|
fun cache(tag: Tag, tx: TxContainer) {
|
||||||
|
if (!cacheEnabled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
// do not cache transactions that are not in a block yet
|
// do not cache transactions that are not in a block yet
|
||||||
if (tx.blockId == null) {
|
if (tx.blockId == null) {
|
||||||
return
|
return
|
||||||
@@ -110,6 +117,9 @@ open class Caches(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun cache(tag: Tag, block: BlockContainer) {
|
fun cache(tag: Tag, block: BlockContainer) {
|
||||||
|
if (!cacheEnabled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
val job = ArrayList<Mono<Void>>()
|
val job = ArrayList<Mono<Void>>()
|
||||||
|
|
||||||
redisHeightByHashCache?.add(block)?.let(job::add)
|
redisHeightByHashCache?.add(block)?.let(job::add)
|
||||||
@@ -129,7 +139,6 @@ open class Caches(
|
|||||||
blockOnlyContainer = block
|
blockOnlyContainer = block
|
||||||
}
|
}
|
||||||
memoizeBlock(blockOnlyContainer)
|
memoizeBlock(blockOnlyContainer)
|
||||||
memBlocksByHash.add(blockOnlyContainer)
|
|
||||||
redisBlocksByHash?.add(blockOnlyContainer)?.let(job::add)
|
redisBlocksByHash?.add(blockOnlyContainer)?.let(job::add)
|
||||||
|
|
||||||
// now cache only transactions
|
// now cache only transactions
|
||||||
@@ -198,7 +207,7 @@ open class Caches(
|
|||||||
return receiptByHash
|
return receiptByHash
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getLastHeightByHash(): Reader<BlockId, Long> {
|
open fun getLastHeightByHash(): Reader<BlockId, Long> {
|
||||||
return memHeightByHash
|
return memHeightByHash
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,6 +236,7 @@ open class Caches(
|
|||||||
private var redisTxsByHash: TxRedisCache? = null
|
private var redisTxsByHash: TxRedisCache? = null
|
||||||
private var redisReceiptCache: ReceiptRedisCache? = null
|
private var redisReceiptCache: ReceiptRedisCache? = null
|
||||||
private var redisHeightByHashCache: HeightByHashRedisCache? = null
|
private var redisHeightByHashCache: HeightByHashRedisCache? = null
|
||||||
|
private var cacheEnabled: Boolean = true
|
||||||
|
|
||||||
fun setBlockByHash(cache: BlocksMemCache): Builder {
|
fun setBlockByHash(cache: BlocksMemCache): Builder {
|
||||||
blocksByHash = cache
|
blocksByHash = cache
|
||||||
@@ -268,6 +278,11 @@ open class Caches(
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setCacheEnabled(cacheEnabled: Boolean): Builder {
|
||||||
|
this.cacheEnabled = cacheEnabled
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
fun build(): Caches {
|
fun build(): Caches {
|
||||||
if (blocksByHash == null) {
|
if (blocksByHash == null) {
|
||||||
blocksByHash = BlocksMemCache()
|
blocksByHash = BlocksMemCache()
|
||||||
@@ -283,7 +298,7 @@ open class Caches(
|
|||||||
}
|
}
|
||||||
return Caches(
|
return Caches(
|
||||||
blocksByHash!!, blocksByHeight!!, txsByHash!!, receipts!!,
|
blocksByHash!!, blocksByHeight!!, txsByHash!!, receipts!!,
|
||||||
redisBlocksByHash, redisTxsByHash, redisReceiptCache, redisHeightByHashCache
|
redisBlocksByHash, redisTxsByHash, redisReceiptCache, redisHeightByHashCache, cacheEnabled
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ open class CachesFactory(
|
|||||||
caches.setReceipts(ReceiptRedisCache(redis.reactive(), chain))
|
caches.setReceipts(ReceiptRedisCache(redis.reactive(), chain))
|
||||||
caches.setHeightByHash(HeightByHashRedisCache(redis.reactive(), chain))
|
caches.setHeightByHash(HeightByHashRedisCache(redis.reactive(), chain))
|
||||||
}
|
}
|
||||||
|
caches.setCacheEnabled(cacheConfig.requestsCacheEnabled)
|
||||||
return caches.build()
|
return caches.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import io.emeraldpay.dshackle.reader.Reader
|
|||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import reactor.core.publisher.Mono
|
import reactor.core.publisher.Mono
|
||||||
|
|
||||||
class HeightByHashMemCache(
|
open class HeightByHashMemCache(
|
||||||
maxSize: Int = 256
|
maxSize: Int = 256
|
||||||
) : Reader<BlockId, Long> {
|
) : Reader<BlockId, Long> {
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ class BlockContainer(
|
|||||||
val nodeRating: Int = 0,
|
val nodeRating: Int = 0,
|
||||||
val upstreamId: String = ""
|
val upstreamId: String = ""
|
||||||
) : SourceContainer(json, parsed) {
|
) : SourceContainer(json, parsed) {
|
||||||
|
val enriched: Boolean = transactions.isNotEmpty()
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
|||||||
@@ -164,10 +164,10 @@ class EthereumCallSelector(
|
|||||||
|
|
||||||
private fun blockByHashFromCache(blockHash: String): Mono<Selector.Matcher> {
|
private fun blockByHashFromCache(blockHash: String): Mono<Selector.Matcher> {
|
||||||
return try {
|
return try {
|
||||||
caches.getBlocksByHash()
|
caches.getLastHeightByHash()
|
||||||
.read(BlockId.from(blockHash))
|
.read(BlockId.from(blockHash))
|
||||||
.onErrorResume { Mono.empty() }
|
.onErrorResume { Mono.empty() }
|
||||||
.map { Selector.HeightMatcher(it.height) }
|
.map { Selector.HeightMatcher(it) }
|
||||||
} catch (e: DecoderException) {
|
} catch (e: DecoderException) {
|
||||||
log.warn("Invalid blockHash: $blockHash")
|
log.warn("Invalid blockHash: $blockHash")
|
||||||
Mono.empty()
|
Mono.empty()
|
||||||
|
|||||||
@@ -19,7 +19,9 @@ import com.fasterxml.jackson.databind.ObjectMapper
|
|||||||
import io.emeraldpay.dshackle.Global
|
import io.emeraldpay.dshackle.Global
|
||||||
import io.emeraldpay.dshackle.data.BlockContainer
|
import io.emeraldpay.dshackle.data.BlockContainer
|
||||||
import io.emeraldpay.etherjar.domain.BlockHash
|
import io.emeraldpay.etherjar.domain.BlockHash
|
||||||
|
import io.emeraldpay.etherjar.domain.TransactionId
|
||||||
import io.emeraldpay.etherjar.rpc.json.BlockJson
|
import io.emeraldpay.etherjar.rpc.json.BlockJson
|
||||||
|
import io.emeraldpay.etherjar.rpc.json.TransactionJson
|
||||||
import io.emeraldpay.etherjar.rpc.json.TransactionRefJson
|
import io.emeraldpay.etherjar.rpc.json.TransactionRefJson
|
||||||
import spock.lang.Specification
|
import spock.lang.Specification
|
||||||
|
|
||||||
@@ -39,12 +41,14 @@ class BlockByHeightSpec extends Specification {
|
|||||||
def heights = new HeightCache()
|
def heights = new HeightCache()
|
||||||
|
|
||||||
def block = new BlockJson<TransactionRefJson>()
|
def block = new BlockJson<TransactionRefJson>()
|
||||||
|
def tx = new TransactionJson()
|
||||||
|
tx.hash = TransactionId.from(hash1)
|
||||||
block.number = 100
|
block.number = 100
|
||||||
block.hash = BlockHash.from(hash1)
|
block.hash = BlockHash.from(hash1)
|
||||||
block.totalDifficulty = BigInteger.ONE
|
block.totalDifficulty = BigInteger.ONE
|
||||||
block.timestamp = Instant.now().truncatedTo(ChronoUnit.SECONDS)
|
block.timestamp = Instant.now().truncatedTo(ChronoUnit.SECONDS)
|
||||||
block.uncles = []
|
block.uncles = []
|
||||||
block.transactions = []
|
block.transactions = List.of(tx)
|
||||||
|
|
||||||
BlockContainer.from(block).with {
|
BlockContainer.from(block).with {
|
||||||
blocks.add(it)
|
blocks.add(it)
|
||||||
@@ -65,12 +69,14 @@ class BlockByHeightSpec extends Specification {
|
|||||||
def heights = new HeightCache()
|
def heights = new HeightCache()
|
||||||
|
|
||||||
def block1 = new BlockJson<TransactionRefJson>()
|
def block1 = new BlockJson<TransactionRefJson>()
|
||||||
|
def tx = new TransactionJson()
|
||||||
|
tx.hash = TransactionId.from(hash1)
|
||||||
block1.number = 100
|
block1.number = 100
|
||||||
block1.hash = BlockHash.from(hash1)
|
block1.hash = BlockHash.from(hash1)
|
||||||
block1.totalDifficulty = BigInteger.ONE
|
block1.totalDifficulty = BigInteger.ONE
|
||||||
block1.timestamp = Instant.now().truncatedTo(ChronoUnit.SECONDS)
|
block1.timestamp = Instant.now().truncatedTo(ChronoUnit.SECONDS)
|
||||||
block1.uncles = []
|
block1.uncles = []
|
||||||
block1.transactions = []
|
block1.transactions = List.of(tx)
|
||||||
|
|
||||||
def block2 = new BlockJson<TransactionRefJson>()
|
def block2 = new BlockJson<TransactionRefJson>()
|
||||||
block2.number = 101
|
block2.number = 101
|
||||||
@@ -78,7 +84,7 @@ class BlockByHeightSpec extends Specification {
|
|||||||
block2.totalDifficulty = BigInteger.ONE
|
block2.totalDifficulty = BigInteger.ONE
|
||||||
block2.timestamp = Instant.now().truncatedTo(ChronoUnit.SECONDS)
|
block2.timestamp = Instant.now().truncatedTo(ChronoUnit.SECONDS)
|
||||||
block2.uncles = []
|
block2.uncles = []
|
||||||
block2.transactions = []
|
block2.transactions = List.of(tx)
|
||||||
|
|
||||||
|
|
||||||
BlockContainer.from(block1).with {
|
BlockContainer.from(block1).with {
|
||||||
@@ -109,12 +115,14 @@ class BlockByHeightSpec extends Specification {
|
|||||||
def heights = new HeightCache()
|
def heights = new HeightCache()
|
||||||
|
|
||||||
def block1 = new BlockJson<TransactionRefJson>()
|
def block1 = new BlockJson<TransactionRefJson>()
|
||||||
|
def tx = new TransactionJson()
|
||||||
|
tx.hash = TransactionId.from(hash1)
|
||||||
block1.number = 100
|
block1.number = 100
|
||||||
block1.hash = BlockHash.from(hash1)
|
block1.hash = BlockHash.from(hash1)
|
||||||
block1.totalDifficulty = BigInteger.ONE
|
block1.totalDifficulty = BigInteger.ONE
|
||||||
block1.timestamp = Instant.now().truncatedTo(ChronoUnit.SECONDS)
|
block1.timestamp = Instant.now().truncatedTo(ChronoUnit.SECONDS)
|
||||||
block1.uncles = []
|
block1.uncles = []
|
||||||
block1.transactions = []
|
block1.transactions = List.of(tx)
|
||||||
|
|
||||||
def block2 = new BlockJson<TransactionRefJson>()
|
def block2 = new BlockJson<TransactionRefJson>()
|
||||||
block2.number = 100
|
block2.number = 100
|
||||||
@@ -122,7 +130,7 @@ class BlockByHeightSpec extends Specification {
|
|||||||
block2.totalDifficulty = BigInteger.ONE
|
block2.totalDifficulty = BigInteger.ONE
|
||||||
block2.timestamp = Instant.now().truncatedTo(ChronoUnit.SECONDS)
|
block2.timestamp = Instant.now().truncatedTo(ChronoUnit.SECONDS)
|
||||||
block2.uncles = []
|
block2.uncles = []
|
||||||
block2.transactions = []
|
block2.transactions = List.of(tx)
|
||||||
|
|
||||||
BlockContainer.from(block1).with {
|
BlockContainer.from(block1).with {
|
||||||
blocks.add(it)
|
blocks.add(it)
|
||||||
|
|||||||
@@ -21,7 +21,9 @@ import io.emeraldpay.dshackle.Global
|
|||||||
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.etherjar.domain.BlockHash
|
import io.emeraldpay.etherjar.domain.BlockHash
|
||||||
|
import io.emeraldpay.etherjar.domain.TransactionId
|
||||||
import io.emeraldpay.etherjar.rpc.json.BlockJson
|
import io.emeraldpay.etherjar.rpc.json.BlockJson
|
||||||
|
import io.emeraldpay.etherjar.rpc.json.TransactionJson
|
||||||
import io.emeraldpay.etherjar.rpc.json.TransactionRefJson
|
import io.emeraldpay.etherjar.rpc.json.TransactionRefJson
|
||||||
import spock.lang.Specification
|
import spock.lang.Specification
|
||||||
|
|
||||||
@@ -39,12 +41,14 @@ class BlocksMemCacheSpec extends Specification {
|
|||||||
setup:
|
setup:
|
||||||
def cache = new BlocksMemCache()
|
def cache = new BlocksMemCache()
|
||||||
def block = new BlockJson<TransactionRefJson>()
|
def block = new BlockJson<TransactionRefJson>()
|
||||||
|
def tx = new TransactionJson()
|
||||||
|
tx.hash = TransactionId.from(hash1)
|
||||||
block.number = 100
|
block.number = 100
|
||||||
block.hash = BlockHash.from(hash1)
|
block.hash = BlockHash.from(hash1)
|
||||||
block.totalDifficulty = BigInteger.ONE
|
block.totalDifficulty = BigInteger.ONE
|
||||||
block.timestamp = Instant.now().truncatedTo(ChronoUnit.SECONDS)
|
block.timestamp = Instant.now().truncatedTo(ChronoUnit.SECONDS)
|
||||||
block.uncles = []
|
block.uncles = []
|
||||||
block.transactions = []
|
block.transactions = List.of(tx)
|
||||||
|
|
||||||
when:
|
when:
|
||||||
cache.add(BlockContainer.from(block))
|
cache.add(BlockContainer.from(block))
|
||||||
@@ -61,12 +65,14 @@ class BlocksMemCacheSpec extends Specification {
|
|||||||
when:
|
when:
|
||||||
[hash1, hash2, hash3, hash4].eachWithIndex { String hash, int i ->
|
[hash1, hash2, hash3, hash4].eachWithIndex { String hash, int i ->
|
||||||
def block = new BlockJson<TransactionRefJson>()
|
def block = new BlockJson<TransactionRefJson>()
|
||||||
|
def tx = new TransactionJson()
|
||||||
|
tx.hash = TransactionId.from(hash1)
|
||||||
block.number = 100 + i
|
block.number = 100 + i
|
||||||
block.hash = BlockHash.from(hash)
|
block.hash = BlockHash.from(hash)
|
||||||
block.totalDifficulty = BigInteger.ONE
|
block.totalDifficulty = BigInteger.ONE
|
||||||
block.timestamp = Instant.now()
|
block.timestamp = Instant.now()
|
||||||
block.uncles = []
|
block.uncles = []
|
||||||
block.transactions = []
|
block.transactions = List.of(tx)
|
||||||
|
|
||||||
cache.add(BlockContainer.from(block))
|
cache.add(BlockContainer.from(block))
|
||||||
}
|
}
|
||||||
@@ -83,4 +89,22 @@ class BlocksMemCacheSpec extends Specification {
|
|||||||
act1 == null
|
act1 == null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def "Try add not full block and read"() {
|
||||||
|
setup:
|
||||||
|
def cache = new BlocksMemCache()
|
||||||
|
def block = new BlockJson<TransactionRefJson>()
|
||||||
|
block.number = 100
|
||||||
|
block.hash = BlockHash.from(hash1)
|
||||||
|
block.totalDifficulty = BigInteger.ONE
|
||||||
|
block.timestamp = Instant.now().truncatedTo(ChronoUnit.SECONDS)
|
||||||
|
block.uncles = []
|
||||||
|
block.transactions = []
|
||||||
|
|
||||||
|
when:
|
||||||
|
cache.add(BlockContainer.from(block))
|
||||||
|
def act = cache.read(BlockId.from(hash1)).block()
|
||||||
|
then:
|
||||||
|
act == null
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,9 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
package io.emeraldpay.dshackle.upstream.calls
|
package io.emeraldpay.dshackle.upstream.calls
|
||||||
|
|
||||||
import io.emeraldpay.dshackle.cache.BlocksMemCache
|
|
||||||
import io.emeraldpay.dshackle.cache.Caches
|
import io.emeraldpay.dshackle.cache.Caches
|
||||||
import io.emeraldpay.dshackle.data.BlockContainer
|
import io.emeraldpay.dshackle.cache.HeightByHashMemCache
|
||||||
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 io.emeraldpay.dshackle.upstream.Head
|
import io.emeraldpay.dshackle.upstream.Head
|
||||||
@@ -27,7 +27,6 @@ import reactor.test.StepVerifier
|
|||||||
import spock.lang.Specification
|
import spock.lang.Specification
|
||||||
|
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
import java.time.Instant
|
|
||||||
|
|
||||||
class EthereumCallSelectorSpec extends Specification {
|
class EthereumCallSelectorSpec extends Specification {
|
||||||
|
|
||||||
@@ -233,14 +232,12 @@ class EthereumCallSelectorSpec extends Specification {
|
|||||||
def "Get height matcher for getByHash and getTransactionByBlockHash methods"() {
|
def "Get height matcher for getByHash and getTransactionByBlockHash methods"() {
|
||||||
setup:
|
setup:
|
||||||
def hash = "0xa6af163aab691919c595e2a466f0a7b01f1dff8cfd9631dee811df57064c2d32"
|
def hash = "0xa6af163aab691919c595e2a466f0a7b01f1dff8cfd9631dee811df57064c2d32"
|
||||||
def block = new BlockContainer(
|
def blockHeight = 12079192L
|
||||||
12079192L, BlockId.from(hash),
|
def cache = Mock(Caches) { caches ->
|
||||||
BigInteger.ONE, Instant.now(), false, "".bytes, null, [], 0, "upstream"
|
1 * caches.getLastHeightByHash() >> Mock(HeightByHashMemCache) { memCache ->
|
||||||
)
|
1 * memCache.read(BlockId.from(hash)) >> Mono.just(blockHeight)
|
||||||
def blockByHashCache = Mock(BlocksMemCache) {
|
}
|
||||||
1 * read(BlockId.from(hash)) >> Mono.just(block)
|
|
||||||
}
|
}
|
||||||
def cache = Caches.newBuilder().setBlockByHash(blockByHashCache).build()
|
|
||||||
def callSelector = new EthereumCallSelector(Stub(Reader), cache)
|
def callSelector = new EthereumCallSelector(Stub(Reader), cache)
|
||||||
def head = Stub(Head)
|
def head = Stub(Head)
|
||||||
|
|
||||||
@@ -318,10 +315,11 @@ class EthereumCallSelectorSpec extends Specification {
|
|||||||
def "No height matcher for getByHash method"() {
|
def "No height matcher for getByHash method"() {
|
||||||
setup:
|
setup:
|
||||||
def hash = "0xa6af163aab691919c595e2a466f0a7b01f1dff8cfd9631dee811df57064c2d32"
|
def hash = "0xa6af163aab691919c595e2a466f0a7b01f1dff8cfd9631dee811df57064c2d32"
|
||||||
def blockByHashCache = Mock(BlocksMemCache) {
|
def cache = Mock(Caches) { caches ->
|
||||||
1 * read(BlockId.from(hash)) >> resultFromCache
|
1 * caches.getLastHeightByHash() >> Mock(HeightByHashMemCache) { memCache ->
|
||||||
|
1 * memCache.read(BlockId.from(hash)) >> resultFromCache
|
||||||
|
}
|
||||||
}
|
}
|
||||||
def cache = Caches.newBuilder().setBlockByHash(blockByHashCache).build()
|
|
||||||
def callSelector = new EthereumCallSelector(Stub(Reader), cache)
|
def callSelector = new EthereumCallSelector(Stub(Reader), cache)
|
||||||
def head = Stub(Head)
|
def head = Stub(Head)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user