0

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)
  }
}
jvliwanag
  • 1,508
  • 1
  • 13
  • 29
  • Make your "schema" a trait. And check your textbook or notes from class, there must be lots of info there. Come up with your own solution first. Then, of you have any concrete problems or questions, come back and show what you have. We can help. – Dima Apr 02 '16 at 12:29
  • Hm. I don't think this is an easy problem. Consider for one that we should allow mapping Request types to their respective Response types to be totally arbitrary. Also, `calcClient.process` should be polymorphic - the reply must be of the correct type based on the input. – jvliwanag Apr 02 '16 at 14:28
  • This is somehow a continuation of my previous query: http://stackoverflow.com/questions/36310264/how-to-define-a-function-whose-output-type-depends-on-the-input-type – jvliwanag Apr 02 '16 at 14:33
  • I don't know what about it you find "not easy". `def foo(request: Bar): Bat` _is_ a mapping between request and response types. – Dima Apr 02 '16 at 17:02

0 Answers0