From 69f1f18a5afa637c008a2613dc40a98b015c4e14 Mon Sep 17 00:00:00 2001 From: Maxksim Fomenkov Date: Thu, 29 Sep 2022 02:20:26 +0300 Subject: [PATCH] better solution --- src/main/kotlin/io/emeraldpay/dshackle/SilentException.kt | 3 +++ src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt | 7 +++++++ .../io/emeraldpay/dshackle/startup/ConfiguredUpstreams.kt | 6 ++++++ .../io/emeraldpay/dshackle/upstream/FilteredApis.kt | 4 ---- .../io/emeraldpay/dshackle/rpc/NativeCallSpec.groovy | 8 ++++++-- 5 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/io/emeraldpay/dshackle/SilentException.kt b/src/main/kotlin/io/emeraldpay/dshackle/SilentException.kt index 7b15b6c0..e92e67f1 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/SilentException.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/SilentException.kt @@ -15,6 +15,7 @@ */ package io.emeraldpay.dshackle +import io.emeraldpay.dshackle.upstream.Selector import io.emeraldpay.grpc.Chain /** @@ -30,4 +31,6 @@ open class SilentException(message: String) : Exception(message) { } class DataUnavailable(val code: String) : SilentException("Data is unavailable: $code") + + class NoMatchingUpstream(matcher: Selector.LabelSelectorMatcher) : SilentException("No configured upstream matching selector [${matcher.describeInternal()}]") } diff --git a/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt b/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt index 6867a786..a6d99c3e 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt @@ -24,6 +24,7 @@ import io.emeraldpay.dshackle.SilentException import io.emeraldpay.dshackle.quorum.CallQuorum import io.emeraldpay.dshackle.quorum.NotLaggingQuorum import io.emeraldpay.dshackle.quorum.QuorumReaderFactory +import io.emeraldpay.dshackle.startup.ConfiguredUpstreams import io.emeraldpay.dshackle.upstream.ApiSource import io.emeraldpay.dshackle.upstream.Multistream import io.emeraldpay.dshackle.upstream.MultistreamHolder @@ -51,6 +52,7 @@ import java.util.EnumMap @Service open class NativeCall( @Autowired private val multistreamHolder: MultistreamHolder, + @Autowired private val configuredUpstreams: ConfiguredUpstreams, @Autowired private val signer: ResponseSigner ) { @@ -150,6 +152,11 @@ open class NativeCall( return Flux.error(CallFailure(0, SilentException.UnsupportedBlockchain(request.chain.number))) } + val matcher = Selector.convertToMatcher(request.selector) + if (!configuredUpstreams.hasMatchingUpstream(chain, matcher)) { + return Flux.error(CallFailure(0, SilentException.NoMatchingUpstream(matcher))) + } + val upstream = multistreamHolder.getUpstream(chain) ?: return Flux.error(CallFailure(0, SilentException.UnsupportedBlockchain(chain))) diff --git a/src/main/kotlin/io/emeraldpay/dshackle/startup/ConfiguredUpstreams.kt b/src/main/kotlin/io/emeraldpay/dshackle/startup/ConfiguredUpstreams.kt index d59b3348..250361d9 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/startup/ConfiguredUpstreams.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/startup/ConfiguredUpstreams.kt @@ -25,6 +25,7 @@ import io.emeraldpay.dshackle.upstream.CurrentMultistreamHolder import io.emeraldpay.dshackle.upstream.Head import io.emeraldpay.dshackle.upstream.HttpRpcFactory import io.emeraldpay.dshackle.upstream.MergedHead +import io.emeraldpay.dshackle.upstream.Selector import io.emeraldpay.dshackle.upstream.Upstream import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinRpcHead import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinRpcUpstream @@ -107,6 +108,11 @@ open class ConfiguredUpstreams( } } + fun hasMatchingUpstream(chain: Chain, matcher: Selector.LabelSelectorMatcher): Boolean = + config.upstreams.any { up -> + up.chain?.equals(chain.chainName, ignoreCase = true) ?: true && matcher.matches(up.labels) + } + private fun buildDefaultOptions(config: UpstreamsConfig): HashMap { val defaultOptions = HashMap() config.defaultOptions.forEach { defaultsConfig -> diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/FilteredApis.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/FilteredApis.kt index d7f3ede3..5f72e89b 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/FilteredApis.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/FilteredApis.kt @@ -156,10 +156,6 @@ class FilteredApis( } override fun subscribe(subscriber: Subscriber) { - if (allUpstreams.none { matcher.matches(it) }) { - Flux.empty().subscribe(subscriber) - return - } // initially try only standard upstreams val first = Flux.fromIterable(primaryUpstreams) val second = Flux.fromIterable(secondaryUpstreams) diff --git a/src/test/groovy/io/emeraldpay/dshackle/rpc/NativeCallSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/rpc/NativeCallSpec.groovy index 2704fdbb..1d27097a 100644 --- a/src/test/groovy/io/emeraldpay/dshackle/rpc/NativeCallSpec.groovy +++ b/src/test/groovy/io/emeraldpay/dshackle/rpc/NativeCallSpec.groovy @@ -24,6 +24,7 @@ import io.emeraldpay.dshackle.Global import io.emeraldpay.dshackle.quorum.QuorumReaderFactory import io.emeraldpay.dshackle.quorum.QuorumRpcReader import io.emeraldpay.dshackle.reader.Reader +import io.emeraldpay.dshackle.startup.ConfiguredUpstreams import io.emeraldpay.dshackle.test.MultistreamHolderMock import io.emeraldpay.dshackle.test.TestingCommons import io.emeraldpay.dshackle.quorum.AlwaysQuorum @@ -51,14 +52,17 @@ class NativeCallSpec extends Specification { ObjectMapper objectMapper = Global.objectMapper - def nativeCall(MultistreamHolder upstreams = null, ResponseSigner signer = null) { + def nativeCall(MultistreamHolder upstreams = null, ResponseSigner signer = null, ConfiguredUpstreams configuredUpstreams = null) { if (upstreams == null) { upstreams = Stub(MultistreamHolder) } if (signer == null) { signer = Stub(ResponseSigner) } - new NativeCall(upstreams, signer) + if (configuredUpstreams == null) { + configuredUpstreams = Stub(ConfiguredUpstreams) + } + new NativeCall(upstreams, configuredUpstreams, signer) } def "Tries router first"() {