mirror of
https://github.com/corda/corda.git
synced 2025-06-16 22:28:15 +00:00
Delay RPC arguments deserialisation to allow routing of errors
This commit is contained in:
@ -19,6 +19,7 @@ import net.corda.core.internal.LifeCycle
|
||||
import net.corda.core.messaging.RPCOps
|
||||
import net.corda.core.serialization.SerializationContext
|
||||
import net.corda.core.serialization.SerializationDefaults.RPC_SERVER_CONTEXT
|
||||
import net.corda.core.serialization.deserialize
|
||||
import net.corda.core.utilities.Try
|
||||
import net.corda.core.utilities.debug
|
||||
import net.corda.core.utilities.loggerFor
|
||||
@ -260,34 +261,26 @@ class RPCServer(
|
||||
|
||||
private fun clientArtemisMessageHandler(artemisMessage: ClientMessage) {
|
||||
lifeCycle.requireState(State.STARTED)
|
||||
|
||||
// Attempt de-serialisation of the RPC request message, in such a way that we can route the error back to
|
||||
// the RPC that was being tried if it fails in a method/rpc specific way.
|
||||
val clientToServerTry = Try.on { RPCApi.ClientToServer.fromClientMessage(RPC_SERVER_CONTEXT, artemisMessage) }
|
||||
val clientToServer = try {
|
||||
clientToServerTry.getOrThrow()
|
||||
} catch (e: RPCApi.ArgumentDeserialisationException) {
|
||||
// The exception itself has a more informative error message, and this could be caused by buggy apps, so
|
||||
// let's just log it as a warning instead of an error. Relay the failure to the client so they can see it.
|
||||
log.warn("Inbound RPC failed", e)
|
||||
sendReply(e.reqWithNoArguments.id, e.reqWithNoArguments.clientAddress, Try.Failure(e.cause!!))
|
||||
return
|
||||
} catch (e: Exception) {
|
||||
// This path indicates something more fundamental went wrong, like a missing message header.
|
||||
log.error("Failed to parse an inbound RPC: version skew between client and server?", e)
|
||||
return
|
||||
} finally {
|
||||
artemisMessage.acknowledge()
|
||||
}
|
||||
|
||||
// Now try dispatching the request itself.
|
||||
val clientToServer = RPCApi.ClientToServer.fromClientMessage(artemisMessage)
|
||||
log.debug { "-> RPC -> $clientToServer" }
|
||||
when (clientToServer) {
|
||||
is RPCApi.ClientToServer.RpcRequest -> {
|
||||
val rpcContext = RpcContext(currentUser = getUser(artemisMessage))
|
||||
rpcExecutor!!.submit {
|
||||
val result = invokeRpc(rpcContext, clientToServer.methodName, clientToServer.arguments)
|
||||
sendReply(clientToServer.id, clientToServer.clientAddress, result)
|
||||
val arguments = Try.on {
|
||||
clientToServer.serialisedArguments.deserialize<List<Any?>>(context = RPC_SERVER_CONTEXT)
|
||||
}
|
||||
when (arguments) {
|
||||
is Try.Success -> {
|
||||
val rpcContext = RpcContext(currentUser = getUser(artemisMessage))
|
||||
rpcExecutor!!.submit {
|
||||
val result = invokeRpc(rpcContext, clientToServer.methodName, arguments.value)
|
||||
sendReply(clientToServer.id, clientToServer.clientAddress, result)
|
||||
}
|
||||
}
|
||||
is Try.Failure -> {
|
||||
// We failed to deserialise the arguments, route back the error
|
||||
log.warn("Inbound RPC failed", arguments.exception)
|
||||
sendReply(clientToServer.id, clientToServer.clientAddress, arguments)
|
||||
}
|
||||
}
|
||||
}
|
||||
is RPCApi.ClientToServer.ObservablesClosed -> {
|
||||
|
Reference in New Issue
Block a user