Improve solana lower bound detection (#416)
This commit is contained in:
@@ -4,6 +4,7 @@ import io.emeraldpay.dshackle.Chain
|
|||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import reactor.core.publisher.Flux
|
import reactor.core.publisher.Flux
|
||||||
import reactor.core.publisher.Mono
|
import reactor.core.publisher.Mono
|
||||||
|
import reactor.kotlin.core.publisher.switchIfEmpty
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
@@ -32,6 +33,8 @@ abstract class LowerBoundBlockDetector(
|
|||||||
.flatMap {
|
.flatMap {
|
||||||
notProcessing.set(false)
|
notProcessing.set(false)
|
||||||
lowerBlockDetect()
|
lowerBlockDetect()
|
||||||
|
.onErrorResume { Mono.just(LowerBlockData.default()) }
|
||||||
|
.switchIfEmpty { Mono.just(LowerBlockData.default()) } // just to trigger onNext event
|
||||||
}
|
}
|
||||||
.doOnNext {
|
.doOnNext {
|
||||||
notProcessing.set(true)
|
notProcessing.set(true)
|
||||||
|
|||||||
@@ -33,52 +33,29 @@ class SolanaLowerBoundBlockDetector(
|
|||||||
slot
|
slot
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.flatMap { slot ->
|
.flatMap {
|
||||||
val from = if (slot <= 10) {
|
|
||||||
1
|
|
||||||
} else {
|
|
||||||
slot - 10
|
|
||||||
}
|
|
||||||
reader.read(
|
reader.read(
|
||||||
JsonRpcRequest(
|
JsonRpcRequest(
|
||||||
"getBlocks",
|
"getBlock", // since getFirstAvailableBlock returns the slot of the lowest confirmed block we can directly call getBlock
|
||||||
listOf(
|
listOf(
|
||||||
from,
|
it,
|
||||||
slot,
|
mapOf(
|
||||||
|
"showRewards" to false,
|
||||||
|
"transactionDetails" to "none",
|
||||||
|
"maxSupportedTransactionVersion" to 0,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
.flatMap(JsonRpcResponse::requireResult)
|
||||||
.flatMap(JsonRpcResponse::requireResult)
|
.map { blockData ->
|
||||||
.flatMap {
|
val block = Global.objectMapper.readValue(blockData, SolanaBlock::class.java)
|
||||||
val response = Global.objectMapper.readValue(it, LongArray::class.java)
|
LowerBlockData(max(block.height, 1), it)
|
||||||
if (response == null || response.isEmpty()) {
|
}
|
||||||
Mono.empty()
|
|
||||||
} else {
|
|
||||||
val maxSlot = response.max()
|
|
||||||
reader.read(
|
|
||||||
JsonRpcRequest(
|
|
||||||
"getBlock",
|
|
||||||
listOf(
|
|
||||||
maxSlot,
|
|
||||||
mapOf(
|
|
||||||
"showRewards" to false,
|
|
||||||
"transactionDetails" to "none",
|
|
||||||
"maxSupportedTransactionVersion" to 0,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.flatMap(JsonRpcResponse::requireResult)
|
|
||||||
.map { blockData ->
|
|
||||||
val block = Global.objectMapper.readValue(blockData, SolanaBlock::class.java)
|
|
||||||
LowerBlockData(max(block.height, 1), maxSlot)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.retryWhen(
|
.retryWhen(
|
||||||
Retry
|
Retry
|
||||||
.backoff(Long.MAX_VALUE, Duration.ofSeconds(1))
|
.backoff(20, Duration.ofSeconds(1))
|
||||||
.maxBackoff(Duration.ofMinutes(3))
|
.maxBackoff(Duration.ofMinutes(3))
|
||||||
.doAfterRetry {
|
.doAfterRetry {
|
||||||
log.debug(
|
log.debug(
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import io.emeraldpay.dshackle.upstream.ethereum.EthereumLowerBoundBlockDetector
|
|||||||
import io.emeraldpay.dshackle.upstream.polkadot.PolkadotLowerBoundBlockDetector
|
import io.emeraldpay.dshackle.upstream.polkadot.PolkadotLowerBoundBlockDetector
|
||||||
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
|
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
|
||||||
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
|
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
|
||||||
import org.junit.jupiter.api.Assertions
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
import org.junit.jupiter.params.ParameterizedTest
|
import org.junit.jupiter.params.ParameterizedTest
|
||||||
import org.junit.jupiter.params.provider.Arguments
|
import org.junit.jupiter.params.provider.Arguments
|
||||||
import org.junit.jupiter.params.provider.MethodSource
|
import org.junit.jupiter.params.provider.MethodSource
|
||||||
@@ -42,7 +42,7 @@ class RecursiveLowerBoundBlockDetectorTest {
|
|||||||
.thenCancel()
|
.thenCancel()
|
||||||
.verify(Duration.ofSeconds(3))
|
.verify(Duration.ofSeconds(3))
|
||||||
|
|
||||||
Assertions.assertEquals(LowerBoundBlockDetector.LowerBlockData(17964844L), detector.getCurrentLowerBlock())
|
assertEquals(17964844L, detector.getCurrentLowerBlock().blockNumber)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@@ -68,7 +68,7 @@ class RecursiveLowerBoundBlockDetectorTest {
|
|||||||
.thenCancel()
|
.thenCancel()
|
||||||
.verify(Duration.ofSeconds(3))
|
.verify(Duration.ofSeconds(3))
|
||||||
|
|
||||||
Assertions.assertEquals(LowerBoundBlockDetector.LowerBlockData(1), detector.getCurrentLowerBlock())
|
assertEquals(1, detector.getCurrentLowerBlock().blockNumber)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -3,11 +3,10 @@ package io.emeraldpay.dshackle.upstream.solana
|
|||||||
import io.emeraldpay.dshackle.Chain
|
import io.emeraldpay.dshackle.Chain
|
||||||
import io.emeraldpay.dshackle.Global
|
import io.emeraldpay.dshackle.Global
|
||||||
import io.emeraldpay.dshackle.reader.JsonRpcReader
|
import io.emeraldpay.dshackle.reader.JsonRpcReader
|
||||||
import io.emeraldpay.dshackle.upstream.LowerBoundBlockDetector
|
|
||||||
import io.emeraldpay.dshackle.upstream.Upstream
|
import io.emeraldpay.dshackle.upstream.Upstream
|
||||||
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
|
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
|
||||||
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
|
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
|
||||||
import org.junit.jupiter.api.Assertions
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.mockito.kotlin.doReturn
|
import org.mockito.kotlin.doReturn
|
||||||
import org.mockito.kotlin.mock
|
import org.mockito.kotlin.mock
|
||||||
@@ -22,14 +21,12 @@ class SolanaLowerBoundBlockDetectorTest {
|
|||||||
val reader = mock<JsonRpcReader> {
|
val reader = mock<JsonRpcReader> {
|
||||||
on { read(JsonRpcRequest("getFirstAvailableBlock", listOf())) } doReturn
|
on { read(JsonRpcRequest("getFirstAvailableBlock", listOf())) } doReturn
|
||||||
Mono.just(JsonRpcResponse("25000000".toByteArray(), null))
|
Mono.just(JsonRpcResponse("25000000".toByteArray(), null))
|
||||||
on { read(JsonRpcRequest("getBlocks", listOf(24999990L, 25000000L))) } doReturn
|
|
||||||
Mono.just(JsonRpcResponse("[23000000, 23000005, 23000010]".toByteArray(), null))
|
|
||||||
on {
|
on {
|
||||||
read(
|
read(
|
||||||
JsonRpcRequest(
|
JsonRpcRequest(
|
||||||
"getBlock",
|
"getBlock",
|
||||||
listOf(
|
listOf(
|
||||||
23000010L,
|
25000000L,
|
||||||
mapOf(
|
mapOf(
|
||||||
"showRewards" to false,
|
"showRewards" to false,
|
||||||
"transactionDetails" to "none",
|
"transactionDetails" to "none",
|
||||||
@@ -61,10 +58,11 @@ class SolanaLowerBoundBlockDetectorTest {
|
|||||||
StepVerifier.withVirtualTime { detector.lowerBlock() }
|
StepVerifier.withVirtualTime { detector.lowerBlock() }
|
||||||
.expectSubscription()
|
.expectSubscription()
|
||||||
.expectNoEvent(Duration.ofSeconds(15))
|
.expectNoEvent(Duration.ofSeconds(15))
|
||||||
.expectNextMatches { it.blockNumber == 21000000L && it.slot == 23000010L }
|
.expectNextMatches { it.blockNumber == 21000000L && it.slot == 25000000L }
|
||||||
.thenCancel()
|
.thenCancel()
|
||||||
.verify(Duration.ofSeconds(3))
|
.verify(Duration.ofSeconds(3))
|
||||||
|
|
||||||
Assertions.assertEquals(LowerBoundBlockDetector.LowerBlockData(21000000, 23000010), detector.getCurrentLowerBlock())
|
assertEquals(21000000, detector.getCurrentLowerBlock().blockNumber)
|
||||||
|
assertEquals(25000000, detector.getCurrentLowerBlock().slot)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user