如何在Play Framework中设置websocket actor的监督策略?

时间:2017-10-18 15:26:28

标签: scala playframework websocket akka

在Play 2.6中,我在控制器中使用以下代码来启动WebSocket actor:

def ws: WebSocket = WebSocket.accept[JsValue, JsValue] { request =>
  ActorFlow.actorRef { out =>
      WebSocketActor.props(request.id.toString, out)
  }
}

Internally Play将创建一个接收器演员,我的演员(WebSocketActor)将被创建为该演员的孩子。接收器actor提供了一些默认监督策略(错误Stop),但我想设置自己的策略,以便在发生故障时重新启动WebSocketActor。我该怎么办?

1 个答案:

答案 0 :(得分:0)

播放ActorFlow并没有提供一种方法来覆盖其主管策略,即在抛出异常时停止您的actor。但是,您可以使用您选择的策略定义自己的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)
  }
}