problem: looses upstream error details

This commit is contained in:
a10zn8
2022-12-07 18:26:01 +04:00
parent 3a606fe0fe
commit 7b96f60228
2 changed files with 46 additions and 18 deletions

View File

@@ -284,11 +284,7 @@ open class NativeCall(
Mono.just(ctx).flatMap(this::executeOnRemote)
)
.onErrorResume {
if (it is CallFailure) {
Mono.just(CallResult.fail(it.id, ctx.nonce, it.reason))
} else {
Mono.just(CallResult.fail(ctx.id, ctx.nonce, it))
}
Mono.just(CallResult.fail(ctx.id, ctx.nonce, it))
}
}
@@ -310,21 +306,14 @@ open class NativeCall(
CallResult(ctx.id, ctx.nonce, bytes, null, it.signature, ctx.upstream.getId())
}
.onErrorResume { t ->
val failure = when (t) {
is CallFailure -> CallResult.fail(t.id, ctx.nonce, t.reason)
is JsonRpcException -> CallResult.fail(ctx.id, ctx.nonce, t.error.code, t.error.message)
else -> CallResult.fail(ctx.id, ctx.nonce, t)
}
Mono.just(failure)
Mono.just(CallResult.fail(ctx.id, ctx.nonce, t))
}
.switchIfEmpty(
Mono.fromSupplier {
counter.get().let { attempts ->
CallResult.fail(
ctx.id,
ctx.nonce,
1,
errorMessage(attempts, ctx.payload.method)
ctx.id, ctx.nonce,
CallError(1, "No response or no available upstream for ${ctx.payload.method}", null)
).also {
countFailure(attempts, ctx)
}
@@ -484,7 +473,15 @@ open class NativeCall(
is JsonRpcException -> CallError(t.id.asNumber().toInt(), t.error.message, t.error)
is RpcException -> CallError(t.code, t.rpcMessage, null)
is CallFailure -> CallError(t.id, t.reason.message ?: "Upstream Error", null)
else -> CallError(1, t.message ?: "Upstream Error", null)
else -> {
// May only happen if it's an unhandled exception.
// In this case try to find a meaningless details in the stack. Most important reason for doing that is to find an ID of the request
if (t.cause != null) {
from(t.cause!!)
} else {
CallError(1, t.message ?: "Upstream Error", null)
}
}
}
}
}
@@ -503,8 +500,8 @@ open class NativeCall(
return CallResult(id, nonce, result, null, signature, upstreamId)
}
fun fail(id: Int, nonce: Long?, errorCore: Int, errorMessage: String): CallResult {
return CallResult(id, nonce, null, CallError(errorCore, errorMessage, null), null, null)
fun fail(id: Int, nonce: Long?, error: CallError): CallResult {
return CallResult(id, nonce, null, error, null, null)
}
fun fail(id: Int, nonce: Long?, error: Throwable): CallResult {

View File

@@ -34,6 +34,8 @@ import io.emeraldpay.dshackle.upstream.Selector
import io.emeraldpay.dshackle.upstream.MultistreamHolder
import io.emeraldpay.dshackle.upstream.calls.DefaultEthereumMethods
import io.emeraldpay.dshackle.upstream.calls.ManagedCallMethods
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcError
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcException
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import io.emeraldpay.dshackle.upstream.signature.ResponseSigner
@@ -156,6 +158,35 @@ class NativeCallSpec extends Specification {
.verify(Duration.ofSeconds(1))
}
def "Returns error details from remote"() {
setup:
def quorum = new AlwaysQuorum()
def nativeCall = nativeCall()
nativeCall.quorumReaderFactory = Mock(QuorumReaderFactory) {
1 * create(_, _, _) >> Mock(Reader) {
1 * read(new JsonRpcRequest("eth_test", [], 10)) >> Mono.error(
new JsonRpcException(JsonRpcResponse.Id.from(12), new JsonRpcError(-32123, "Foo Bar", "Foo Bar Baz"))
)
}
}
def call = new NativeCall.ValidCallContext(12, 10, TestingCommons.multistream(TestingCommons.api()), Selector.empty, quorum,
new NativeCall.ParsedCallDetails("eth_test", []))
when:
def resp = nativeCall.executeOnRemote(call).block(Duration.ofSeconds(1))
then:
resp.isError()
with(resp.getError()) {
message == "Foo Bar"
upstreamError != null
with (upstreamError) {
code == -32123
details == "Foo Bar Baz"
}
}
}
def "Packs call exception into response with id"() {
setup:
def nativeCall = nativeCall()