scala - Akka actor system with HTTP interface -


i'm trying create akka system among other things respond http requests. created few actors exchange messages fine. can use akka-http respond http requests. problem in connecting 2 parts.

tl;dr: how talk akka actors during akka-http request processing?

i created single actor responsible bringing http system:

class httpactor extends actor actorlogging  {   /* implicits elided */    private def inithttp() = {     val route: route =  path("status") { { complete { "ok" } } }     http()(context.system).bindandhandle(route, "localhost", 8080)   }   private var bound: option[future[http.serverbinding]] = none    override def receive = {     case httpactor.init =>       bound match {         case some(x) => log.warning("http bootstrapping")         case none =>           bound = some(inithttp(watcher))       }    } }  object httpactor {   case object init } 

as may see, actor creates akka-http service on first message receives (no reason, really, in constructor well).

now, during request processing need communicate other actors, , can't working.

my approach:

  private def initinteractivehttp() = {     val route: route =  path("status") {        { complete { "ok" } }      } ~ path("ask") {       { complete {         // here interesting 2 lines:         val otheractorresponse = someotheractor ? somemessage         otheractorresponse.mapto[string]     } }     http()(context.system).bindandhandle(route, "localhost", 8080)   } 

this send somemessage someotheractor , wait response prior completing request-response cycle. understand, however, messages sent root httpactor, bad , leads in terms of scalability. ideally create distinct instance of specialized actor every request, fails due akka-http typing. consider following example:

class disposableactor(httpcontext: httpcontext) {     override def prestart() = {        // ... send questions other actors     }     override def receive = {       case gotalldata(x) => httpcontext.complete(x)     } }  class httpactorwithdisposables {   // there `context` value in scope - we're actor, after   private def inithttpwithdisposableactors() = {     val route: route =  path("status") {        { complete { "ok" } }      } ~ path("ask") {       { httpcontext =>         val props = props(new disposableactor(httpcontext))         val disposableactor = context.actorof(props, "disposable-actor-name")         // have nothing return here       }     }     http()(context.system).bindandhandle(route, "localhost", 8080)   } 

with approach, can force disposableactor call httpcontext.complete @ point of time. should correctly end request-response processing cycle. route dsl, however, requires return valid response (or future) inside get block, approach doesn't work.

your first approach quite alright, actually. ask pattern creates lightweight, disposable actor waits on result (non-blockingly) complete future. things want replicate disposableactor , main httpactor not stressed this.

if still want use different actor, there completewith:

completewith(instanceof[string]) { complete =>   // complete of type string => unit   val props = props(new disposableactor(complete))   val disposableactor = context.actorof(props, "disposable-actor-name")    // completewith expects return unit } 

and in actor, call complete function when have result

class disposableactor(complete: string => unit) {   override def receive = {     case gotalldata(x) =>        complete(x)       context stop self // don't stop actor   } } 

Comments

Popular posts from this blog

javascript - jQuery: Add class depending on URL in the best way -

caching - How to check if a url path exists in the service worker cache -

Redirect to a HTTPS version using .htaccess -