2016-05-17 11 views
2

ich das Beispiel gefolgt sind Web Sockets mit Scala für die Erstellung von:Wiedergabe Scala Akka WebSockets Änderung Schauspieler Weg

https://www.playframework.com/documentation/2.5.x/ScalaWebSockets#Handling-WebSockets-with-Akka-Streams-and-actors

bei Wiederaufnahme der Controller:

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)) 
    } 

Und der Schauspieler:

Die Schauspieler erstellt (eine pro Websocket Verbindung) sind Kind von/Benutzer Schauspieler. Ich habe drei Verbindungen erstellt und der Schauspieler erstellt wurden:

  1. /user/$ b
  2. /user/$ c
  3. /user/$ d

Ich möchte das ändern Name der Schauspieler in einem Feld der Web-Socket-Nachricht. Wie könnte ich das tun?

Antwort

2

Nach dem Quellcode ActorFlow, ist es derzeit nicht möglich, den Namen des tatsächlichen Schauspieler thange für eine Verbindung hervorgebracht (Leitung 38):

Sink.actorRef(factory.actorOf(Props(new Actor { ... }) /*, name parameter is omitted */) 

jedoch ActorFlow.actorRef akzeptiert ein implizites ActorRefFactory, die ist implicit system: ActorSystem in allen Fällen in Ihrem Code. Wie wir wissen, gibt es zwei gängige ActorRefFactories: ActorSystem und ActorContext. Sie können Ihren Code so ändern, dass jedes Mal, wenn eine Verbindung akzeptiert wird, ein anderer Dummy-Actor mit Ihrem bevorzugten Namen erscheint (z. B. myActor1) und die des neuen Actors stattdessen an ActorFlow.actorRef übergeben wird. Im Gegenzug Akteure für Verbindungen wie folgt benannt werden würde:

  • /user/myActor1/$ ein
  • /user/myActor2/$ ein
  • etc
+1

Gibt es eine Möglichkeit, ich kann die actorRef erstellt von 'ActorFlow.actoRef' als Kind eines bestimmten Actor erstellt werden? Ich möchte es so machen, dass alle WebSocket Schauspieler Kinder eines Meisters sind, den ich verwenden kann, um sie zu koordinieren. – Nathan

2

Sie den Namen festlegen wie folgt des Darstellers:

  1. erstellen Sie eine Datei 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)) 
    
        } 
    } 
    
  2. Verwenden BetterActorFlow statt ActorFlow:

    BetterActorFlow.actorRef(out => 
        ChatActor.props(out), 16, OverflowStrategy.dropNew, Some("alicebob")) 
    

Das ist für mich gearbeitet. Der erstellte Schauspieler ist um user/alicebob (verwenden Sie das mit context.system.actorSelection("user/alicebob"))

Verwandte Themen