better solution
This commit is contained in:
@@ -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()}]")
|
||||
}
|
||||
|
||||
@@ -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)))
|
||||
|
||||
|
||||
@@ -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<Chain, UpstreamsConfig.Options> {
|
||||
val defaultOptions = HashMap<Chain, UpstreamsConfig.Options>()
|
||||
config.defaultOptions.forEach { defaultsConfig ->
|
||||
|
||||
@@ -156,10 +156,6 @@ class FilteredApis(
|
||||
}
|
||||
|
||||
override fun subscribe(subscriber: Subscriber<in Upstream>) {
|
||||
if (allUpstreams.none { matcher.matches(it) }) {
|
||||
Flux.empty<Upstream>().subscribe(subscriber)
|
||||
return
|
||||
}
|
||||
// initially try only standard upstreams
|
||||
val first = Flux.fromIterable(primaryUpstreams)
|
||||
val second = Flux.fromIterable(secondaryUpstreams)
|
||||
|
||||
@@ -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"() {
|
||||
|
||||
Reference in New Issue
Block a user