support data field in error response

This commit is contained in:
a10zn8
2023-06-06 17:08:57 +04:00
committed by GitHub
parent 0db052024b
commit df8586258f
5 changed files with 32 additions and 35 deletions

View File

@@ -116,7 +116,7 @@ abstract class BaseHandler(
// If Proxy is configured to preserve original order it means that a client expect responses at exact same position
// as requests even if a request completely failed for a some reason. It's very unlikely situation, but still possible
// At this case, if we found a gap in responses, we put a default response with an error
?: NativeCall.CallResult(id, null, null, NativeCall.CallError(id, "No response", null), null, null, null)
?: NativeCall.CallResult(id, null, null, NativeCall.CallError(id, "No response", null, null), null, null, null)
}
}
.flatMapMany {

View File

@@ -203,7 +203,12 @@ open class NativeCall(
.setId(it.id)
if (it.isError()) {
it.error?.let { error ->
result.setErrorMessage(error.message).setErrorCode(error.id)
result.setErrorMessage(error.message)
.setErrorCode(error.id)
error.data?.let { data ->
result.setErrorData(data)
}
}
} else {
result.payload = ByteString.copyFrom(it.result)
@@ -301,7 +306,8 @@ open class NativeCall(
CallError(
requestItem.id,
errorMessage,
JsonRpcError(RpcResponseError.CODE_METHOD_NOT_EXIST, errorMessage)
JsonRpcError(RpcResponseError.CODE_METHOD_NOT_EXIST, errorMessage),
null
),
requestId,
requestCount
@@ -409,7 +415,7 @@ open class NativeCall(
counter.get().let { attempts ->
CallResult.fail(
ctx.id, ctx.nonce,
CallError(1, "No response or no available upstream for ${ctx.payload.method}", null),
CallError(1, "No response or no available upstream for ${ctx.payload.method}", null, null),
ctx
).also {
countFailure(attempts, ctx)
@@ -592,20 +598,33 @@ open class NativeCall(
open class CallFailure(val id: Int, val reason: Throwable) : Exception("Failed to call $id: ${reason.message}")
open class CallError(val id: Int, val message: String, val upstreamError: JsonRpcError?) {
open class CallError(val id: Int, val message: String, val upstreamError: JsonRpcError?, val data: String?) {
companion object {
private val log = LoggerFactory.getLogger(CallError::class.java)
private fun getDataAsSting(details: Any?): String? {
return when (details) {
is String -> details
null -> null
else -> {
log.debug("Unsupported error details: {}", details)
null
}
}
}
fun from(t: Throwable): CallError {
return when (t) {
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)
is JsonRpcException -> CallError(t.id.asNumber().toInt(), t.error.message, t.error, getDataAsSting(t.error.details))
is RpcException -> CallError(t.code, t.rpcMessage, null, getDataAsSting(t.details))
is CallFailure -> CallError(t.id, t.reason.message ?: "Upstream Error", null, 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)
CallError(1, t.message ?: "Upstream Error", null, null)
}
}
}

View File

@@ -17,7 +17,7 @@ package io.emeraldpay.dshackle.upstream.rpcclient
import io.emeraldpay.etherjar.rpc.RpcException
class JsonRpcError(val code: Int, val message: String, val details: Any?) {
data class JsonRpcError(val code: Int, val message: String, val details: Any?) {
constructor(code: Int, message: String) : this(code, message, null)
@@ -33,26 +33,4 @@ class JsonRpcError(val code: Int, val message: String, val details: Any?) {
fun asException(id: JsonRpcResponse.Id?): JsonRpcException {
return JsonRpcException(id ?: JsonRpcResponse.NumberId(-1), this, false)
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is JsonRpcError) return false
if (code != other.code) return false
if (message != other.message) return false
if (details != other.details) return false
return true
}
override fun hashCode(): Int {
var result = code
result = 31 * result + message.hashCode()
result = 31 * result + (details?.hashCode() ?: 0)
return result
}
override fun toString(): String {
return "JsonRpcError(code=$code, message='$message', details=$details)"
}
}