Use Future in Spray Routing

akka, scala, spray

Solution

You can use the `onSuccess` directive:

get {
    optionalCookie("commToken") { cookie =>
      //....
      val response = (MTurkerProgressActor ? Register).mapTo[..].map({...})
      onSuccess(response) {
        case (result, mTurkerResponse) =>
          setCookie(HttpCookie("commToken", content = mTurkerResponse.mturker.get.commToken)) {
            complete(result, mturkerResponse.mturker.get)
          }
      }
    }

There's also `onFailure` and `onComplete` (for which you have to match on `Success` and `Failure`) See http://spray.io/documentation/1.2.1/spray-routing/future-directives/onComplete/

Also, instead of using `get` directly it's much more idiomatic to use `map` (I assume the `mturker` is an `Option` or something similar):

case (result, mTurkerResponse) =>
  mTurkerResponse.mturker.map { mt =>
    setCookie(HttpCookie("commToken", content = mt.commToken)) {
      complete(result, mt)
    }
  }

Problem

I'm new to asynchronous programming. I read this tutorial http://danielwestheide.com/blog/2013/01/09/the-neophytes-guide-to-scala-part-8-welcome-to-the-future.html and was surprised by how effortless I can incorporate Future into the program. However, when I was using Future with Routing, the return type is kind of wrong. ``` get { optionalCookie("commToken") { case Some(commCookie) => val response = (MTurkerProgressActor ? Register).mapTo[..].map({...}) val result = Await.result(response, 5 seconds) setCookie(HttpCookie("commToken", content = result._2.mturker.get.commToken)) { complete(result._1, result._2.mturker.get) } case None => // ... } } ``` I really don't want to use `Await` (what's the point of asynchronous if I just block the thread and wait for 5 seconds?). I tried to use `for`-comprehension or `flatMap` and place the `setCookie` and `complete` actions inside, but the return type is unacceptable to Spray. For-comprehension returns "Unit", and `flatMap` returns a Future. Since I need to set up this cookie, I need the data inside. Is `Await` the solution? Or is there a smatter way?

Original source