solution: describe available methods per chain

This commit is contained in:
Igor Artamonov
2019-07-29 23:07:18 -04:00
parent 36e089f65f
commit dd0c29c40c
8 changed files with 35 additions and 6 deletions

View File

@@ -26,12 +26,13 @@ class Describe(
chainUpstreams.getAll().let { ups ->
if (ups.isNotEmpty()) {
val status = subscribeStatus.chainStatus(chain, ups)
resp.addChains(
BlockchainOuterClass.DescribeChain.newBuilder()
.setChain(Common.ChainRef.forNumber(chain.id))
.setStatus(status)
.build()
)
val targets = chainUpstreams.getSupportedTargets()
val chainDescription = BlockchainOuterClass.DescribeChain.newBuilder()
.setChain(Common.ChainRef.forNumber(chain.id))
.addAllSupportedTargets(targets)
.setStatus(status)
.build()
resp.addChains(chainDescription)
}
}
}

View File

@@ -32,6 +32,7 @@ class NativeCall(
if (chain == Chain.UNSPECIFIED) {
throw Exception("Invalid chain id: ${request.chain.number}")
}
// TODO send error to all requests?
val upstream = upstreams.getUpstream(chain)?.getApi() ?: throw Exception("Chain ${chain.id} is unavailable")
request.itemsList.toFlux().map {
val method = it.target

View File

@@ -20,6 +20,14 @@ abstract class AggregatedUpstreams: Upstream {
.map { it.status }
}
override fun getSupportedTargets(): Set<String> {
val list = HashSet<String>()
getAll().forEach {
list.addAll(it.getSupportedTargets())
}
return list
}
override fun isAvailable(): Boolean {
return getAll().any { it.isAvailable() }
}

View File

@@ -167,4 +167,8 @@ open class EthereumApi(
}
throw RpcException(-32601, "Method not found")
}
fun getSupportedMethods(): Set<String> {
return allowedMethods.plus(hardcodedMethods).toSortedSet()
}
}

View File

@@ -16,6 +16,10 @@ class EthereumUpstream(
private val options: UpstreamsConfig.Options
): Upstream {
override fun getSupportedTargets(): Set<String> {
return api.getSupportedMethods()
}
private val log = LoggerFactory.getLogger(EthereumUpstream::class.java)
private val head: EthereumHead = if (ethereumWs != null) {

View File

@@ -20,8 +20,10 @@ import reactor.core.publisher.toMono
import java.lang.Exception
import java.math.BigInteger
import java.time.Duration
import java.util.*
import java.util.concurrent.atomic.AtomicReference
import java.util.function.Function
import kotlin.collections.ArrayList
open class GrpcUpstream(
private val chain: Chain,
@@ -41,6 +43,7 @@ open class GrpcUpstream(
private val head = Head(this)
private val api: EthereumApi
private val statusStream: TopicProcessor<UpstreamAvailability> = TopicProcessor.create()
private val supportedMethods = HashSet<String>()
init {
val grpcTransport = EthereumGrpcTransport(chain, client, objectMapper)
@@ -93,6 +96,7 @@ open class GrpcUpstream(
}
fun init(conf: BlockchainOuterClass.DescribeChain) {
supportedMethods.addAll(conf.supportedTargetsList)
conf.status?.let { status -> onStatus(status) }
}
@@ -110,6 +114,9 @@ open class GrpcUpstream(
}
// ------------------------------------------------------------------------------------------
override fun getSupportedTargets(): Set<String> {
return supportedMethods
}
override fun isAvailable(): Boolean {
return headBlock.get() != null

View File

@@ -56,6 +56,9 @@ class GrpcUpstreams(
}
chains as List<Chain>
}
.doOnError { t ->
log.error("Failed to get description from $host:$port", t)
}
//TODO subscribe only after receiving details
client.subscribeStatus(BlockchainOuterClass.StatusRequest.newBuilder().build())
.subscribe { value ->

View File

@@ -10,4 +10,5 @@ interface Upstream {
fun getHead(): EthereumHead
fun getApi(): EthereumApi
fun getOptions(): UpstreamsConfig.Options
fun getSupportedTargets(): Set<String>
}