mirror of
https://github.com/status-im/nim-json-rpc.git
synced 2025-02-24 18:28:10 +00:00
Make rpc transform use async
This commit is contained in:
parent
2f7b91c035
commit
ffc7a6378b
@ -1,10 +1,14 @@
|
|||||||
import macros, servertypes
|
import macros, servertypes, strutils
|
||||||
|
|
||||||
var rpcCallRefs {.compiletime.} = newSeq[(string)]()
|
var rpcCallRefs {.compiletime.} = newSeq[(string)]()
|
||||||
|
|
||||||
macro rpc*(prc: untyped): untyped =
|
macro rpc*(prc: untyped): untyped =
|
||||||
# REVIEW: (IMPORTANT) I think the rpc procs should be async.
|
## Converts a procedure into the following format:
|
||||||
# they may need to call into other async procs of the VM
|
## <proc name>*(params: JsonNode): Future[JsonNode] {.async.}
|
||||||
|
## This procedure is then added into a compile-time list
|
||||||
|
## so that it is automatically registered for every server that
|
||||||
|
## calls registerRpcs(server)
|
||||||
|
prc.expectKind nnkProcDef
|
||||||
result = prc
|
result = prc
|
||||||
let
|
let
|
||||||
params = prc.findChild(it.kind == nnkFormalParams)
|
params = prc.findChild(it.kind == nnkFormalParams)
|
||||||
@ -20,8 +24,13 @@ macro rpc*(prc: untyped): untyped =
|
|||||||
identDefs.add ident("params"), ident("JsonNode"), newEmptyNode()
|
identDefs.add ident("params"), ident("JsonNode"), newEmptyNode()
|
||||||
# check there isn't already a result type
|
# check there isn't already a result type
|
||||||
assert params.len == 1 and params[0].kind == nnkEmpty
|
assert params.len == 1 and params[0].kind == nnkEmpty
|
||||||
params[0] = ident("JsonNode")
|
params[0] = newNimNode(nnkBracketExpr)
|
||||||
|
params[0].add ident("Future"), ident("JsonNode")
|
||||||
params.add identDefs
|
params.add identDefs
|
||||||
|
# add async pragma, we can assume there isn't an existing .async.
|
||||||
|
# as this would fail the result check above.
|
||||||
|
prc.addPragma(newIdentNode("async"))
|
||||||
|
|
||||||
# Adds to compiletime list of rpc calls so we can register them in bulk
|
# Adds to compiletime list of rpc calls so we can register them in bulk
|
||||||
# for multiple servers using `registerRpcs`.
|
# for multiple servers using `registerRpcs`.
|
||||||
rpcCallRefs.add $procName
|
rpcCallRefs.add $procName
|
||||||
@ -33,3 +42,4 @@ macro registerRpcs*(server: RpcServer): untyped =
|
|||||||
for procName in rpcCallRefs:
|
for procName in rpcCallRefs:
|
||||||
let de = newDotExpr(ident($server), ident("register"))
|
let de = newDotExpr(ident($server), ident("register"))
|
||||||
result.add(newCall(de, newStrLitNode(procName), ident(procName)))
|
result.add(newCall(de, newStrLitNode(procName), ident(procName)))
|
||||||
|
echo result.repr
|
||||||
|
@ -20,7 +20,7 @@ proc processMessage(server: RpcServer, client: AsyncSocket, line: string) {.asyn
|
|||||||
if not server.procs.hasKey(methodName):
|
if not server.procs.hasKey(methodName):
|
||||||
await client.sendError(METHOD_NOT_FOUND, "Method not found", id, %(methodName & " is not a registered method."))
|
await client.sendError(METHOD_NOT_FOUND, "Method not found", id, %(methodName & " is not a registered method."))
|
||||||
else:
|
else:
|
||||||
let callRes = server.procs[methodName](node["params"])
|
let callRes = await server.procs[methodName](node["params"])
|
||||||
await client.send($wrapReply(id, callRes, newJNull()) & "\c\l")
|
await client.send($wrapReply(id, callRes, newJNull()) & "\c\l")
|
||||||
|
|
||||||
proc processClient(server: RpcServer, client: AsyncSocket) {.async.} =
|
proc processClient(server: RpcServer, client: AsyncSocket) {.async.} =
|
||||||
@ -33,12 +33,11 @@ proc processClient(server: RpcServer, client: AsyncSocket) {.async.} =
|
|||||||
|
|
||||||
ifDebug: echo "Process client: ", server.port, ":" & line
|
ifDebug: echo "Process client: ", server.port, ":" & line
|
||||||
|
|
||||||
let fut = processMessage(server, client, line)
|
let future = processMessage(server, client, line)
|
||||||
await fut
|
await future
|
||||||
if fut.failed:
|
if future.failed:
|
||||||
if fut.readError of RpcProcError:
|
if future.readError of RpcProcError:
|
||||||
# TODO: Currently exceptions in rpc calls are not properly handled
|
let err = future.readError.RpcProcError
|
||||||
let err = fut.readError.RpcProcError
|
|
||||||
await client.sendError(err.code, err.msg, err.data)
|
await client.sendError(err.code, err.msg, err.data)
|
||||||
else:
|
else:
|
||||||
await client.sendError(-32000, "Error", %getCurrentExceptionMsg())
|
await client.sendError(-32000, "Error", %getCurrentExceptionMsg())
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import asyncdispatch, asyncnet, json, tables
|
import asyncdispatch, asyncnet, json, tables
|
||||||
|
|
||||||
type
|
type
|
||||||
RpcProc* = proc (params: JsonNode): JsonNode
|
RpcProc* = proc (params: JsonNode): Future[JsonNode]
|
||||||
|
|
||||||
RpcServer* = ref object
|
RpcServer* = ref object
|
||||||
socket*: AsyncSocket
|
socket*: AsyncSocket
|
||||||
|
Loading…
x
Reference in New Issue
Block a user