diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 67c92517..446d239d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -96,7 +96,7 @@ zeromq = "org.zeromq:jeromq:0.5.2" objgenesis = "org.objenesis:objenesis:3.1" reactor-core = { module = "io.projectreactor:reactor-core", version.ref = "reactor" } -reactor-netty = { module = "io.projectreactor.netty:reactor-netty", version = "1.0.24" } +reactor-netty = { module = "io.projectreactor.netty:reactor-netty", version = "1.0.11" } reactor-extra = { module = "io.projectreactor.addons:reactor-extra", version = "3.4.5" } reactor-kotlin = { module = "io.projectreactor.kotlin:reactor-kotlin-extensions", version = "1.1.4" } reactor-test = { module = "io.projectreactor:reactor-test", version.ref = "reactor" } diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumLikeRpcUpstream.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumLikeRpcUpstream.kt index 0ab1056f..9cb6c573 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumLikeRpcUpstream.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumLikeRpcUpstream.kt @@ -56,6 +56,7 @@ open class EthereumLikeRpcUpstream( private var hasLiveSubscriptionHead: AtomicBoolean = AtomicBoolean(false) private var validatorSubscription: Disposable? = null + private var livenessSubscription: Disposable? = null override fun getCapabilities(): Set { return if (hasLiveSubscriptionHead.get()) { @@ -88,7 +89,7 @@ open class EthereumLikeRpcUpstream( validatorSubscription = validator.start() .subscribe(this::setStatus) } - connector.hasLiveSubscriptionHead().subscribe { + livenessSubscription = connector.hasLiveSubscriptionHead().subscribe { hasLiveSubscriptionHead.set(it) eventPublisher?.publishEvent(UpstreamChangeEvent(chain, this, UpstreamChangeEvent.ChangeType.UPDATED)) } @@ -122,6 +123,8 @@ open class EthereumLikeRpcUpstream( override fun stop() { validatorSubscription?.dispose() validatorSubscription = null + livenessSubscription?.dispose() + livenessSubscription = null connector.stop() } diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/HeadLivenessValidator.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/HeadLivenessValidator.kt index f8d84084..34c5eca5 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/HeadLivenessValidator.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/HeadLivenessValidator.kt @@ -7,9 +7,9 @@ import reactor.core.scheduler.Scheduler import java.time.Duration class HeadLivenessValidator( - val head: Head, - val expectedBlockTime: Duration, - val scheduler: Scheduler, + private val head: Head, + private val expectedBlockTime: Duration, + private val scheduler: Scheduler, private val upstreamId: String ) { companion object { @@ -17,17 +17,10 @@ class HeadLivenessValidator( private val log = LoggerFactory.getLogger(HeadLivenessValidator::class.java) } - private fun fallback(): Flux { - return Flux.defer { - log.debug("head liveness check broken with timeout in $upstreamId") - Flux.just(false).concatWith(getFlux()) // emit false and then restart the Flux - } - } - fun getFlux(): Flux { // first we have moving window of 2 blocks and check that they are consecutive ones - return head.getFlux().buffer(2, 1).map { - it.last().height - it.first().height == 1L + return head.getFlux().map { it.height }.buffer(2, 1).map { + it.last() - it.first() == 1L }.scan(Pair(0, true)) { acc, value -> // then we accumulate consecutive true events, false resets counter if (value) { @@ -44,10 +37,11 @@ class HeadLivenessValidator( !value -> Flux.just(false) else -> Flux.empty() } - // finally, we timeout after we waited for double the time we needed to emit those blocks }.timeout( expectedBlockTime.multipliedBy(CHECKED_BLOCKS_UNTIL_LIVE.toLong() * 2), - fallback() - ).subscribeOn(scheduler) + Flux.just(false).doOnNext { + log.debug("head liveness check broken with timeout in $upstreamId") + } + ).repeat().subscribeOn(scheduler) } }