Play 的ActorFlow 没有提供一种方法来覆盖其主管策略,即在引发异常时停止您的演员。但是,您可以使用您选择的策略简单地定义自己的 ActorFlow 副本:
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)
)
}
}
然后在你的控制器中使用这个替代方案:
def ws: WebSocket = WebSocket.accept[JsValue, JsValue] { request =>
ActorFlowAlt.actorRef { out =>
WebSocketActor.props(request.id.toString, out)
}
}