solution: refactoring
This commit is contained in:
@@ -17,6 +17,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.startup.QuorumForLabels
|
||||||
import io.emeraldpay.dshackle.upstream.*
|
import io.emeraldpay.dshackle.upstream.*
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstream
|
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstream
|
||||||
import io.emeraldpay.dshackle.upstream.grpc.GrpcUpstream
|
import io.emeraldpay.dshackle.upstream.grpc.GrpcUpstream
|
||||||
@@ -43,13 +44,13 @@ class Describe(
|
|||||||
.setStatus(status)
|
.setStatus(status)
|
||||||
chainUpstreams.getAll().let { ups ->
|
chainUpstreams.getAll().let { ups ->
|
||||||
ups.forEach { up ->
|
ups.forEach { up ->
|
||||||
val nodes = NodeDetailsList()
|
val nodes = QuorumForLabels()
|
||||||
if (up is EthereumUpstream) {
|
if (up is EthereumUpstream) {
|
||||||
nodes.add(up.node)
|
nodes.add(up.node)
|
||||||
} else if (up is GrpcUpstream) {
|
} else if (up is GrpcUpstream) {
|
||||||
nodes.add(up.getNodes())
|
nodes.add(up.getNodes())
|
||||||
}
|
}
|
||||||
nodes.getNodes().forEach { node ->
|
nodes.getAll().forEach { node ->
|
||||||
val nodeDetails = BlockchainOuterClass.NodeDetails.newBuilder()
|
val nodeDetails = BlockchainOuterClass.NodeDetails.newBuilder()
|
||||||
.setQuorum(node.quorum)
|
.setQuorum(node.quorum)
|
||||||
.addAllLabels(node.labels.entries.map { label ->
|
.addAllLabels(node.labels.entries.map { label ->
|
||||||
|
|||||||
@@ -13,12 +13,14 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package io.emeraldpay.dshackle.upstream
|
package io.emeraldpay.dshackle.startup
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
import io.emeraldpay.dshackle.FileResolver
|
import io.emeraldpay.dshackle.FileResolver
|
||||||
import io.emeraldpay.dshackle.config.UpstreamsConfig
|
import io.emeraldpay.dshackle.config.UpstreamsConfig
|
||||||
import io.emeraldpay.dshackle.config.UpstreamsConfigReader
|
import io.emeraldpay.dshackle.config.UpstreamsConfigReader
|
||||||
|
import io.emeraldpay.dshackle.upstream.CurrentUpstreams
|
||||||
|
import io.emeraldpay.dshackle.upstream.calls.ManagedCallMethods
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.DirectEthereumApi
|
import io.emeraldpay.dshackle.upstream.ethereum.DirectEthereumApi
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstream
|
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstream
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.EthereumWs
|
import io.emeraldpay.dshackle.upstream.ethereum.EthereumWs
|
||||||
@@ -172,7 +174,7 @@ open class ConfiguredUpstreams(
|
|||||||
val ethereumUpstream = EthereumUpstream(
|
val ethereumUpstream = EthereumUpstream(
|
||||||
config.id!!,
|
config.id!!,
|
||||||
chain, rpcApi!!, wsApi, options,
|
chain, rpcApi!!, wsApi, options,
|
||||||
NodeDetailsList.NodeDetails(1, config.labels),
|
QuorumForLabels.QuorumItem(1, config.labels),
|
||||||
methods)
|
methods)
|
||||||
ethereumUpstream.start()
|
ethereumUpstream.start()
|
||||||
currentUpstreams.update(UpstreamChange(chain, ethereumUpstream, UpstreamChange.ChangeType.ADDED))
|
currentUpstreams.update(UpstreamChange(chain, ethereumUpstream, UpstreamChange.ChangeType.ADDED))
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package io.emeraldpay.dshackle.upstream
|
package io.emeraldpay.dshackle.startup
|
||||||
|
|
||||||
import io.emeraldpay.dshackle.config.UpstreamsConfig
|
import io.emeraldpay.dshackle.config.UpstreamsConfig
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@@ -22,17 +22,20 @@ import kotlin.collections.ArrayList
|
|||||||
import kotlin.concurrent.read
|
import kotlin.concurrent.read
|
||||||
import kotlin.concurrent.write
|
import kotlin.concurrent.write
|
||||||
|
|
||||||
class NodeDetailsList {
|
/**
|
||||||
|
* Summary details over few upstream nodes. Provides aggregate quorum for nodes with particular label
|
||||||
|
*/
|
||||||
|
class QuorumForLabels {
|
||||||
|
|
||||||
private val lock = ReentrantReadWriteLock()
|
private val lock = ReentrantReadWriteLock()
|
||||||
private val nodes = ArrayList<NodeDetails>()
|
private val nodes = ArrayList<QuorumItem>()
|
||||||
|
|
||||||
fun add(node: NodeDetails) {
|
fun add(node: QuorumItem) {
|
||||||
lock.read {
|
lock.read {
|
||||||
val existing = nodes.find { it.labels == node.labels }
|
val existing = nodes.find { it.labels == node.labels }
|
||||||
lock.write {
|
lock.write {
|
||||||
if (existing != null) {
|
if (existing != null) {
|
||||||
val merged = NodeDetails(existing.quorum + node.quorum, existing.labels)
|
val merged = QuorumItem(existing.quorum + node.quorum, existing.labels)
|
||||||
nodes.remove(existing)
|
nodes.remove(existing)
|
||||||
nodes.add(merged)
|
nodes.add(merged)
|
||||||
} else {
|
} else {
|
||||||
@@ -42,15 +45,18 @@ class NodeDetailsList {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun add(nodes: NodeDetailsList) {
|
fun add(nodes: QuorumForLabels) {
|
||||||
nodes.nodes.forEach { node -> this.add(node) }
|
nodes.nodes.forEach { node -> this.add(node) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getNodes(): List<NodeDetails> {
|
fun getAll(): List<QuorumItem> {
|
||||||
return Collections.unmodifiableList(nodes)
|
return Collections.unmodifiableList(nodes)
|
||||||
}
|
}
|
||||||
|
|
||||||
class NodeDetails(val quorum: Int, val labels: UpstreamsConfig.Labels) {
|
/**
|
||||||
|
* Details for a single element (upstream, node or aggregation)
|
||||||
|
*/
|
||||||
|
class QuorumItem(val quorum: Int, val labels: UpstreamsConfig.Labels) {
|
||||||
companion object {
|
companion object {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -13,10 +13,11 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package io.emeraldpay.dshackle.upstream
|
package io.emeraldpay.dshackle.startup
|
||||||
|
|
||||||
import io.emeraldpay.dshackle.cache.Caches
|
import io.emeraldpay.dshackle.cache.Caches
|
||||||
import io.emeraldpay.dshackle.cache.CachesEnabled
|
import io.emeraldpay.dshackle.cache.CachesEnabled
|
||||||
|
import io.emeraldpay.dshackle.upstream.Upstream
|
||||||
import io.emeraldpay.grpc.Chain
|
import io.emeraldpay.grpc.Chain
|
||||||
|
|
||||||
class UpstreamChange(
|
class UpstreamChange(
|
||||||
@@ -18,6 +18,8 @@ package io.emeraldpay.dshackle.upstream
|
|||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
import io.emeraldpay.dshackle.cache.*
|
import io.emeraldpay.dshackle.cache.*
|
||||||
import io.emeraldpay.dshackle.config.UpstreamsConfig
|
import io.emeraldpay.dshackle.config.UpstreamsConfig
|
||||||
|
import io.emeraldpay.dshackle.upstream.calls.AggregatedCallMethods
|
||||||
|
import io.emeraldpay.dshackle.upstream.calls.CallMethods
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.EthereumHead
|
import io.emeraldpay.dshackle.upstream.ethereum.EthereumHead
|
||||||
import org.springframework.context.Lifecycle
|
import org.springframework.context.Lifecycle
|
||||||
import reactor.core.Disposable
|
import reactor.core.Disposable
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ package io.emeraldpay.dshackle.upstream
|
|||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
import io.emeraldpay.dshackle.cache.Caches
|
import io.emeraldpay.dshackle.cache.Caches
|
||||||
import io.emeraldpay.dshackle.cache.CachesEnabled
|
import io.emeraldpay.dshackle.cache.CachesEnabled
|
||||||
|
import io.emeraldpay.dshackle.startup.UpstreamChange
|
||||||
|
import io.emeraldpay.dshackle.upstream.calls.CallMethods
|
||||||
|
import io.emeraldpay.dshackle.upstream.calls.QuorumBasedMethods
|
||||||
import io.emeraldpay.grpc.Chain
|
import io.emeraldpay.grpc.Chain
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import org.springframework.beans.factory.annotation.Autowired
|
import org.springframework.beans.factory.annotation.Autowired
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
package io.emeraldpay.dshackle.upstream
|
package io.emeraldpay.dshackle.upstream
|
||||||
|
|
||||||
import io.emeraldpay.dshackle.config.UpstreamsConfig
|
import io.emeraldpay.dshackle.config.UpstreamsConfig
|
||||||
|
import io.emeraldpay.dshackle.upstream.calls.CallMethods
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.DirectEthereumApi
|
import io.emeraldpay.dshackle.upstream.ethereum.DirectEthereumApi
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.EthereumHead
|
import io.emeraldpay.dshackle.upstream.ethereum.EthereumHead
|
||||||
import reactor.core.publisher.Flux
|
import reactor.core.publisher.Flux
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package io.emeraldpay.dshackle.upstream
|
package io.emeraldpay.dshackle.upstream
|
||||||
|
|
||||||
|
import io.emeraldpay.dshackle.upstream.calls.CallMethods
|
||||||
import io.emeraldpay.grpc.Chain
|
import io.emeraldpay.grpc.Chain
|
||||||
import reactor.core.publisher.Flux
|
import reactor.core.publisher.Flux
|
||||||
|
|
||||||
|
|||||||
@@ -13,12 +13,15 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package io.emeraldpay.dshackle.upstream
|
package io.emeraldpay.dshackle.upstream.calls
|
||||||
|
|
||||||
import io.emeraldpay.dshackle.quorum.CallQuorum
|
import io.emeraldpay.dshackle.quorum.CallQuorum
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.HashSet
|
import kotlin.collections.HashSet
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Aggregation over several parent configuration. It dispatches call to a first delegate that supports it.
|
||||||
|
*/
|
||||||
class AggregatedCallMethods(
|
class AggregatedCallMethods(
|
||||||
private val delegates: Collection<CallMethods>
|
private val delegates: Collection<CallMethods>
|
||||||
): CallMethods {
|
): CallMethods {
|
||||||
@@ -31,24 +34,39 @@ class AggregatedCallMethods(
|
|||||||
allMethods = Collections.unmodifiableSet(buf)
|
allMethods = Collections.unmodifiableSet(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds first delegate that has Allowed that method and returns its Quorum
|
||||||
|
*/
|
||||||
override fun getQuorumFor(method: String): CallQuorum {
|
override fun getQuorumFor(method: String): CallQuorum {
|
||||||
return delegates.find {
|
return delegates.find {
|
||||||
it.isAllowed(method)
|
it.isAllowed(method)
|
||||||
}?.getQuorumFor(method) ?: throw IllegalStateException("No quorum for $method")
|
}?.getQuorumFor(method) ?: throw IllegalStateException("No quorum for $method")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if ANY of delegates supports the method
|
||||||
|
*/
|
||||||
override fun isAllowed(method: String): Boolean {
|
override fun isAllowed(method: String): Boolean {
|
||||||
return delegates.any { it.isAllowed(method) }
|
return delegates.any { it.isAllowed(method) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all available methods, accessible through at least one of delegates
|
||||||
|
*/
|
||||||
override fun getSupportedMethods(): Set<String> {
|
override fun getSupportedMethods(): Set<String> {
|
||||||
return allMethods
|
return allMethods
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if there is at least one delegate that allows the method and it's hardcoded on that delegate
|
||||||
|
*/
|
||||||
override fun isHardcoded(method: String): Boolean {
|
override fun isHardcoded(method: String): Boolean {
|
||||||
return delegates.any { it.isAllowed(method) && it.isHardcoded(method) }
|
return delegates.any { it.isAllowed(method) && it.isHardcoded(method) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executed the method on the first delegate that supports it as a hardcoded method
|
||||||
|
*/
|
||||||
override fun executeHardcoded(method: String): Any {
|
override fun executeHardcoded(method: String): Any {
|
||||||
return delegates.find {
|
return delegates.find {
|
||||||
it.isAllowed(method) && it.isHardcoded(method)
|
it.isAllowed(method) && it.isHardcoded(method)
|
||||||
@@ -13,14 +13,37 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package io.emeraldpay.dshackle.upstream
|
package io.emeraldpay.dshackle.upstream.calls
|
||||||
|
|
||||||
import io.emeraldpay.dshackle.quorum.CallQuorum
|
import io.emeraldpay.dshackle.quorum.CallQuorum
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration for upstream calls
|
||||||
|
*/
|
||||||
interface CallMethods {
|
interface CallMethods {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return CallQuorum configured for the specified method
|
||||||
|
*/
|
||||||
fun getQuorumFor(method: String): CallQuorum
|
fun getQuorumFor(method: String): CallQuorum
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return false is call for that method is not allowed. Allowed method may be also Hardcoded
|
||||||
|
*/
|
||||||
fun isAllowed(method: String): Boolean
|
fun isAllowed(method: String): Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return list of all allowed methods.
|
||||||
|
*/
|
||||||
fun getSupportedMethods(): Set<String>
|
fun getSupportedMethods(): Set<String>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if the method should not be executed on upstream, but accessed through this class
|
||||||
|
*/
|
||||||
fun isHardcoded(method: String): Boolean
|
fun isHardcoded(method: String): Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read [supposed to be predefined] method from this config
|
||||||
|
*/
|
||||||
fun executeHardcoded(method: String): Any
|
fun executeHardcoded(method: String): Any
|
||||||
}
|
}
|
||||||
@@ -13,12 +13,15 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package io.emeraldpay.dshackle.upstream
|
package io.emeraldpay.dshackle.upstream.calls
|
||||||
|
|
||||||
import io.emeraldpay.dshackle.quorum.AlwaysQuorum
|
import io.emeraldpay.dshackle.quorum.AlwaysQuorum
|
||||||
import io.emeraldpay.dshackle.quorum.CallQuorum
|
import io.emeraldpay.dshackle.quorum.CallQuorum
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration that uses [AlwaysQuorum] for all available methods. The methods list itself
|
||||||
|
* is provided in constructor (or empty otherwise)
|
||||||
|
*/
|
||||||
class DirectCallMethods(private val methods: Set<String>) : CallMethods {
|
class DirectCallMethods(private val methods: Set<String>) : CallMethods {
|
||||||
|
|
||||||
constructor(): this(emptySet())
|
constructor(): this(emptySet())
|
||||||
@@ -13,12 +13,17 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package io.emeraldpay.dshackle.upstream
|
package io.emeraldpay.dshackle.upstream.calls
|
||||||
|
|
||||||
import io.emeraldpay.dshackle.quorum.AlwaysQuorum
|
import io.emeraldpay.dshackle.quorum.AlwaysQuorum
|
||||||
import io.emeraldpay.dshackle.quorum.CallQuorum
|
import io.emeraldpay.dshackle.quorum.CallQuorum
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper on top of another configuration, that may disable or enable additional methods on top of it.
|
||||||
|
* If a new method enabled, then its Quorum will be [AlwaysQuorum]. For other methods it delegates all to the provided
|
||||||
|
* parent config.
|
||||||
|
*/
|
||||||
class ManagedCallMethods(
|
class ManagedCallMethods(
|
||||||
private val delegate: CallMethods,
|
private val delegate: CallMethods,
|
||||||
private val enabled: Set<String>,
|
private val enabled: Set<String>,
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package io.emeraldpay.dshackle.upstream
|
package io.emeraldpay.dshackle.upstream.calls
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
import io.emeraldpay.dshackle.quorum.*
|
import io.emeraldpay.dshackle.quorum.*
|
||||||
@@ -22,6 +22,10 @@ import io.infinitape.etherjar.rpc.JacksonRpcConverter
|
|||||||
import io.infinitape.etherjar.rpc.RpcException
|
import io.infinitape.etherjar.rpc.RpcException
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default configuration for Ethereum based RPC. Defines optimal Quorum strategies for different methods, and provides
|
||||||
|
* hardcoded results for base methods, such as `net_version`, `web3_clientVersion` and similar
|
||||||
|
*/
|
||||||
class QuorumBasedMethods(
|
class QuorumBasedMethods(
|
||||||
private val objectMapper: ObjectMapper,
|
private val objectMapper: ObjectMapper,
|
||||||
private val chain: Chain
|
private val chain: Chain
|
||||||
@@ -18,7 +18,7 @@ package io.emeraldpay.dshackle.upstream.ethereum
|
|||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
import io.emeraldpay.dshackle.Defaults
|
import io.emeraldpay.dshackle.Defaults
|
||||||
import io.emeraldpay.dshackle.cache.Caches
|
import io.emeraldpay.dshackle.cache.Caches
|
||||||
import io.emeraldpay.dshackle.upstream.CallMethods
|
import io.emeraldpay.dshackle.upstream.calls.CallMethods
|
||||||
import io.grpc.Status
|
import io.grpc.Status
|
||||||
import io.grpc.StatusRuntimeException
|
import io.grpc.StatusRuntimeException
|
||||||
import io.infinitape.etherjar.domain.BlockHash
|
import io.infinitape.etherjar.domain.BlockHash
|
||||||
|
|||||||
@@ -18,7 +18,10 @@ package io.emeraldpay.dshackle.upstream.ethereum
|
|||||||
import io.emeraldpay.dshackle.cache.Caches
|
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.startup.QuorumForLabels
|
||||||
import io.emeraldpay.dshackle.upstream.*
|
import io.emeraldpay.dshackle.upstream.*
|
||||||
|
import io.emeraldpay.dshackle.upstream.calls.CallMethods
|
||||||
|
import io.emeraldpay.dshackle.upstream.calls.DirectCallMethods
|
||||||
import io.emeraldpay.grpc.Chain
|
import io.emeraldpay.grpc.Chain
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import org.springframework.context.Lifecycle
|
import org.springframework.context.Lifecycle
|
||||||
@@ -32,12 +35,12 @@ open class EthereumUpstream(
|
|||||||
private val api: DirectEthereumApi,
|
private val api: DirectEthereumApi,
|
||||||
private val ethereumWs: EthereumWs? = null,
|
private val ethereumWs: EthereumWs? = null,
|
||||||
private val options: UpstreamsConfig.Options,
|
private val options: UpstreamsConfig.Options,
|
||||||
val node: NodeDetailsList.NodeDetails,
|
val node: QuorumForLabels.QuorumItem,
|
||||||
private val targets: CallMethods
|
private val targets: CallMethods
|
||||||
): DefaultUpstream(), CachesEnabled, Lifecycle {
|
): DefaultUpstream(), CachesEnabled, Lifecycle {
|
||||||
|
|
||||||
constructor(id: String, chain: Chain, api: DirectEthereumApi): this(id, chain, api, null,
|
constructor(id: String, chain: Chain, api: DirectEthereumApi): this(id, chain, api, null,
|
||||||
UpstreamsConfig.Options.getDefaults(), NodeDetailsList.NodeDetails(1, UpstreamsConfig.Labels()),
|
UpstreamsConfig.Options.getDefaults(), QuorumForLabels.QuorumItem(1, UpstreamsConfig.Labels()),
|
||||||
DirectCallMethods())
|
DirectCallMethods())
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -24,13 +24,15 @@ import io.emeraldpay.dshackle.Defaults
|
|||||||
import io.emeraldpay.dshackle.cache.Caches
|
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.startup.QuorumForLabels
|
||||||
import io.emeraldpay.dshackle.upstream.*
|
import io.emeraldpay.dshackle.upstream.*
|
||||||
|
import io.emeraldpay.dshackle.upstream.calls.CallMethods
|
||||||
|
import io.emeraldpay.dshackle.upstream.calls.DirectCallMethods
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.DefaultEthereumHead
|
import io.emeraldpay.dshackle.upstream.ethereum.DefaultEthereumHead
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.DirectEthereumApi
|
import io.emeraldpay.dshackle.upstream.ethereum.DirectEthereumApi
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.EthereumHead
|
import io.emeraldpay.dshackle.upstream.ethereum.EthereumHead
|
||||||
import io.emeraldpay.grpc.Chain
|
import io.emeraldpay.grpc.Chain
|
||||||
import io.infinitape.etherjar.domain.BlockHash
|
import io.infinitape.etherjar.domain.BlockHash
|
||||||
import io.infinitape.etherjar.domain.TransactionId
|
|
||||||
import io.infinitape.etherjar.rpc.*
|
import io.infinitape.etherjar.rpc.*
|
||||||
import io.infinitape.etherjar.rpc.emerald.ReactorEmeraldClient
|
import io.infinitape.etherjar.rpc.emerald.ReactorEmeraldClient
|
||||||
import io.infinitape.etherjar.rpc.json.BlockJson
|
import io.infinitape.etherjar.rpc.json.BlockJson
|
||||||
@@ -62,7 +64,7 @@ open class GrpcUpstream(
|
|||||||
private var caches: Caches? = null
|
private var caches: Caches? = null
|
||||||
|
|
||||||
private val options = UpstreamsConfig.Options.getDefaults()
|
private val options = UpstreamsConfig.Options.getDefaults()
|
||||||
private val nodes = AtomicReference<NodeDetailsList>(NodeDetailsList())
|
private val nodes = AtomicReference<QuorumForLabels>(QuorumForLabels())
|
||||||
private val head = DefaultEthereumHead()
|
private val head = DefaultEthereumHead()
|
||||||
private var targets: CallMethods? = null
|
private var targets: CallMethods? = null
|
||||||
private var headSubscription: Disposable? = null
|
private var headSubscription: Disposable? = null
|
||||||
@@ -148,10 +150,10 @@ open class GrpcUpstream(
|
|||||||
|
|
||||||
fun init(conf: BlockchainOuterClass.DescribeChain) {
|
fun init(conf: BlockchainOuterClass.DescribeChain) {
|
||||||
targets = DirectCallMethods(conf.supportedMethodsList.toSet())
|
targets = DirectCallMethods(conf.supportedMethodsList.toSet())
|
||||||
val nodes = NodeDetailsList()
|
val nodes = QuorumForLabels()
|
||||||
val allLabels = ArrayList<UpstreamsConfig.Labels>()
|
val allLabels = ArrayList<UpstreamsConfig.Labels>()
|
||||||
conf.nodesList.forEach { remoteNode ->
|
conf.nodesList.forEach { remoteNode ->
|
||||||
val node = NodeDetailsList.NodeDetails(remoteNode.quorum,
|
val node = QuorumForLabels.QuorumItem(remoteNode.quorum,
|
||||||
remoteNode.labelsList.let { provided ->
|
remoteNode.labelsList.let { provided ->
|
||||||
val labels = UpstreamsConfig.Labels()
|
val labels = UpstreamsConfig.Labels()
|
||||||
provided.forEach {
|
provided.forEach {
|
||||||
@@ -176,7 +178,7 @@ open class GrpcUpstream(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getNodes(): NodeDetailsList {
|
fun getNodes(): QuorumForLabels {
|
||||||
return nodes.get()
|
return nodes.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,7 +193,7 @@ open class GrpcUpstream(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun isAvailable(): Boolean {
|
override fun isAvailable(): Boolean {
|
||||||
return getStatus() == UpstreamAvailability.OK && head.getCurrent() != null && nodes.get().getNodes().any {
|
return getStatus() == UpstreamAvailability.OK && head.getCurrent() != null && nodes.get().getAll().any {
|
||||||
it.quorum > 0
|
it.quorum > 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import io.emeraldpay.dshackle.Defaults
|
|||||||
import io.emeraldpay.dshackle.FileResolver
|
import io.emeraldpay.dshackle.FileResolver
|
||||||
import io.emeraldpay.dshackle.config.UpstreamsConfig
|
import io.emeraldpay.dshackle.config.UpstreamsConfig
|
||||||
import io.emeraldpay.dshackle.upstream.UpstreamAvailability
|
import io.emeraldpay.dshackle.upstream.UpstreamAvailability
|
||||||
import io.emeraldpay.dshackle.upstream.UpstreamChange
|
import io.emeraldpay.dshackle.startup.UpstreamChange
|
||||||
import io.emeraldpay.grpc.Chain
|
import io.emeraldpay.grpc.Chain
|
||||||
import io.grpc.ManagedChannelBuilder
|
import io.grpc.ManagedChannelBuilder
|
||||||
import io.grpc.netty.NettyChannelBuilder
|
import io.grpc.netty.NettyChannelBuilder
|
||||||
@@ -36,7 +36,6 @@ import reactor.core.publisher.Flux
|
|||||||
import java.net.ConnectException
|
import java.net.ConnectException
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.Executors
|
|
||||||
import java.util.concurrent.atomic.AtomicReference
|
import java.util.concurrent.atomic.AtomicReference
|
||||||
import java.util.concurrent.locks.ReentrantLock
|
import java.util.concurrent.locks.ReentrantLock
|
||||||
import kotlin.concurrent.withLock
|
import kotlin.concurrent.withLock
|
||||||
|
|||||||
@@ -18,13 +18,11 @@ package io.emeraldpay.dshackle.test
|
|||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
import com.google.protobuf.ByteString
|
import com.google.protobuf.ByteString
|
||||||
import io.emeraldpay.api.proto.BlockchainOuterClass
|
import io.emeraldpay.api.proto.BlockchainOuterClass
|
||||||
import io.emeraldpay.dshackle.upstream.DirectCallMethods
|
import io.emeraldpay.dshackle.upstream.calls.DirectCallMethods
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.DirectEthereumApi
|
import io.emeraldpay.dshackle.upstream.ethereum.DirectEthereumApi
|
||||||
import io.emeraldpay.grpc.Chain
|
import io.emeraldpay.grpc.Chain
|
||||||
import io.grpc.stub.StreamObserver
|
import io.grpc.stub.StreamObserver
|
||||||
import io.infinitape.etherjar.rpc.ReactorRpcClient
|
import io.infinitape.etherjar.rpc.ReactorRpcClient
|
||||||
import io.infinitape.etherjar.rpc.RpcClient
|
|
||||||
import io.infinitape.etherjar.rpc.RpcException
|
|
||||||
import io.infinitape.etherjar.rpc.RpcResponseError
|
import io.infinitape.etherjar.rpc.RpcResponseError
|
||||||
import io.infinitape.etherjar.rpc.json.ResponseJson
|
import io.infinitape.etherjar.rpc.json.ResponseJson
|
||||||
import org.jetbrains.annotations.NotNull
|
import org.jetbrains.annotations.NotNull
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
package io.emeraldpay.dshackle.test
|
package io.emeraldpay.dshackle.test
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
import io.emeraldpay.dshackle.upstream.DirectCallMethods
|
import io.emeraldpay.dshackle.upstream.calls.DirectCallMethods
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.DirectEthereumApi
|
import io.emeraldpay.dshackle.upstream.ethereum.DirectEthereumApi
|
||||||
import io.infinitape.etherjar.rpc.ReactorBatch
|
import io.infinitape.etherjar.rpc.ReactorBatch
|
||||||
import io.infinitape.etherjar.rpc.ReactorRpcClient
|
import io.infinitape.etherjar.rpc.ReactorRpcClient
|
||||||
@@ -25,8 +25,6 @@ import io.infinitape.etherjar.rpc.RpcCallResponse
|
|||||||
import reactor.core.publisher.Flux
|
import reactor.core.publisher.Flux
|
||||||
import reactor.core.publisher.Mono
|
import reactor.core.publisher.Mono
|
||||||
|
|
||||||
import java.util.concurrent.CompletableFuture
|
|
||||||
|
|
||||||
class EthereumApiStub extends DirectEthereumApi {
|
class EthereumApiStub extends DirectEthereumApi {
|
||||||
|
|
||||||
private String id
|
private String id
|
||||||
|
|||||||
@@ -16,9 +16,9 @@
|
|||||||
package io.emeraldpay.dshackle.test
|
package io.emeraldpay.dshackle.test
|
||||||
|
|
||||||
import io.emeraldpay.dshackle.config.UpstreamsConfig
|
import io.emeraldpay.dshackle.config.UpstreamsConfig
|
||||||
import io.emeraldpay.dshackle.upstream.CallMethods
|
import io.emeraldpay.dshackle.upstream.calls.CallMethods
|
||||||
import io.emeraldpay.dshackle.upstream.NodeDetailsList
|
import io.emeraldpay.dshackle.startup.QuorumForLabels
|
||||||
import io.emeraldpay.dshackle.upstream.QuorumBasedMethods
|
import io.emeraldpay.dshackle.upstream.calls.QuorumBasedMethods
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.DirectEthereumApi
|
import io.emeraldpay.dshackle.upstream.ethereum.DirectEthereumApi
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.EthereumHead
|
import io.emeraldpay.dshackle.upstream.ethereum.EthereumHead
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstream
|
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstream
|
||||||
@@ -46,7 +46,7 @@ class EthereumUpstreamMock extends EthereumUpstream {
|
|||||||
|
|
||||||
EthereumUpstreamMock(@NotNull String id, @NotNull Chain chain, @NotNull DirectEthereumApi api, CallMethods methods) {
|
EthereumUpstreamMock(@NotNull String id, @NotNull Chain chain, @NotNull DirectEthereumApi api, CallMethods methods) {
|
||||||
super(id, chain, api, null,
|
super(id, chain, api, null,
|
||||||
UpstreamsConfig.Options.getDefaults(), new NodeDetailsList.NodeDetails(1, new UpstreamsConfig.Labels()),
|
UpstreamsConfig.Options.getDefaults(), new QuorumForLabels.QuorumItem(1, new UpstreamsConfig.Labels()),
|
||||||
methods)
|
methods)
|
||||||
setLag(0)
|
setLag(0)
|
||||||
setStatus(UpstreamAvailability.OK)
|
setStatus(UpstreamAvailability.OK)
|
||||||
|
|||||||
@@ -21,16 +21,13 @@ import com.fasterxml.jackson.databind.ObjectMapper
|
|||||||
import com.fasterxml.jackson.databind.module.SimpleModule
|
import com.fasterxml.jackson.databind.module.SimpleModule
|
||||||
import io.emeraldpay.dshackle.cache.Caches
|
import io.emeraldpay.dshackle.cache.Caches
|
||||||
import io.emeraldpay.dshackle.upstream.AggregatedUpstream
|
import io.emeraldpay.dshackle.upstream.AggregatedUpstream
|
||||||
import io.emeraldpay.dshackle.upstream.CallMethods
|
|
||||||
import io.emeraldpay.dshackle.upstream.ChainUpstreams
|
import io.emeraldpay.dshackle.upstream.ChainUpstreams
|
||||||
import io.emeraldpay.dshackle.upstream.DirectCallMethods
|
import io.emeraldpay.dshackle.upstream.calls.DirectCallMethods
|
||||||
import io.emeraldpay.dshackle.upstream.QuorumBasedMethods
|
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.DirectEthereumApi
|
import io.emeraldpay.dshackle.upstream.ethereum.DirectEthereumApi
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstream
|
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstream
|
||||||
import io.emeraldpay.grpc.Chain
|
import io.emeraldpay.grpc.Chain
|
||||||
import io.infinitape.etherjar.rpc.JacksonRpcConverter
|
import io.infinitape.etherjar.rpc.JacksonRpcConverter
|
||||||
import io.infinitape.etherjar.rpc.ReactorRpcClient
|
import io.infinitape.etherjar.rpc.ReactorRpcClient
|
||||||
import io.infinitape.etherjar.rpc.RpcClient
|
|
||||||
|
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ package io.emeraldpay.dshackle.test
|
|||||||
import io.emeraldpay.dshackle.cache.Caches
|
import io.emeraldpay.dshackle.cache.Caches
|
||||||
import io.emeraldpay.dshackle.upstream.AggregatedUpstream
|
import io.emeraldpay.dshackle.upstream.AggregatedUpstream
|
||||||
import io.emeraldpay.dshackle.upstream.ChainUpstreams
|
import io.emeraldpay.dshackle.upstream.ChainUpstreams
|
||||||
import io.emeraldpay.dshackle.upstream.QuorumBasedMethods
|
import io.emeraldpay.dshackle.upstream.calls.QuorumBasedMethods
|
||||||
import io.emeraldpay.dshackle.upstream.Upstream
|
import io.emeraldpay.dshackle.upstream.Upstream
|
||||||
import io.emeraldpay.dshackle.upstream.Upstreams
|
import io.emeraldpay.dshackle.upstream.Upstreams
|
||||||
import io.emeraldpay.grpc.Chain
|
import io.emeraldpay.grpc.Chain
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import io.emeraldpay.dshackle.cache.Caches
|
|||||||
import io.emeraldpay.dshackle.quorum.AlwaysQuorum
|
import io.emeraldpay.dshackle.quorum.AlwaysQuorum
|
||||||
import io.emeraldpay.dshackle.test.EthereumUpstreamMock
|
import io.emeraldpay.dshackle.test.EthereumUpstreamMock
|
||||||
import io.emeraldpay.dshackle.test.TestingCommons
|
import io.emeraldpay.dshackle.test.TestingCommons
|
||||||
|
import io.emeraldpay.dshackle.upstream.calls.DirectCallMethods
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.DirectEthereumApi
|
import io.emeraldpay.dshackle.upstream.ethereum.DirectEthereumApi
|
||||||
import io.emeraldpay.grpc.Chain
|
import io.emeraldpay.grpc.Chain
|
||||||
import spock.lang.Specification
|
import spock.lang.Specification
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package io.emeraldpay.dshackle.upstream
|
package io.emeraldpay.dshackle.upstream
|
||||||
|
|
||||||
|
import io.emeraldpay.dshackle.startup.UpstreamChange
|
||||||
import io.emeraldpay.dshackle.test.EthereumUpstreamMock
|
import io.emeraldpay.dshackle.test.EthereumUpstreamMock
|
||||||
import io.emeraldpay.dshackle.test.TestingCommons
|
import io.emeraldpay.dshackle.test.TestingCommons
|
||||||
import io.emeraldpay.grpc.Chain
|
import io.emeraldpay.grpc.Chain
|
||||||
|
|||||||
@@ -16,8 +16,10 @@
|
|||||||
package io.emeraldpay.dshackle.upstream
|
package io.emeraldpay.dshackle.upstream
|
||||||
|
|
||||||
import io.emeraldpay.dshackle.config.UpstreamsConfig
|
import io.emeraldpay.dshackle.config.UpstreamsConfig
|
||||||
|
import io.emeraldpay.dshackle.startup.QuorumForLabels
|
||||||
import io.emeraldpay.dshackle.test.EthereumApiStub
|
import io.emeraldpay.dshackle.test.EthereumApiStub
|
||||||
import io.emeraldpay.dshackle.test.TestingCommons
|
import io.emeraldpay.dshackle.test.TestingCommons
|
||||||
|
import io.emeraldpay.dshackle.upstream.calls.QuorumBasedMethods
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.DirectEthereumApi
|
import io.emeraldpay.dshackle.upstream.ethereum.DirectEthereumApi
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstream
|
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstream
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.EthereumWs
|
import io.emeraldpay.dshackle.upstream.ethereum.EthereumWs
|
||||||
@@ -50,7 +52,7 @@ class FilteredApisSpec extends Specification {
|
|||||||
new DirectEthereumApi(rpcClient, null, objectMapper, ethereumTargets),
|
new DirectEthereumApi(rpcClient, null, objectMapper, ethereumTargets),
|
||||||
(EthereumWs) null,
|
(EthereumWs) null,
|
||||||
new UpstreamsConfig.Options(),
|
new UpstreamsConfig.Options(),
|
||||||
new NodeDetailsList.NodeDetails(1, UpstreamsConfig.Labels.fromMap(it)),
|
new QuorumForLabels.QuorumItem(1, UpstreamsConfig.Labels.fromMap(it)),
|
||||||
ethereumTargets
|
ethereumTargets
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,49 +16,50 @@
|
|||||||
package io.emeraldpay.dshackle.upstream
|
package io.emeraldpay.dshackle.upstream
|
||||||
|
|
||||||
import io.emeraldpay.dshackle.config.UpstreamsConfig
|
import io.emeraldpay.dshackle.config.UpstreamsConfig
|
||||||
|
import io.emeraldpay.dshackle.startup.QuorumForLabels
|
||||||
import org.codehaus.groovy.runtime.DefaultGroovyMethods
|
import org.codehaus.groovy.runtime.DefaultGroovyMethods
|
||||||
import spock.lang.Specification
|
import spock.lang.Specification
|
||||||
|
|
||||||
class NodeDetailsListSpec extends Specification {
|
class QuorumForLabelsSpec extends Specification {
|
||||||
|
|
||||||
def "Adds new node"() {
|
def "Adds new node"() {
|
||||||
setup:
|
setup:
|
||||||
def list = new NodeDetailsList()
|
def list = new QuorumForLabels()
|
||||||
when:
|
when:
|
||||||
list.add(new NodeDetailsList.NodeDetails(1, asLabels([foo: "bar"])))
|
list.add(new QuorumForLabels.QuorumItem(1, asLabels([foo: "bar"])))
|
||||||
then:
|
then:
|
||||||
list.nodes.size() == 1
|
list.all.size() == 1
|
||||||
with(list.nodes.get(0)) {
|
with(list.all.get(0)) {
|
||||||
quorum == 1
|
quorum == 1
|
||||||
DefaultGroovyMethods.equals(labels, [foo: "bar"])
|
DefaultGroovyMethods.equals(labels, [foo: "bar"])
|
||||||
}
|
}
|
||||||
|
|
||||||
when:
|
when:
|
||||||
list.add(new NodeDetailsList.NodeDetails(2, asLabels([foo: "not-bar"])))
|
list.add(new QuorumForLabels.QuorumItem(2, asLabels([foo: "not-bar"])))
|
||||||
then:
|
then:
|
||||||
list.nodes.size() == 2
|
list.all.size() == 2
|
||||||
with(list.nodes.get(0)) {
|
with(list.all.get(0)) {
|
||||||
quorum == 1
|
quorum == 1
|
||||||
DefaultGroovyMethods.equals(labels, [foo: "bar"])
|
DefaultGroovyMethods.equals(labels, [foo: "bar"])
|
||||||
}
|
}
|
||||||
with(list.nodes.get(1)) {
|
with(list.all.get(1)) {
|
||||||
quorum == 2
|
quorum == 2
|
||||||
DefaultGroovyMethods.equals(labels, [foo: "not-bar"])
|
DefaultGroovyMethods.equals(labels, [foo: "not-bar"])
|
||||||
}
|
}
|
||||||
|
|
||||||
when:
|
when:
|
||||||
list.add(new NodeDetailsList.NodeDetails(1, asLabels([foo: "bar", baz: "baz"])))
|
list.add(new QuorumForLabels.QuorumItem(1, asLabels([foo: "bar", baz: "baz"])))
|
||||||
then:
|
then:
|
||||||
list.nodes.size() == 3
|
list.all.size() == 3
|
||||||
with(list.nodes.get(0)) {
|
with(list.all.get(0)) {
|
||||||
quorum == 1
|
quorum == 1
|
||||||
DefaultGroovyMethods.equals(labels, [foo: "bar"])
|
DefaultGroovyMethods.equals(labels, [foo: "bar"])
|
||||||
}
|
}
|
||||||
with(list.nodes.get(1)) {
|
with(list.all.get(1)) {
|
||||||
quorum == 2
|
quorum == 2
|
||||||
DefaultGroovyMethods.equals(labels, [foo: "not-bar"])
|
DefaultGroovyMethods.equals(labels, [foo: "not-bar"])
|
||||||
}
|
}
|
||||||
with(list.nodes.get(2)) {
|
with(list.all.get(2)) {
|
||||||
quorum == 1
|
quorum == 1
|
||||||
DefaultGroovyMethods.equals(labels, [foo: "bar", baz: "baz"])
|
DefaultGroovyMethods.equals(labels, [foo: "bar", baz: "baz"])
|
||||||
}
|
}
|
||||||
@@ -66,19 +67,19 @@ class NodeDetailsListSpec extends Specification {
|
|||||||
|
|
||||||
def "Updates existing node"() {
|
def "Updates existing node"() {
|
||||||
setup:
|
setup:
|
||||||
def list = new NodeDetailsList()
|
def list = new QuorumForLabels()
|
||||||
list.add(new NodeDetailsList.NodeDetails(1, asLabels([foo: "bar"])))
|
list.add(new QuorumForLabels.QuorumItem(1, asLabels([foo: "bar"])))
|
||||||
list.add(new NodeDetailsList.NodeDetails(1, asLabels([baz: "true"])))
|
list.add(new QuorumForLabels.QuorumItem(1, asLabels([baz: "true"])))
|
||||||
|
|
||||||
when:
|
when:
|
||||||
list.add(new NodeDetailsList.NodeDetails(2, asLabels([baz: "true"])))
|
list.add(new QuorumForLabels.QuorumItem(2, asLabels([baz: "true"])))
|
||||||
then:
|
then:
|
||||||
list.nodes.size() == 2
|
list.all.size() == 2
|
||||||
with(list.nodes.get(0)) {
|
with(list.all.get(0)) {
|
||||||
quorum == 1
|
quorum == 1
|
||||||
DefaultGroovyMethods.equals(labels, [foo: "bar"])
|
DefaultGroovyMethods.equals(labels, [foo: "bar"])
|
||||||
}
|
}
|
||||||
with(list.nodes.get(1)) {
|
with(list.all.get(1)) {
|
||||||
quorum == 3
|
quorum == 3
|
||||||
DefaultGroovyMethods.equals(labels, [baz: "true"])
|
DefaultGroovyMethods.equals(labels, [baz: "true"])
|
||||||
}
|
}
|
||||||
@@ -86,23 +87,23 @@ class NodeDetailsListSpec extends Specification {
|
|||||||
|
|
||||||
def "Applies all from another list"() {
|
def "Applies all from another list"() {
|
||||||
setup:
|
setup:
|
||||||
def list1 = new NodeDetailsList()
|
def list1 = new QuorumForLabels()
|
||||||
list1.add(new NodeDetailsList.NodeDetails(1, asLabels([foo: "bar"])))
|
list1.add(new QuorumForLabels.QuorumItem(1, asLabels([foo: "bar"])))
|
||||||
list1.add(new NodeDetailsList.NodeDetails(2, asLabels([baz: "true"])))
|
list1.add(new QuorumForLabels.QuorumItem(2, asLabels([baz: "true"])))
|
||||||
list1.add(new NodeDetailsList.NodeDetails(3, asLabels([baz: "true", bar: "bar"])))
|
list1.add(new QuorumForLabels.QuorumItem(3, asLabels([baz: "true", bar: "bar"])))
|
||||||
|
|
||||||
def list2 = new NodeDetailsList()
|
def list2 = new QuorumForLabels()
|
||||||
list1.add(new NodeDetailsList.NodeDetails(4, asLabels([foo: "bar"])))
|
list1.add(new QuorumForLabels.QuorumItem(4, asLabels([foo: "bar"])))
|
||||||
list1.add(new NodeDetailsList.NodeDetails(5, asLabels([baz: "true", bar: "bar"])))
|
list1.add(new QuorumForLabels.QuorumItem(5, asLabels([baz: "true", bar: "bar"])))
|
||||||
list1.add(new NodeDetailsList.NodeDetails(6, asLabels([bar: "bar"])))
|
list1.add(new QuorumForLabels.QuorumItem(6, asLabels([bar: "bar"])))
|
||||||
|
|
||||||
def list = new NodeDetailsList()
|
def list = new QuorumForLabels()
|
||||||
when:
|
when:
|
||||||
list.add(list1)
|
list.add(list1)
|
||||||
list.add(list2)
|
list.add(list2)
|
||||||
def nodes = list.nodes.toSorted { it.quorum }
|
def nodes = list.all.toSorted { it.quorum }
|
||||||
then:
|
then:
|
||||||
list.nodes.size() == 4
|
list.all.size() == 4
|
||||||
with(nodes.get(0)) {
|
with(nodes.get(0)) {
|
||||||
quorum == 2
|
quorum == 2
|
||||||
DefaultGroovyMethods.equals(labels, [baz: "true"])
|
DefaultGroovyMethods.equals(labels, [baz: "true"])
|
||||||
@@ -13,9 +13,12 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package io.emeraldpay.dshackle.upstream
|
package io.emeraldpay.dshackle.upstream.calls
|
||||||
|
|
||||||
import io.emeraldpay.dshackle.quorum.AlwaysQuorum
|
import io.emeraldpay.dshackle.quorum.AlwaysQuorum
|
||||||
|
import io.emeraldpay.dshackle.upstream.calls.AggregatedCallMethods
|
||||||
|
import io.emeraldpay.dshackle.upstream.calls.CallMethods
|
||||||
|
import io.emeraldpay.dshackle.upstream.calls.DirectCallMethods
|
||||||
import spock.lang.Specification
|
import spock.lang.Specification
|
||||||
|
|
||||||
class AggregatedCallMethodsSpec extends Specification {
|
class AggregatedCallMethodsSpec extends Specification {
|
||||||
@@ -13,9 +13,11 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package io.emeraldpay.dshackle.upstream
|
package io.emeraldpay.dshackle.upstream.calls
|
||||||
|
|
||||||
import io.emeraldpay.dshackle.quorum.AlwaysQuorum
|
import io.emeraldpay.dshackle.quorum.AlwaysQuorum
|
||||||
|
import io.emeraldpay.dshackle.upstream.calls.DirectCallMethods
|
||||||
|
import io.emeraldpay.dshackle.upstream.calls.ManagedCallMethods
|
||||||
import spock.lang.Specification
|
import spock.lang.Specification
|
||||||
|
|
||||||
class ManagedCallMethodsSpec extends Specification {
|
class ManagedCallMethodsSpec extends Specification {
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
package io.emeraldpay.dshackle.upstream.ethereum
|
package io.emeraldpay.dshackle.upstream.ethereum
|
||||||
|
|
||||||
import io.emeraldpay.dshackle.test.TestingCommons
|
import io.emeraldpay.dshackle.test.TestingCommons
|
||||||
import io.emeraldpay.dshackle.upstream.DirectCallMethods
|
import io.emeraldpay.dshackle.upstream.calls.DirectCallMethods
|
||||||
import io.infinitape.etherjar.rpc.ReactorRpcClient
|
import io.infinitape.etherjar.rpc.ReactorRpcClient
|
||||||
import io.infinitape.etherjar.rpc.RpcException
|
import io.infinitape.etherjar.rpc.RpcException
|
||||||
import io.infinitape.etherjar.rpc.RpcResponseError
|
import io.infinitape.etherjar.rpc.RpcResponseError
|
||||||
|
|||||||
@@ -22,22 +22,17 @@ import io.emeraldpay.api.proto.BlockchainOuterClass
|
|||||||
import io.emeraldpay.api.proto.Common
|
import io.emeraldpay.api.proto.Common
|
||||||
import io.emeraldpay.dshackle.test.MockServer
|
import io.emeraldpay.dshackle.test.MockServer
|
||||||
import io.emeraldpay.dshackle.test.TestingCommons
|
import io.emeraldpay.dshackle.test.TestingCommons
|
||||||
import io.emeraldpay.dshackle.upstream.QuorumBasedMethods
|
|
||||||
import io.emeraldpay.dshackle.upstream.UpstreamAvailability
|
import io.emeraldpay.dshackle.upstream.UpstreamAvailability
|
||||||
import io.emeraldpay.dshackle.upstream.grpc.GrpcUpstream
|
|
||||||
import io.emeraldpay.grpc.Chain
|
import io.emeraldpay.grpc.Chain
|
||||||
import io.grpc.stub.StreamObserver
|
import io.grpc.stub.StreamObserver
|
||||||
import io.infinitape.etherjar.domain.BlockHash
|
import io.infinitape.etherjar.domain.BlockHash
|
||||||
import io.infinitape.etherjar.rpc.JacksonRpcConverter
|
|
||||||
import io.infinitape.etherjar.rpc.ReactorRpcClient
|
import io.infinitape.etherjar.rpc.ReactorRpcClient
|
||||||
import io.infinitape.etherjar.rpc.emerald.ReactorEmeraldClient
|
import io.infinitape.etherjar.rpc.emerald.ReactorEmeraldClient
|
||||||
import io.infinitape.etherjar.rpc.json.BlockJson
|
import io.infinitape.etherjar.rpc.json.BlockJson
|
||||||
import reactor.test.StepVerifier
|
|
||||||
import spock.lang.Specification
|
import spock.lang.Specification
|
||||||
|
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
import java.util.concurrent.CompletableFuture
|
import java.util.concurrent.CompletableFuture
|
||||||
import java.util.concurrent.Executors
|
|
||||||
|
|
||||||
class GrpcUpstreamSpec extends Specification {
|
class GrpcUpstreamSpec extends Specification {
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user