Le jeu ActorFlow
de Play ne permet pas de contourner sa stratégie de superviseur consistant à arrêter votre acteur lorsqu'une exception est levée. Vous pouvez cependant définir simplement votre propre copie de ActorFlow
avec la stratégie de votre choix:
import akka.actor._
import akka.stream.{ Materializer, OverflowStrategy }
import akka.stream.scaladsl.{ Sink, Keep, Source, Flow }
object ActorFlowAlt {
def actorRef[In, Out](props: ActorRef => Props, bufferSize: Int = 16, overflowStrategy: OverflowStrategy = OverflowStrategy.dropNew)(implicit factory: ActorRefFactory, mat: Materializer): Flow[In, Out, _] = {
val (outActor, publisher) = Source.actorRef[Out](bufferSize, overflowStrategy)
.toMat(Sink.asPublisher(false))(Keep.both).run()
Flow.fromSinkAndSource(
Sink.actorRef(factory.actorOf(Props(new Actor {
val flowActor = context.watch(context.actorOf(props(outActor), "flowActor"))
def receive = {
case Status.Success(_) | Status.Failure(_) => flowActor ! PoisonPill
case Terminated(_) => context.stop(self)
case other => flowActor ! other
}
override def supervisorStrategy = OneForOneStrategy() {
case _ => SupervisorStrategy.Restart // <--- restart instead of stop
}
})), Status.Success(())),
Source.fromPublisher(publisher)
)
}
}
Ensuite, utilisez cette option dans votre contrôleur:
def ws: WebSocket = WebSocket.accept[JsValue, JsValue] { request =>
ActorFlowAlt.actorRef { out =>
WebSocketActor.props(request.id.toString, out)
}
}
Merci. J'y ai aussi réfléchi mais je pensais qu'il y aurait peut-être une meilleure façon de le faire. – Piotr