如何从ActorFlow获取Actor引用(ActorRef)?

3
根据关于WebSockets的Play文档,建立WebSocket的标准方法是使用ActorFlow.actorRef,该方法接受一个返回我的actor的Props函数。我的目标是获取对此基础ActorRef的引用,例如为了发送第一条消息或将ActorRef传递给另一个actor的构造函数。
就最小化示例而言,我正在尝试实现这一点:
class WebSocketController @Inject() (implicit system: ActorSystem, materializer: Materializer) {

  def socket = WebSocket.accept[String, String] { request =>
    val flow = ActorFlow.actorRef { out => MyWebSocketActor.props(out) }
    // How to get the ActorRef that is created by MyWebSocketActor.props(out)?
    // Fictitious syntax (does not work)
    flow.underlyingActor ! "first message send"
    flow
  }
}

我怎么才能获取到创建的 actor 的引用呢?

如果此时无法获取 ActorRef (可能需要将 flow 材料化),那么存储所创建 actor 的引用最简单的方法是什么?

1个回答

1
使用Actor.preStart()钩子,您可以进行一些技巧来访问actorRef:
class MyWebSocketActor(
  out: ActorRef, 
  firstMessage: Any, 
  actorRegistry: ActorRef
) extends Actor {
  import play.api.libs.json.JsValue
  override def preStart(): Unit = {
    self ! firstMessage
    actorRegistry ! self
  }
  ...
}

def socket = WebSocket.accept[String, String] { request =>
  ActorFlow.actorRef { out => 
    Props(new MyWebSocketActor(out, "First Message", someRegistryActorRef)) 
  }
}

我希望可以避免使用 actorRegistry 方法。在我的实际用例中,我已经实现了一个朝着这个方向的解决方案,但生成的代码相当复杂,而且感觉我需要把一个非常简单的逻辑散布到许多不必要的部分中去。 - bluenote10
@bluenote10 我认为,获取底层的actorRef会破坏封装性,因为它的生命周期由流程管理,你可能会得到一个指向已死亡的actor的引用,因为该actor的名称不唯一,因此不能保证其邮箱在重生后被传递。 - Tair
@bluenote10,我不确定有没有所谓的“正确”方法,但你完全可以重新实现ActorFlow.actorOf。源代码是公开的:) - Tair
我尝试过,但我认为这是不可能的,因为对输出演员的引用只有在稍后才可用。 - bluenote10
1
@bluenote10 可以实现,这里有一个快速原型 https://gist.github.com/tsabirgaliev/4168639e991bd13e364c54def5c6d2cd - Tair

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接