How to complete a request in another actor when using akka-http

醉酒当歌 提交于 2019-12-21 09:29:38

问题


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?


回答1:


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



回答2:


you may try even better like:

package controllers

import akka.actor.{Actor, ActorSystem, Props}
import akka.stream.ActorMaterializer

import scala.concurrent.{Await, Future}
import akka.http.scaladsl.server.Directives._
import akka.stream.ActorMaterializer
import akka.util.Timeout
import akka.pattern.ask
import scala.concurrent.Await
import scala.concurrent.duration._
import scala.io.StdIn
import akka.actor._

import akka.util.Timeout


case object Message

class TestActor(name:String) extends Actor {
  def receive = {
    case Message =>
      sender ! "Testing Ask pattern Approach"
      println(s"hello from $name")

    case _ =>

      println("that was unexpected")
  }
}

object AskTest extends App {

  implicit val system= ActorSystem("myactor")
  implicit val material=ActorMaterializer()

//  implicit val props=Props.empty
implicit val timeout = Timeout(5 seconds)
  implicit val result =system.actorOf(Props(new TestActor("TestingName")),name = "Scala")

   val future3:Future[String]= ask(result ,Message).mapTo[String]
  val results = Await.result(future3, 2 seconds)
  println(results)
}


来源:https://stackoverflow.com/questions/32011503/how-to-complete-a-request-in-another-actor-when-using-akka-http

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!