Exception handling signatures (#97)

Minimally work around leaking `Exception` for
https://github.com/status-im/nim-chronos/pull/166
This commit is contained in:
Jacek Sieka 2021-03-26 11:53:03 +01:00 committed by GitHub
parent 4eb39203eb
commit ac5288651c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 23 additions and 10 deletions

View File

@ -10,11 +10,12 @@ export
type
ClientId* = int64
MethodHandler* = proc (j: JsonNode) {.gcsafe, raises: [Defect, CatchableError].}
RpcClient* = ref object of RootRef
awaiting*: Table[ClientId, Future[Response]]
lastId: ClientId
methodHandlers: Table[string, proc(j: JsonNode) {.gcsafe.}]
onDisconnect*: proc() {.gcsafe.}
methodHandlers: Table[string, MethodHandler]
onDisconnect*: proc() {.gcsafe, raises: [Defect].}
Response* = JsonNode
@ -26,10 +27,13 @@ proc rpcCallNode*(path: string, params: JsonNode, id: ClientId): JsonNode =
%{"jsonrpc": %"2.0", "method": %path, "params": params, "id": %id}
method call*(client: RpcClient, name: string,
params: JsonNode): Future[Response] {.gcsafe, async, base.} =
params: JsonNode): Future[Response] {.
base, async, gcsafe, raises: [Defect, CatchableError].} =
discard
method close*(client: RpcClient) {.base, gcsafe, async.} = discard
method close*(client: RpcClient): Future[void] {.
base, async, gcsafe, raises: [Defect, CatchableError].} =
discard
template `or`(a: JsonNode, b: typed): JsonNode =
if a == nil: b else: a
@ -37,7 +41,10 @@ template `or`(a: JsonNode, b: typed): JsonNode =
proc processMessage*(self: RpcClient, line: string) =
# Note: this doesn't use any transport code so doesn't need to be
# differentiated.
let node = parseJson(line)
let node = try: parseJson(line)
except CatchableError as exc: raise exc
# TODO https://github.com/status-im/nimbus-eth2/issues/2430
except Exception as exc: raise (ref ValueError)(msg: exc.msg, parent: exc)
if "id" in node:
let id = node{"id"} or newJNull()
@ -164,7 +171,7 @@ proc processRpcSigs(clientType, parsedCode: NimNode): NimNode =
var procDef = createRpcFromSig(clientType, line)
result.add(procDef)
proc setMethodHandler*(cl: RpcClient, name: string, callback: proc(j: JsonNode) {.gcsafe.}) =
proc setMethodHandler*(cl: RpcClient, name: string, callback: MethodHandler) =
cl.methodHandlers[name] = callback
proc delMethodHandler*(cl: RpcClient, name: string) =

View File

@ -170,7 +170,8 @@ proc httpMethod*(client: RpcHttpClient, m: HttpMethod) =
client.options.httpMethod = m
method call*(client: RpcHttpClient, name: string,
params: JsonNode): Future[Response] {.async, gcsafe.} =
params: JsonNode): Future[Response] {.
async, gcsafe, raises: [Defect, CatchableError].} =
## Remotely calls the specified RPC method.
let id = client.getNextId()

View File

@ -18,7 +18,8 @@ proc newRpcSocketClient*: RpcSocketClient =
RpcSocketClient.new()
method call*(self: RpcSocketClient, name: string,
params: JsonNode): Future[Response] {.async.} =
params: JsonNode): Future[Response] {.
async, gcsafe, raises: [Defect, CatchableError].} =
## Remotely calls the specified RPC method.
let id = self.getNextId()
var value = $rpcCallNode(name, params, id) & "\r\n"

View File

@ -19,7 +19,8 @@ proc newRpcWebSocketClient*: RpcWebSocketClient =
RpcWebSocketClient.new()
method call*(self: RpcWebSocketClient, name: string,
params: JsonNode): Future[Response] {.async.} =
params: JsonNode): Future[Response] {.
async, gcsafe, raises: [Defect, CatchableError].} =
## Remotely calls the specified RPC method.
let id = self.getNextId()
var value = $rpcCallNode(name, params, id) & "\r\n"

View File

@ -10,7 +10,7 @@ type
StringOfJson* = JsonString
# Procedure signature accepted as an RPC call by server
RpcProc* = proc(input: JsonNode): Future[StringOfJson] {.gcsafe.}
RpcProc* = proc(input: JsonNode): Future[StringOfJson] {.gcsafe, raises: [Defect, CatchableError].}
RpcRouter* = object
procs*: Table[string, RpcProc]
@ -90,6 +90,9 @@ proc route*(router: RpcRouter, data: string): Future[string] {.async, gcsafe.} =
try: parseJson(data)
except CatchableError as err:
return string(wrapError(JSON_PARSE_ERROR, err.msg))
except Exception as err:
# TODO https://github.com/status-im/nimbus-eth2/issues/2430
return string(wrapError(JSON_PARSE_ERROR, err.msg))
return string(await router.route(node))