use head scheduler instead of stock schedulers in other parts of system

This commit is contained in:
a10zn8
2023-04-21 18:02:25 +08:00
parent f218e6e73b
commit b97108fd35
17 changed files with 63 additions and 60 deletions

View File

@@ -388,6 +388,7 @@ open class ConfiguredUpstreams(
id, chain,
endpoint.url,
endpoint.origin ?: URI("http://localhost"),
headScheduler
).apply {
config = endpoint
basicAuth = endpoint.basicAuth

View File

@@ -10,9 +10,11 @@ import io.emeraldpay.etherjar.domain.Address
import io.emeraldpay.etherjar.hex.Hex32
import org.slf4j.LoggerFactory
import reactor.core.publisher.Flux
import reactor.core.scheduler.Scheduler
open class EthereumEgressSubscription(
val upstream: EthereumLikeMultistream,
val scheduler: Scheduler,
val pendingTxesSource: PendingTxesSource?
) : EgressSubscription {
@@ -37,8 +39,8 @@ open class EthereumEgressSubscription(
}
}
private val newHeads = ConnectNewHeads(upstream)
open val logs = ConnectLogs(upstream)
private val newHeads = ConnectNewHeads(upstream, scheduler)
open val logs = ConnectLogs(upstream, scheduler)
private val syncing = ConnectSyncing(upstream)
override fun getAvailableTopics() = availableTopics

View File

@@ -63,7 +63,7 @@ open class EthereumMultistream(
ConcurrentReferenceHashMap(16, ConcurrentReferenceHashMap.ReferenceType.WEAK)
private val reader: EthereumCachingReader = EthereumCachingReader(this, this.caches, getMethodsFactory(), tracer)
private var subscribe = EthereumEgressSubscription(this, NoPendingTxes())
private var subscribe = EthereumEgressSubscription(this, headScheduler, NoPendingTxes())
private val supportsEIP1559 = when (chain) {
Chain.ETHEREUM, Chain.TESTNET_ROPSTEN,
@@ -102,7 +102,7 @@ open class EthereumMultistream(
AggregatedPendingTxes(it)
}
}
subscribe = EthereumEgressSubscription(this, pendingTxes)
subscribe = EthereumEgressSubscription(this, headScheduler, pendingTxes)
}
override fun start() {

View File

@@ -8,6 +8,7 @@ import io.micrometer.core.instrument.Counter
import io.micrometer.core.instrument.Metrics
import io.micrometer.core.instrument.Tag
import io.micrometer.core.instrument.Timer
import reactor.core.scheduler.Scheduler
import java.net.URI
open class EthereumWsConnectionFactory(
@@ -15,6 +16,7 @@ open class EthereumWsConnectionFactory(
private val chain: Chain,
private val uri: URI,
private val origin: URI,
private val scheduler: Scheduler
) {
var basicAuth: AuthConfig.ClientBasicAuth? = null
@@ -42,7 +44,7 @@ open class EthereumWsConnectionFactory(
}
open fun createWsConnection(connIndex: Int = 0, onDisconnect: () -> Unit): WsConnection =
WsConnectionImpl(uri, origin, basicAuth, metrics(connIndex), onDisconnect).also { ws ->
WsConnectionImpl(uri, origin, basicAuth, metrics(connIndex), onDisconnect, scheduler).also { ws ->
config?.frameSize?.let {
ws.frameSize = it
}

View File

@@ -33,7 +33,6 @@ import reactor.core.publisher.Flux
import reactor.core.publisher.Mono
import reactor.core.publisher.Sinks
import reactor.core.scheduler.Scheduler
import reactor.core.scheduler.Schedulers
import reactor.retry.Repeat
import java.time.Duration
@@ -45,7 +44,7 @@ class EthereumWsHead(
private val wsSubscriptions: WsSubscriptions,
private val skipEnhance: Boolean,
private val wsConnectionResubscribeScheduler: Scheduler,
headScheduler: Scheduler,
private val headScheduler: Scheduler,
) : DefaultEthereumHead(upstreamId, forkChoice, blockValidator, headScheduler), Lifecycle {
private var connectionId: String? = null
@@ -119,7 +118,7 @@ class EthereumWsHead(
}
.flatMap(JsonRpcResponse::requireResult)
.map { BlockContainer.fromEthereumJson(it, upstreamId) }
.subscribeOn(Schedulers.boundedElastic())
.subscribeOn(headScheduler)
.timeout(Defaults.timeoutInternal, Mono.empty())
}.repeatWhenEmpty { n ->
Repeat.times<Any>(5)

View File

@@ -44,7 +44,7 @@ import reactor.core.Disposable
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono
import reactor.core.publisher.Sinks
import reactor.core.scheduler.Schedulers
import reactor.core.scheduler.Scheduler
import reactor.netty.http.client.HttpClient
import reactor.netty.http.client.WebsocketClientSpec
import reactor.netty.http.websocket.WebsocketInbound
@@ -67,7 +67,8 @@ open class WsConnectionImpl(
private val origin: URI,
private val basicAuth: AuthConfig.ClientBasicAuth?,
private val rpcMetrics: RpcMetrics?,
private val onDisconnect: () -> Unit
private val onDisconnect: () -> Unit,
private val scheduler: Scheduler
) : AutoCloseable, WsConnection, Cloneable {
companion object {
@@ -292,8 +293,8 @@ open class WsConnectionImpl(
return outbound.send(
Flux.merge(
calls.subscribeOn(Schedulers.boundedElastic()),
consumer.then(Mono.empty<ByteBuf>()).subscribeOn(Schedulers.boundedElastic())
calls.subscribeOn(scheduler),
consumer.then(Mono.empty<ByteBuf>()).subscribeOn(scheduler)
)
)
}

View File

@@ -22,9 +22,8 @@ import io.emeraldpay.dshackle.upstream.Head
import io.emeraldpay.dshackle.upstream.Selector
import io.emeraldpay.dshackle.upstream.SubscriptionConnect
import io.emeraldpay.dshackle.upstream.ethereum.EthereumLikeMultistream
import org.slf4j.LoggerFactory
import reactor.core.publisher.Flux
import reactor.core.scheduler.Schedulers
import reactor.core.scheduler.Scheduler
import java.time.Duration
import java.util.LinkedList
import java.util.concurrent.ConcurrentHashMap
@@ -33,11 +32,11 @@ import kotlin.concurrent.read
import kotlin.concurrent.write
class ConnectBlockUpdates(
private val upstream: EthereumLikeMultistream
private val upstream: EthereumLikeMultistream,
private val scheduler: Scheduler
) : SubscriptionConnect<ConnectBlockUpdates.Update> {
companion object {
private val log = LoggerFactory.getLogger(ConnectBlockUpdates::class.java)
private const val HISTORY_LIMIT = 6 * 3
}
@@ -53,7 +52,7 @@ class ConnectBlockUpdates(
override fun connect(matcher: Selector.Matcher): Flux<Update> {
return connected.computeIfAbsent(matcher.describeInternal()) { key ->
extract(upstream.getHead(matcher))
.publishOn(Schedulers.boundedElastic())
.publishOn(scheduler)
.publish()
.refCount(1, Duration.ofSeconds(60))
.doFinally {

View File

@@ -22,8 +22,8 @@ import io.emeraldpay.dshackle.upstream.ethereum.subscribe.json.LogMessage
import io.emeraldpay.etherjar.domain.Address
import io.emeraldpay.etherjar.hex.Hex32
import io.emeraldpay.etherjar.hex.HexDataComparator
import org.slf4j.LoggerFactory
import reactor.core.publisher.Flux
import reactor.core.scheduler.Scheduler
import java.util.function.Function
open class ConnectLogs(
@@ -32,14 +32,11 @@ open class ConnectLogs(
) {
companion object {
private val log = LoggerFactory.getLogger(ConnectLogs::class.java)
private val ADDR_COMPARATOR = HexDataComparator()
private val TOPIC_COMPARATOR = HexDataComparator()
}
constructor(upstream: EthereumLikeMultistream) : this(upstream, ConnectBlockUpdates(upstream))
constructor(upstream: EthereumLikeMultistream, scheduler: Scheduler) : this(upstream, ConnectBlockUpdates(upstream, scheduler))
private val produceLogs = ProduceLogs(upstream)
fun start(matcher: Selector.Matcher): Flux<LogMessage> {

View File

@@ -19,9 +19,8 @@ import io.emeraldpay.dshackle.upstream.Selector
import io.emeraldpay.dshackle.upstream.SubscriptionConnect
import io.emeraldpay.dshackle.upstream.ethereum.EthereumLikeMultistream
import io.emeraldpay.dshackle.upstream.ethereum.subscribe.json.NewHeadMessage
import org.slf4j.LoggerFactory
import reactor.core.publisher.Flux
import reactor.core.scheduler.Schedulers
import reactor.core.scheduler.Scheduler
import java.time.Duration
import java.util.concurrent.ConcurrentHashMap
@@ -29,20 +28,17 @@ import java.util.concurrent.ConcurrentHashMap
* Connects/reconnects to the upstream to produce NewHeads messages
*/
class ConnectNewHeads(
private val upstream: EthereumLikeMultistream
private val upstream: EthereumLikeMultistream,
private val scheduler: Scheduler
) : SubscriptionConnect<NewHeadMessage> {
companion object {
private val log = LoggerFactory.getLogger(ConnectNewHeads::class.java)
}
private val connected: MutableMap<String, Flux<NewHeadMessage>> = ConcurrentHashMap()
override fun connect(matcher: Selector.Matcher): Flux<NewHeadMessage> =
connected.computeIfAbsent(matcher.describeInternal()) { key ->
ProduceNewHeads(upstream.getHead(matcher))
.start()
.publishOn(Schedulers.boundedElastic())
.publishOn(scheduler)
.publish()
.refCount(1, Duration.ofSeconds(60))
.doFinally {

View File

@@ -19,7 +19,6 @@ import io.emeraldpay.dshackle.upstream.Selector
import io.emeraldpay.dshackle.upstream.SubscriptionConnect
import io.emeraldpay.dshackle.upstream.UpstreamAvailability
import io.emeraldpay.dshackle.upstream.ethereum.EthereumLikeMultistream
import org.slf4j.LoggerFactory
import reactor.core.publisher.Flux
import java.time.Duration
import java.util.concurrent.locks.ReentrantLock
@@ -29,10 +28,6 @@ class ConnectSyncing(
private val upstream: EthereumLikeMultistream
) : SubscriptionConnect<Boolean> {
companion object {
private val log = LoggerFactory.getLogger(ConnectSyncing::class.java)
}
private var connected: Flux<Boolean>? = null
private val connectLock = ReentrantLock()

View File

@@ -58,7 +58,7 @@ open class EthereumPosMultiStream(
)
private val reader: EthereumCachingReader = EthereumCachingReader(this, this.caches, getMethodsFactory(), tracer)
private var subscribe = EthereumEgressSubscription(this, NoPendingTxes())
private var subscribe = EthereumEgressSubscription(this, headScheduler, NoPendingTxes())
private val feeEstimation = EthereumPriorityFees(this, reader, 256)
private val filteredHeads: MutableMap<String, Head> =
ConcurrentReferenceHashMap(16, ConcurrentReferenceHashMap.ReferenceType.WEAK)
@@ -198,6 +198,6 @@ open class EthereumPosMultiStream(
AggregatedPendingTxes(it)
}
}
subscribe = EthereumEgressSubscription(this, pendingTxes)
subscribe = EthereumEgressSubscription(this, headScheduler, pendingTxes)
}
}