problem: uses only one Head Subscription for Dshackle Upstream even if multiple are provided
This commit is contained in:
@@ -93,7 +93,7 @@ class BitcoinGrpcUpstream(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
private val upstreamStatus = GrpcUpstreamStatus()
|
private val upstreamStatus = GrpcUpstreamStatus()
|
||||||
private val grpcHead = GrpcHead(chain, this, blockConverter, reloadBlock)
|
private val grpcHead = GrpcHead(chain, this, remote, blockConverter, reloadBlock)
|
||||||
var timeout = Defaults.timeout
|
var timeout = Defaults.timeout
|
||||||
private var capabilities: Set<Capability> = emptySet()
|
private var capabilities: Set<Capability> = emptySet()
|
||||||
|
|
||||||
@@ -126,15 +126,13 @@ class BitcoinGrpcUpstream(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun isRunning(): Boolean {
|
override fun isRunning(): Boolean {
|
||||||
return grpcHead.isRunning
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun start() {
|
override fun start() {
|
||||||
grpcHead.start(remote)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun stop() {
|
override fun stop() {
|
||||||
grpcHead.stop()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun update(conf: BlockchainOuterClass.DescribeChain) {
|
override fun update(conf: BlockchainOuterClass.DescribeChain) {
|
||||||
|
|||||||
@@ -95,22 +95,20 @@ open class EthereumGrpcUpstream(
|
|||||||
|
|
||||||
private val log = LoggerFactory.getLogger(EthereumGrpcUpstream::class.java)
|
private val log = LoggerFactory.getLogger(EthereumGrpcUpstream::class.java)
|
||||||
private val upstreamStatus = GrpcUpstreamStatus()
|
private val upstreamStatus = GrpcUpstreamStatus()
|
||||||
private val grpcHead = GrpcHead(chain, this, blockConverter, reloadBlock)
|
private val grpcHead = GrpcHead(chain, this, remote, blockConverter, reloadBlock)
|
||||||
private var capabilities: Set<Capability> = emptySet()
|
private var capabilities: Set<Capability> = emptySet()
|
||||||
|
|
||||||
private val defaultReader: Reader<JsonRpcRequest, JsonRpcResponse> = client.forSelector(Selector.empty)
|
private val defaultReader: Reader<JsonRpcRequest, JsonRpcResponse> = client.forSelector(Selector.empty)
|
||||||
var timeout = Defaults.timeout
|
var timeout = Defaults.timeout
|
||||||
|
|
||||||
override fun start() {
|
override fun start() {
|
||||||
grpcHead.start(remote)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isRunning(): Boolean {
|
override fun isRunning(): Boolean {
|
||||||
return grpcHead.isRunning
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun stop() {
|
override fun stop() {
|
||||||
grpcHead.stop()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun update(conf: BlockchainOuterClass.DescribeChain) {
|
override fun update(conf: BlockchainOuterClass.DescribeChain) {
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import java.util.function.Function
|
|||||||
class GrpcHead(
|
class GrpcHead(
|
||||||
private val chain: Chain,
|
private val chain: Chain,
|
||||||
private val parent: DefaultUpstream,
|
private val parent: DefaultUpstream,
|
||||||
|
private val remote: ReactorBlockchainGrpc.ReactorBlockchainStub,
|
||||||
/**
|
/**
|
||||||
* Converted from remote head details to the block container, which could be partial at this point
|
* Converted from remote head details to the block container, which could be partial at this point
|
||||||
*/
|
*/
|
||||||
@@ -56,10 +57,11 @@ class GrpcHead(
|
|||||||
/**
|
/**
|
||||||
* Initiate a new head subscription with connection to the remote
|
* Initiate a new head subscription with connection to the remote
|
||||||
*/
|
*/
|
||||||
fun start(remote: ReactorBlockchainGrpc.ReactorBlockchainStub) {
|
private fun internalStart(remote: ReactorBlockchainGrpc.ReactorBlockchainStub) {
|
||||||
if (this.isRunning) {
|
if (this.isRunning) {
|
||||||
stop()
|
stop()
|
||||||
}
|
}
|
||||||
|
log.debug("Start Head subscription to ${parent.getId()}")
|
||||||
|
|
||||||
val source = Flux.concat(
|
val source = Flux.concat(
|
||||||
// first connect immediately
|
// first connect immediately
|
||||||
@@ -68,7 +70,7 @@ class GrpcHead(
|
|||||||
Flux.just(remote).repeat().delayElements(Defaults.retryConnection)
|
Flux.just(remote).repeat().delayElements(Defaults.retryConnection)
|
||||||
).flatMap(this::subscribeHead)
|
).flatMap(this::subscribeHead)
|
||||||
|
|
||||||
start(source)
|
internalStart(source)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun subscribeHead(client: ReactorBlockchainGrpc.ReactorBlockchainStub): Publisher<BlockchainOuterClass.ChainHead> {
|
fun subscribeHead(client: ReactorBlockchainGrpc.ReactorBlockchainStub): Publisher<BlockchainOuterClass.ChainHead> {
|
||||||
@@ -88,7 +90,7 @@ class GrpcHead(
|
|||||||
/**
|
/**
|
||||||
* Initiate a new head from provided source of head details
|
* Initiate a new head from provided source of head details
|
||||||
*/
|
*/
|
||||||
fun start(source: Flux<BlockchainOuterClass.ChainHead>) {
|
private fun internalStart(source: Flux<BlockchainOuterClass.ChainHead>) {
|
||||||
var blocks = source.map(converter)
|
var blocks = source.map(converter)
|
||||||
.distinctUntilChanged {
|
.distinctUntilChanged {
|
||||||
it.hash
|
it.hash
|
||||||
@@ -112,7 +114,7 @@ class GrpcHead(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun start() {
|
override fun start() {
|
||||||
log.error("Use start with provides source")
|
this.internalStart(remote)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun stop() {
|
override fun stop() {
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ class EthereumGrpcUpstreamSpec extends Specification {
|
|||||||
.addAllSupportedMethods(["eth_getBlockByHash"])
|
.addAllSupportedMethods(["eth_getBlockByHash"])
|
||||||
.build())
|
.build())
|
||||||
when:
|
when:
|
||||||
new Thread({ Thread.sleep(50); upstream.start() }).start()
|
new Thread({ Thread.sleep(50); upstream.head.start() }).start()
|
||||||
def h = upstream.head.getFlux().next().block(Duration.ofSeconds(1))
|
def h = upstream.head.getFlux().next().block(Duration.ofSeconds(1))
|
||||||
then:
|
then:
|
||||||
callData.chain == Chain.ETHEREUM.id
|
callData.chain == Chain.ETHEREUM.id
|
||||||
@@ -145,8 +145,8 @@ class EthereumGrpcUpstreamSpec extends Specification {
|
|||||||
.addAllSupportedMethods(["eth_getBlockByHash"])
|
.addAllSupportedMethods(["eth_getBlockByHash"])
|
||||||
.build())
|
.build())
|
||||||
when:
|
when:
|
||||||
new Thread({ Thread.sleep(50); upstream.start() }).start()
|
new Thread({ Thread.sleep(50); upstream.head.start() }).start()
|
||||||
def h = upstream.head.getFlux().take(Duration.ofSeconds(1)).last().block()
|
def h = upstream.head.getFlux().take(Duration.ofSeconds(1)).last().block(Duration.ofSeconds(2))
|
||||||
then:
|
then:
|
||||||
upstream.status == UpstreamAvailability.OK
|
upstream.status == UpstreamAvailability.OK
|
||||||
h.hash == BlockId.from("0x50d26e119968e791970d84a7bf5d0ec474d3ec2ef85d5ec8915210ac6bc09ad7")
|
h.hash == BlockId.from("0x50d26e119968e791970d84a7bf5d0ec474d3ec2ef85d5ec8915210ac6bc09ad7")
|
||||||
@@ -207,9 +207,9 @@ class EthereumGrpcUpstreamSpec extends Specification {
|
|||||||
.addAllSupportedMethods(["eth_getBlockByHash"])
|
.addAllSupportedMethods(["eth_getBlockByHash"])
|
||||||
.build())
|
.build())
|
||||||
when:
|
when:
|
||||||
new Thread({ Thread.sleep(50); upstream.start() }).start()
|
new Thread({ Thread.sleep(50); upstream.head.start() }).start()
|
||||||
finished.get()
|
finished.get()
|
||||||
def h = upstream.head.getFlux().take(Duration.ofSeconds(1)).last().block()
|
def h = upstream.head.getFlux().take(Duration.ofSeconds(1)).last().block(Duration.ofSeconds(2))
|
||||||
then:
|
then:
|
||||||
upstream.status == UpstreamAvailability.OK
|
upstream.status == UpstreamAvailability.OK
|
||||||
h.hash == BlockId.from("0x3ec2ebf5d0ec474d0ac6bc50d2770d8409ad76e119968e7919f85d5ec891521a")
|
h.hash == BlockId.from("0x3ec2ebf5d0ec474d0ac6bc50d2770d8409ad76e119968e7919f85d5ec891521a")
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ package io.emeraldpay.dshackle.upstream.grpc
|
|||||||
import io.emeraldpay.api.proto.BlockchainGrpc
|
import io.emeraldpay.api.proto.BlockchainGrpc
|
||||||
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.data.BlockContainer
|
|
||||||
import io.emeraldpay.dshackle.test.MockGrpcServer
|
import io.emeraldpay.dshackle.test.MockGrpcServer
|
||||||
import io.emeraldpay.dshackle.test.TestingCommons
|
import io.emeraldpay.dshackle.test.TestingCommons
|
||||||
import io.emeraldpay.dshackle.upstream.DefaultUpstream
|
import io.emeraldpay.dshackle.upstream.DefaultUpstream
|
||||||
@@ -28,7 +27,6 @@ import reactor.test.StepVerifier
|
|||||||
import spock.lang.Specification
|
import spock.lang.Specification
|
||||||
|
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
import java.util.function.Function
|
|
||||||
|
|
||||||
class GrpcHeadSpec extends Specification {
|
class GrpcHeadSpec extends Specification {
|
||||||
|
|
||||||
@@ -61,6 +59,7 @@ class GrpcHeadSpec extends Specification {
|
|||||||
def head = new GrpcHead(
|
def head = new GrpcHead(
|
||||||
Chain.BITCOIN,
|
Chain.BITCOIN,
|
||||||
Stub(DefaultUpstream),
|
Stub(DefaultUpstream),
|
||||||
|
client,
|
||||||
convert, null
|
convert, null
|
||||||
)
|
)
|
||||||
when:
|
when:
|
||||||
@@ -69,7 +68,7 @@ class GrpcHeadSpec extends Specification {
|
|||||||
|
|
||||||
then:
|
then:
|
||||||
StepVerifier.create(act)
|
StepVerifier.create(act)
|
||||||
.then { head.start(client) }
|
.then { head.start() }
|
||||||
.expectNext(TestingCommons.blockForBitcoin(10)).as("block 10")
|
.expectNext(TestingCommons.blockForBitcoin(10)).as("block 10")
|
||||||
.expectNext(TestingCommons.blockForBitcoin(11)).as("block 11")
|
.expectNext(TestingCommons.blockForBitcoin(11)).as("block 11")
|
||||||
.expectNext(TestingCommons.blockForBitcoin(12)).as("block 12")
|
.expectNext(TestingCommons.blockForBitcoin(12)).as("block 12")
|
||||||
@@ -121,12 +120,13 @@ class GrpcHeadSpec extends Specification {
|
|||||||
def head = new GrpcHead(
|
def head = new GrpcHead(
|
||||||
Chain.BITCOIN,
|
Chain.BITCOIN,
|
||||||
Stub(DefaultUpstream),
|
Stub(DefaultUpstream),
|
||||||
|
client,
|
||||||
convert, null
|
convert, null
|
||||||
)
|
)
|
||||||
when:
|
when:
|
||||||
def act = head.getFlux()
|
def act = head.getFlux()
|
||||||
.take(3)
|
.take(3)
|
||||||
head.start(client)
|
head.start()
|
||||||
|
|
||||||
then:
|
then:
|
||||||
StepVerifier.create(act)
|
StepVerifier.create(act)
|
||||||
|
|||||||
Reference in New Issue
Block a user