Say I have the following schema defined:
object CalculatorSchema {
case class AddRequest(x: Int, y: Int)
case class AddReply(sum: Int)
case class SubtractRequest(x: Int, y: Int)
case class SubtractReply(diff: Int)
// Some code to pair off Requests with respective Replies
...
}
A possible mapping might be:
class RR[Req, Rep]
def rr[Req, Rep] = new RR[Req, Rep]()
// within CalculatorSchema, we then define the ff:
val mapping = rr[AddRequest, AddReply] ::
rr[SubtractRequest, SubtractReply] ::
HNil // from shapeless
I want to be able to build a client in the following manner:
val calcClient = RpcGen.createClient(CalculatorSchema)
Wherein the following should hold true:
val r1: AddReply = calcClient.process(AddRequest(1, 2)) // compiles
val r2 = calcClient.process(SomethingElse(99)) // does not compile
We assume that all clients, in order to process the request does something like:
def process[Req, Rep](req: Req): Rep = {
val serialized = serialize[Req](req)
val rawResponse = sendOverHttpAndAwaitResponse(serialized)
deserialize[Rep](rawResponse)
}
Also, how can we define a server that accepts a given schema? Logic of the server should be something like:
object CalculatorServer {
def process(req: AddRequest) = AddReply(req.x + req.y)
def process(req: SubtractRequest) = SubtractReply(req.x - req.y)
}
But how do we assert that CalculatorServer
should handle all the Request
from CalculatorSchema
and return the proper Reply
for each?
Also how do we define the following:
RpcGen.startHttpServer(CalculatorSchema, CalculatorServer)
Wherein logic of startServer
goes along the lines of:
def startHttpServer(schema: ???, server: ???): Unit = {
Http.startServer(9090) { httpReq: HttpReq =>
val req: ??? = fromHttpReq(httpReq)
val resp: ??? server.process(req)
Ok(resp)
}
}