The akka http documentation mentions in the high level client request API documentation that we should not use access actor state form inside a Future in an actor.
Instead, this should be the pattern used:
import akka.actor.Actor
import akka.http.scaladsl.Http
import akka.http.scaladsl.model._
import akka.stream.scaladsl.ImplicitMaterializer
class Myself extends Actor
with ImplicitMaterializer
with ActorLogging {
import akka.pattern.pipe
import context.dispatcher
val http = Http(context.system)
override def preStart() = {
http.singleRequest(HttpRequest(uri = "http://akka.io"))
.pipeTo(self)
}
def receive = {
case HttpResponse(StatusCodes.OK, headers, entity, _) =>
log.info("Got response, body: " + entity.dataBytes.runFold(ByteString(""))(_ ++ _))
case HttpResponse(code, _, _, _) =>
log.info("Request failed, response code: " + code)
}
}
Should we do something similar when using cachedHostConnectionPool ?
ex:
import akka.actor.Actor
import akka.http.scaladsl.Http
import akka.http.scaladsl.model._
import akka.stream.scaladsl.ImplicitMaterializer
class Myself extends Actor
with ImplicitMaterializer
with ActorLogging {
import akka.pattern.pipe
import context.dispatcher
var state = 10
val http = Http(context.system)
val pool = http.cachedHostConnectionPoolTls[Int](apiEndpoint.authority.host.toString())
override def preStart() = {
Source.single(HttpRequest(uri = "http://akka.io") -> 42)
.via(poolClientFlow)
.runWith(Sink.head)
.pipeTo(self)
}
def receive = {
case (res, ref) => ref match {
case 42 => state -= 1 // Do something with the response
}
}
}
If so why do we need that ? Could not find the explanation in the doc If not, what's the correct pattern ?
Thank you
pipeTois the right thing to do because if you don't you could run into concurrent mods to that state and lose the benefit of the actor. If you do not need to mutate/deal with state after the future is done then no, you don't need to pipe back to self. - cmbaxter