I am using akka-http 1.0 and I would like to use a route defined as
def route: Route = path("") {
// start actor with requestContext
// call requestContext.complete(...) in actor with the result
}
How do I accomplish this?
The Akka HTTP modules implement a full server- and client-side HTTP stack on top of akka-actor and akka-stream . A typical application does not sit on top of Akka HTTP. Instead, Akka HTTP makes it easier to build integration layers based on HTTP, and therefore stays on the sidelines.
Akka ensures that each instance of an actor runs in its own lightweight thread and its messages are processed one at a time. If this is the case that AKKA actors processes its messages sequentially then how AKKA provides concurrency for a single Actor.
Akka HTTP implements a full server stack for HTTP, including full HTTPS support, and has support for HTTP/2. The Akka HTTP server backend is the default in Play. You can also use the Netty backend if you choose.
Elaborating on @jrudolph's comment, the below code satisfies your requirements of dispatching RequestContext values to an Actor. Your question indicated that you wanted a new Actor for each request; however, the below code uses the same Actor for all requests which I think is a more efficient/likely use case. The Actor creation can always be moved inside handleRequest if needed.
First we need an Actor for processing a request to a response:
import akka.actor.Actor
import akka.http.scaladsl.server.{RequestContext, RouteResult}
import akka.http.scaladsl.model.HttpResponse
class RequestActor extends Actor {
//business logic - returns empty HttpResponse
def handleRequestMessage(requestContext : RequestContext) =
RouteResult.Complete(new HttpResponse())
override def receive = {
case reqContext : RequestContext =>
sender ! handleRequestMessage(reqContext)
}
}//end class RequestActor
Now create a utility function for querying the Actor:
import akka.actor.ActorRef
import scala.concurrent.Future
import akka.pattern.ask
object RequestActor {
val handleRequest : ActorRef => RequestContext => Future[RouteResult] =
(actorRef) =>
(requestContext) =>
ask(actorRef,reqContext).mapTo[RouteResult]
}
And all that is left to do is wire everything together into a service:
import akka.actor.{ActorSystem, Props}
import akka.stream.ActorMaterializer
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Directives.{get,path}
import akka.util.Timeout
object RouteActorTest extends App {
implicit val as = ActorSystem("RouteActorTest")
implicit val timeout = new Timeout(1000)
val sendRequestToActor : RequestContext => Future[RouteResult] =
RequestActor handleRequest (as actorOf Props[RequestActor])
val route = path("")(get(sendRequestToActor))
//rest of application...
}//end object RouteActorTest
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With