播放斯卡拉阿卡的WebSockets改变演员路径
问题描述:
我是按照使用Scala创建Web套接字播放和阿卡演员的例子:播放斯卡拉阿卡的WebSockets改变演员路径
在恢复时,控制器:
import play.api.mvc._
import play.api.libs.streams._
class Controller1 @Inject() (implicit system: ActorSystem, materializer: Materializer) {
def socket = WebSocket.accept[String, String] { request =>
ActorFlow.actorRef(out => MyWebSocketActor.props(out))
}
而且演员:
import akka.actor._
object MyWebSocketActor {
def props(out: ActorRef) = Props(new MyWebSocketActor(out))
}
class MyWebSocketActor(out: ActorRef) extends Actor {
def receive = {
case msg: String =>
out ! ("I received your message: " + msg)
}
}
演员创建(每个websocket一个连接)是/用户角色的孩子。我创建了3个连接,创造了男演员依次为:
- /用户/ $ B
- /用户/ $ C
- /用户/ $ d
我想改变基于Web套接字消息的字段中的角色名称。我怎么能这样做?
答
据ActorFlow源代码,它是目前无法thange实际演员的名称的连接产生了(线38):
Sink.actorRef(factory.actorOf(Props(new Actor { ... }) /*, name parameter is omitted */)
然而,ActorFlow.actorRef
接受一个隐含ActorRefFactory
,其在代码中的所有情况下都是implicit system: ActorSystem
。我们知道,有2个最常见的ActorRefFactory:ActorSystem
和ActorContext
。您可以修改代码,以便每次连接被接受时,另一个虚拟演员会产生您的首选名称(例如myActor1
),然后将此新演员的context
改为ActorFlow.actorRef
。作为回报,演员的连接将被命名如下:
- /用户/ myActor1/$一个
- /用户/ myActor2/$一个
- 等
答
您可以设置名称演员如下:
-
创建一个文件BetterActorFlow.scala
package your.package import akka.actor._ import akka.stream.scaladsl.{Keep, Sink, Source, Flow} import akka.stream.{Materializer, OverflowStrategy} object BetterActorFlow { def actorRef[In, Out](props: ActorRef => Props, bufferSize: Int = 16, overflowStrategy: OverflowStrategy = OverflowStrategy.dropNew, maybeName: Option[String] = None)(implicit factory: ActorRefFactory, mat: Materializer): Flow[In, Out, _] = { val (outActor, publisher) = Source.actorRef[Out](bufferSize, overflowStrategy) .toMat(Sink.asPublisher(false))(Keep.both).run() def flowActorProps: Props = { 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.Stop } }) } def actorRefForSink = maybeName.fold(factory.actorOf(flowActorProps)) { name => factory.actorOf(flowActorProps, name) } Flow.fromSinkAndSource(Sink.actorRef(actorRefForSink, Status.Success(())), Source.fromPublisher(publisher)) } }
-
使用BetterActorFlow代替ActorFlow:
BetterActorFlow.actorRef(out => ChatActor.props(out), 16, OverflowStrategy.dropNew, Some("alicebob"))
这为我工作。创建的演员在user/alicebob
(与context.system.actorSelection("user/alicebob")
一起使用)
有没有办法让'ActorFlow.actoRef'创建的actorRef被创建为特定Actor的子元素? 我想让它成为所有websocket演员都是我可以用来协调它们的主演员的子项。 – Nathan