problem: doesn't cache transactions requested for a block

This commit is contained in:
Igor Artamonov
2020-07-20 20:34:37 -04:00
parent 9d752fc8f1
commit d3a3b6606a
4 changed files with 71 additions and 25 deletions

View File

@@ -97,9 +97,10 @@ open class Caches(
return return
} }
memTxsByHash.add(tx) memTxsByHash.add(tx)
memBlocksByHash.get(tx.blockId)?.let { block -> //TODO move subscription to the caller
redisTxsByHash?.add(tx, block) getBlocksByHash().read(tx.blockId).flatMap { block ->
} redisTxsByHash?.add(tx, block) ?: Mono.empty()
}.subscribe()
} }
fun cache(tag: Tag, block: BlockContainer) { fun cache(tag: Tag, block: BlockContainer) {
@@ -142,11 +143,11 @@ open class Caches(
val transactions = plainTransactions.map { tx -> val transactions = plainTransactions.map { tx ->
TxContainer.from(tx) TxContainer.from(tx)
} }
transactions.forEach {
cache(Tag.REQUESTED, it)
}
if (redisTxsByHash != null) { if (redisTxsByHash != null) {
job.add(Flux.fromIterable(transactions).flatMap { redisTxsByHash.add(it, block) }.then()) job.add(Flux.fromIterable(transactions)
.doOnNext { memTxsByHash.add(it) }
.flatMap { redisTxsByHash.add(it, block) }
.then())
} }
} }
} }

View File

@@ -117,7 +117,7 @@ abstract class OnTxRedisCache<T>(
} }
} }
fun add(id: TxId, value: T, block: BlockContainer?, blockHeight: Long?): Mono<Void> { open fun add(id: TxId, value: T, block: BlockContainer?, blockHeight: Long?): Mono<Void> {
return Mono.just(id) return Mono.just(id)
.flatMap { .flatMap {
val key = key(it) val key = key(it)

View File

@@ -35,7 +35,7 @@ import kotlin.math.min
/** /**
* Cache transactions in Redis, up to 24 hours. * Cache transactions in Redis, up to 24 hours.
*/ */
class TxRedisCache( open class TxRedisCache(
private val redis: RedisReactiveCommands<String, ByteArray>, private val redis: RedisReactiveCommands<String, ByteArray>,
private val chain: Chain private val chain: Chain
) : Reader<TxId, TxContainer>, ) : Reader<TxId, TxContainer>,
@@ -74,7 +74,7 @@ class TxRedisCache(
) )
} }
fun add(tx: TxContainer, block: BlockContainer): Mono<Void> { open fun add(tx: TxContainer, block: BlockContainer): Mono<Void> {
return super.add(tx.hash, tx, block, tx.height) return super.add(tx.hash, tx, block, tx.height)
} }

View File

@@ -18,6 +18,7 @@ package io.emeraldpay.dshackle.cache
import com.fasterxml.jackson.databind.ObjectMapper 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.dshackle.data.BlockId
import io.emeraldpay.dshackle.data.TxContainer import io.emeraldpay.dshackle.data.TxContainer
import io.emeraldpay.dshackle.test.TestingCommons import io.emeraldpay.dshackle.test.TestingCommons
import io.infinitape.etherjar.domain.BlockHash import io.infinitape.etherjar.domain.BlockHash
@@ -25,6 +26,7 @@ import io.infinitape.etherjar.domain.TransactionId
import io.infinitape.etherjar.rpc.json.BlockJson import io.infinitape.etherjar.rpc.json.BlockJson
import io.infinitape.etherjar.rpc.json.TransactionJson import io.infinitape.etherjar.rpc.json.TransactionJson
import io.infinitape.etherjar.rpc.json.TransactionRefJson import io.infinitape.etherjar.rpc.json.TransactionRefJson
import reactor.core.publisher.Mono
import spock.lang.Specification import spock.lang.Specification
import java.time.Instant import java.time.Instant
@@ -145,14 +147,6 @@ class CachesSpec extends Specification {
def "Cache txes of a requested block"() { def "Cache txes of a requested block"() {
setup: setup:
TxMemCache txCache = Mock()
HeightCache heightCache = Mock()
BlocksMemCache blocksCache = Mock()
def caches = Caches.newBuilder()
.setTxByHash(txCache)
.setBlockByHeight(heightCache)
.setBlockByHash(blocksCache)
.build()
def tx1 = new TransactionJson().with { def tx1 = new TransactionJson().with {
hash = TransactionId.from(hash1) hash = TransactionId.from(hash1)
@@ -166,20 +160,71 @@ class CachesSpec extends Specification {
blockNumber = 100 blockNumber = 100
it it
} }
BlockContainer block = new BlockJson().with { block ->
block.number = 100
block.hash = BlockHash.from(hash1)
block.totalDifficulty = BigInteger.ONE
block.transactions = [tx1, tx2]
block.timestamp = Instant.now()
BlockContainer.from(block)
}
def block = new BlockJson() TxMemCache txCache = Mock()
block.number = 100 HeightCache heightCache = Mock()
block.hash = BlockHash.from(hash1) BlocksMemCache blocksCache = Mock() {
block.totalDifficulty = BigInteger.ONE _ * add(block)
block.transactions = [tx1, tx2] _ * read(block.hash) >> Mono.just(block)
block.timestamp = Instant.now() }
block = BlockContainer.from(block) TxRedisCache txRedisCache = Mock()
def caches = Caches.newBuilder()
.setTxByHash(txCache)
.setBlockByHeight(heightCache)
.setBlockByHash(blocksCache)
.setTxByHash(txRedisCache)
.build()
when: when:
caches.cache(Caches.Tag.REQUESTED, block) caches.cache(Caches.Tag.REQUESTED, block)
then: then:
1 * txCache.add(TxContainer.from(tx1)) 1 * txCache.add(TxContainer.from(tx1))
1 * txCache.add(TxContainer.from(tx2)) 1 * txCache.add(TxContainer.from(tx2))
1 * txRedisCache.add(TxContainer.from(tx1), block) >> Mono.just(1).then()
1 * txRedisCache.add(TxContainer.from(tx2), block) >> Mono.just(1).then()
}
def "Cache tx with redis"() {
setup:
def tx1 = new TransactionJson().with {
hash = TransactionId.from(hash1)
blockHash = BlockHash.from(hash1)
blockNumber = 100
it
}
BlockContainer block = new BlockJson().with { block ->
block.number = 100
block.hash = BlockHash.from(hash1)
block.totalDifficulty = BigInteger.ONE
block.transactions = [tx1]
block.timestamp = Instant.now()
BlockContainer.from(block)
}
TxMemCache txCache = Mock()
HeightCache heightCache = Mock()
BlocksMemCache blocksCache = Mock()
TxRedisCache txRedisCache = Mock()
def caches = Caches.newBuilder()
.setTxByHash(txCache)
.setBlockByHeight(heightCache)
.setBlockByHash(blocksCache)
.setTxByHash(txRedisCache)
.build()
when:
caches.cache(Caches.Tag.REQUESTED, TxContainer.from(tx1))
then:
1 * blocksCache.read(block.hash) >> Mono.just(block)
1 * txRedisCache.add(TxContainer.from(tx1), block) >> Mono.just(1).then()
} }
} }