-
-
Notifications
You must be signed in to change notification settings - Fork 106
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Sender attribute? #40
Comments
This is me from the future - I suggest you guys take a look at Erlang instead of Akka for inspiration. This is what I ended up using instead. |
Thanks for the tip! We now have the
I'm open to other suggestions and to hear what expectations you have for this from other actor systems. |
please publish a release with this feature, to verify its usability in practice |
In Akka it works the following way:
var currentMessage: Envelope = _
final case class Envelope private (val message: Any, val sender: ActorRef)`
final def sender(): ActorRef = currentMessage match {
case null => system.deadLetters
case msg if msg.sender ne null => msg.sender
case _ => system.deadLetters
} Following this pattern, in Pykka it could be something like: class Envelope:
"""
Envelope to add metadata to a message.
This is an internal type and is not part of the public API.
:param message: the message to send
:type message: any
:param reply_to: the future to reply to if there is a response
:type reply_to: :class:`pykka.Future`
"""
# Using slots speeds up envelope creation with ~20%
__slots__ = ["message", "sender", "reply_to"]
def __init__(self, message, sender=None, reply_to=None):
self.message = message
self.reply_to = reply_to
self.sender = sender
... In def _actor_loop(self):
"""
The actor's event loop.
This is the method that will be executed by the thread or greenlet.
"""
try:
self.on_start()
except Exception:
self._handle_failure(*sys.exc_info())
while not self.actor_stopped.is_set():
envelope = self.actor_inbox.get()
self.current_message = envelope
... and def _sender(self):
sender = self.current_message.sender
if not sender:
sender = DeadLetters(self)
return sender where class DeadLetters(ActorRef):
def __repr__(self):
return f"<DeadLetters of {self}>"
def tell(self, message):
logger.warning("%s: Received message %s via 'tell'.", self.__repr__(), message)
def ask(self, message, block=True, timeout=None):
logger.warning("%s: Received message %s via 'ask'.", self.__repr__(), message) or something like this. Just to cover a situation when an actor tries to send something to a sender and this sender is not an actor. I don't mean, that's a great solution, but that's an example of how it's implemented in Akka Classic. Surely, it would be necessary to modify final def tell(msg: Any, sender: ActorRef): Unit = this.!(msg)(sender) So, to have something similar, we would need to do something like: def tell(self, message, sender=None):
"""
Send message to actor without waiting for any response.
Will generally not block, but if the underlying queue is full it will
block until a free slot is available.
:param message: message to send
:param sender: ActorRef of a sender
:type message: any
:raise: :exc:`pykka.ActorDeadError` if actor is not available
:return: nothing
"""
if hasattr(sender, "actor_ref"):
sender = sender.actor_ref
if not self.is_alive():
raise ActorDeadError(f"{self} not found")
self.actor_inbox.put(Envelope(message, sender=sender)) And then use it from an actor like: def on_receive(self, message):
if message == "Hello!":
self._sender().tell("Why, hello, good sir!", self) That's not pretty, but since we don't have implicit variables right now I don't see how to make it prettier. |
any updates? |
coming also from Akka, the solution from @akatashev looks nice and very useful. |
Is there an equivalent of a
sender
attribute on the actor?This is to allow me to send messages to the "sender" --- and is drastically different from the "ask" semantics.
Consider, for example, a child actor keeping track of "failures" and sending a message to parent saying "Failure Limit Reached".
In this case the semantics of the parent would be something like this:
This cannot be accomplished with an "ask" --- since once the child is spawned, the parent cares not for it and carries on with its duties.
P.S.: As a side note, documentation seems to favor the "ask" way of doing things (see "replying to messages" in pykka docs), which is not how the general actor system usually functions. The preferred way is to use "tell" and only resort to "ask" in select cases. Akka also prefers tell:
http://doc.akka.io/docs/akka/snapshot/scala/actors.html
The text was updated successfully, but these errors were encountered: