zio / zio-actors

A high-performance, purely-functional library for building, composing, and supervising typed actors based on ZIO
https://zio.dev/zio-actors
Apache License 2.0
268 stars 56 forks source link

Receiving multiple responses asynchronously #268

Open nightscape opened 4 years ago

nightscape commented 4 years ago

Hi all,

I'm trying to write a zio-actor for the originally Akka based Petri Net implementation Kagera. The Akka implementation does one thing that I don't know how to do in zio-actors: When an actor A sends the Petri Net actor B a command to fire a transition, B sends a corresponding TransitionResponse (that's easy to do in zio-actors), but then other transitions can automatically fire and in the Akka implementation this sends additional TransitionResponses back to A asynchronously whenever the automatic transitions have fired (corresponding test). Afais, a Stateful actor never gets to know the actor who sent it a message, so just sending A an additional TransitionResponse via ! won't work. The only idea I have for implementing this in zio-actors is to return a Seq[TransitionResponse], but that means that one has to await all transitions to finish before sending the response.

I hope this is understandable without knowing too much about Petri Nets.

Is there any way to get something like this to work?

nightscape commented 4 years ago

One conceptually nice solution for this use case might be to allow the response to be a zio.stream.Stream[Nothing, TransitionResponse]. One could add something like this to the part of the code that sends the response:

for {
  // ...
  response <- actor.unsafeOp(envelope.command).either
  _        <- response match {
    case stream: zio.stream.Stream[_, Any] => stream.foreach(writeToWire(worker, _))
    case _ => writeToWire(worker, response)
  }
} yield ()
devas123 commented 2 years ago

I may be misunderstood the question, but this problem can also arise in Akka Typed. In Akka untyped context contains the sender reference which can be used to send the replies in async way. But in Akka Typed there is no sender() https://doc.akka.io/docs/akka/current/typed/from-classic.html#sender

So the solution in your case could be to just pass the sender along with the message and use ! to send the replies to the sender.

nightscape commented 2 years ago

Yes, that would be an option, but less elegant than the ZStream version because it requires working with callbacks instead of the nice collection-like abstraction that streams provide.