Update labels (#302)

This commit is contained in:
KirillPamPam
2023-09-19 13:11:31 +04:00
committed by GitHub
parent 5a2e5e9304
commit 674bc18f25
5 changed files with 39 additions and 34 deletions

View File

@@ -19,9 +19,7 @@ package io.emeraldpay.dshackle.rpc
import io.emeraldpay.api.proto.BlockchainOuterClass import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.api.proto.Common import io.emeraldpay.api.proto.Common
import io.emeraldpay.dshackle.Global import io.emeraldpay.dshackle.Global
import io.emeraldpay.dshackle.startup.QuorumForLabels
import io.emeraldpay.dshackle.upstream.Capability import io.emeraldpay.dshackle.upstream.Capability
import io.emeraldpay.dshackle.upstream.DefaultUpstream
import io.emeraldpay.dshackle.upstream.MultistreamHolder import io.emeraldpay.dshackle.upstream.MultistreamHolder
import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service import org.springframework.stereotype.Service
@@ -48,28 +46,21 @@ class Describe(
.addAllSupportedSubscriptions(chainUpstreams.getEgressSubscription().getAvailableTopics()) .addAllSupportedSubscriptions(chainUpstreams.getEgressSubscription().getAvailableTopics())
.setStatus(status) .setStatus(status)
.setCurrentHeight(chainUpstreams.getHead().getCurrentHeight() ?: 0) .setCurrentHeight(chainUpstreams.getHead().getCurrentHeight() ?: 0)
chainUpstreams.getAll().let { ups -> chainUpstreams.getQuorumLabels()
ups.forEach { up -> .forEach { node ->
val nodes = QuorumForLabels() val nodeDetails = BlockchainOuterClass.NodeDetails.newBuilder()
if (up is DefaultUpstream) { .setQuorum(node.quorum)
nodes.add(up.getQuorumByLabel()) .addAllLabels(
} node.labels.entries.map { label ->
nodes.getAll().forEach { node -> BlockchainOuterClass.Label.newBuilder()
val nodeDetails = BlockchainOuterClass.NodeDetails.newBuilder() .setName(label.key)
.setQuorum(node.quorum) .setValue(label.value)
.addAllLabels( .build()
node.labels.entries.map { label -> }
BlockchainOuterClass.Label.newBuilder() )
.setName(label.key) chainDescription.addNodes(nodeDetails)
.setValue(label.value)
.build()
}
)
chainDescription.addNodes(nodeDetails)
}
capabilities.addAll(up.getCapabilities())
} }
} capabilities.addAll(chainUpstreams.getCapabilities())
chainDescription.addAllCapabilities( chainDescription.addAllCapabilities(
capabilities.map { capabilities.map {
when (it) { when (it) {

View File

@@ -21,6 +21,7 @@ import io.emeraldpay.dshackle.cache.Caches
import io.emeraldpay.dshackle.cache.CachesEnabled import io.emeraldpay.dshackle.cache.CachesEnabled
import io.emeraldpay.dshackle.config.UpstreamsConfig import io.emeraldpay.dshackle.config.UpstreamsConfig
import io.emeraldpay.dshackle.reader.JsonRpcReader import io.emeraldpay.dshackle.reader.JsonRpcReader
import io.emeraldpay.dshackle.startup.QuorumForLabels
import io.emeraldpay.dshackle.startup.UpstreamChangeEvent import io.emeraldpay.dshackle.startup.UpstreamChangeEvent
import io.emeraldpay.dshackle.upstream.calls.AggregatedCallMethods import io.emeraldpay.dshackle.upstream.calls.AggregatedCallMethods
import io.emeraldpay.dshackle.upstream.calls.CallMethods import io.emeraldpay.dshackle.upstream.calls.CallMethods
@@ -63,6 +64,7 @@ abstract class Multistream(
private var cacheSubscription: Disposable? = null private var cacheSubscription: Disposable? = null
private val reconfigLock = ReentrantLock() private val reconfigLock = ReentrantLock()
private val eventLock = ReentrantLock() private val eventLock = ReentrantLock()
@Volatile
private var callMethods: CallMethods? = null private var callMethods: CallMethods? = null
private var callMethodsFactory: Factory<CallMethods> = Factory { private var callMethodsFactory: Factory<CallMethods> = Factory {
return@Factory callMethods ?: throw FunctorException("Not initialized yet") return@Factory callMethods ?: throw FunctorException("Not initialized yet")
@@ -70,7 +72,10 @@ abstract class Multistream(
private var seq = 0 private var seq = 0
protected var lagObserver: HeadLagObserver? = null protected var lagObserver: HeadLagObserver? = null
private var subscription: Disposable? = null private var subscription: Disposable? = null
@Volatile
private var capabilities: Set<Capability> = emptySet() private var capabilities: Set<Capability> = emptySet()
@Volatile
private var quorumLabels: List<QuorumForLabels.QuorumItem>? = null
private val removed: MutableMap<String, Upstream> = HashMap() private val removed: MutableMap<String, Upstream> = HashMap()
private val meters: MutableMap<String, List<Meter.Id>> = HashMap() private val meters: MutableMap<String, List<Meter.Id>> = HashMap()
private val addedUpstreams = Sinks.many() private val addedUpstreams = Sinks.many()
@@ -203,13 +208,14 @@ abstract class Multistream(
open fun onUpstreamsUpdated() { open fun onUpstreamsUpdated() {
reconfigLock.withLock { reconfigLock.withLock {
val upstreams = getAll() val upstreams = getAll()
upstreams.filter { it.isAvailable() }.map { it.getMethods() }.let { val availableUpstreams = upstreams.filter { it.isAvailable() }
availableUpstreams.map { it.getMethods() }.let {
callMethods = AggregatedCallMethods(it) callMethods = AggregatedCallMethods(it)
} }
capabilities = if (upstreams.isEmpty()) { capabilities = if (upstreams.isEmpty()) {
emptySet() emptySet()
} else { } else {
upstreams.filter { it.isAvailable() }.map { up -> availableUpstreams.map { up ->
up.getCapabilities() up.getCapabilities()
}.let { }.let {
if (it.isNotEmpty()) { if (it.isNotEmpty()) {
@@ -219,6 +225,7 @@ abstract class Multistream(
} }
} }
} }
quorumLabels = getQuorumLabels(availableUpstreams)
when { when {
upstreams.size == 1 -> { upstreams.size == 1 -> {
lagObserver?.stop() lagObserver?.stop()
@@ -230,6 +237,18 @@ abstract class Multistream(
} }
} }
private fun getQuorumLabels(ups: List<Upstream>): List<QuorumForLabels.QuorumItem> {
val nodes = QuorumForLabels()
ups.forEach { up ->
if (up is DefaultUpstream) {
nodes.add(up.getQuorumByLabel())
}
}
return nodes.getAll()
}
fun getQuorumLabels(): List<QuorumForLabels.QuorumItem> = quorumLabels ?: emptyList()
override fun observeStatus(): Flux<UpstreamAvailability> { override fun observeStatus(): Flux<UpstreamAvailability> {
val upstreamsFluxes = getAll().map { up -> val upstreamsFluxes = getAll().map { up ->
Flux.concat( Flux.concat(
@@ -457,9 +476,4 @@ abstract class Multistream(
return map.values.min() return map.values.min()
} }
} }
data class UpstreamChangeState(
val upId: String,
val status: UpstreamAvailability
)
} }

View File

@@ -54,10 +54,11 @@ class GrpcUpstreamStatus(
} }
this.nodes.set(updateNodes) this.nodes.set(updateNodes)
val labelsChanged = updateLabels != this.allLabels.get().toList()
this.allLabels.set(Collections.unmodifiableCollection(updateLabels)) this.allLabels.set(Collections.unmodifiableCollection(updateLabels))
val changed = conf.supportedMethodsList.toSet() != this.targets?.getSupportedMethods() val changed = conf.supportedMethodsList.toSet() != this.targets?.getSupportedMethods()
this.targets = DirectCallMethods(conf.supportedMethodsList.toSet()) this.targets = DirectCallMethods(conf.supportedMethodsList.toSet())
return changed return changed || labelsChanged
} }
fun getLabels(): Collection<UpstreamsConfig.Labels> { fun getLabels(): Collection<UpstreamsConfig.Labels> {

View File

@@ -81,7 +81,7 @@ class GrpcUpstreamStatusSpec extends Specification {
) )
act = status.getLabels() act = status.getLabels()
then: then:
!result result
act.toList() == [ act.toList() == [
UpstreamsConfig.Labels.fromMap([test1: "bar", test2: "baz"]) UpstreamsConfig.Labels.fromMap([test1: "bar", test2: "baz"])
] ]
@@ -125,7 +125,7 @@ class GrpcUpstreamStatusSpec extends Specification {
) )
act = status.getLabels() act = status.getLabels()
then: then:
!result result
act.toList() == [ act.toList() == [
UpstreamsConfig.Labels.fromMap([test: "bar", fix: "value"]) UpstreamsConfig.Labels.fromMap([test: "bar", fix: "value"])
] ]

View File

@@ -72,7 +72,6 @@ class IntegrationTest {
val result = stub.describe(BlockchainOuterClass.DescribeRequest.newBuilder().build()) val result = stub.describe(BlockchainOuterClass.DescribeRequest.newBuilder().build())
Assertions.assertThat(result.chainsCount).isEqualTo(1) Assertions.assertThat(result.chainsCount).isEqualTo(1)
Assertions.assertThat(result.chainsList[0].chain).isEqualTo(ChainRef.CHAIN_ETHEREUM__MAINNET) Assertions.assertThat(result.chainsList[0].chain).isEqualTo(ChainRef.CHAIN_ETHEREUM__MAINNET)
Assertions.assertThat(result.chainsList[0].nodesCount).isEqualTo(1)
} }
@TestConfiguration @TestConfiguration