-
-
Notifications
You must be signed in to change notification settings - Fork 107
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
Nicer syntax for creating/comparing messages #39
Comments
Issue #45 alludes to this approach. I am not sure inheritance is the right way to go. |
Here is what I came up with, works quite nicely (same solution for issue #45): Here is how you can patch the ThreadingActor. Of course, you would inherit from this class instead for creating all your actors: from pykka import ThreadingActor, ActorRef
class Actor(ThreadingActor):
"""
Actor class from which classes should inherit to create an actor.
Adapter to the pykka actors that treats messages as instances
of some class. If pykka's system message is encountered,
this adapter simply passes the message on.
"""
PAYLOAD_MARKER = '__actor.message.payload__'
def __init__(self, *args, **kwargs):
super(Actor, self).__init__(*args, **kwargs)
# Override actor ref with our custom actor ref,
# that creates a dict each time it sends a message
self.actor_ref = ActorRefAdaptor(self)
def _handle_receive(self, message_or_dict):
if Actor.PAYLOAD_MARKER in message_or_dict:
# This is our message with an instance of the object in it - pass it
# straight to on receive function
self.on_receive(message_or_dict[Actor.PAYLOAD_MARKER])
else:
# hand the message over to pykka
super(Actor, self)._handle_receive(message_or_dict)
class ActorRefAdaptor(ActorRef):
def tell(self, message):
# If this is a dict message, it might be pykka's system message,
# and we leave it as is.
if isinstance(message, dict):
super(ActorRefAdaptor, self).tell(message)
else:
# Our message is an instance of some class, but we need
#to pass pykka a dict object - so we wrap it in one!
super(ActorRefAdaptor, self).tell({Actor.PAYLOAD_MARKER: message}) Now use it simply as: class MyActor(Actor):
def on_receive(self, message):
if isinstance(message, SomeCommand):
print("Got command with x=%s, and y=%s!!!" % (message.x, message.y))
class SomeCommand(object):
def __init__(self, x, y):
self.x = x
self.y = y
actor = MyActor.start()
actor.tell(SomeCommand(x=1, y=2)) Enjoy! |
With the merge of #79 that will be part of the upcoming Pykka 2.0, the example here now works without having to wrap the actor and ref in adapters: In [1]: import pykka
In [2]: class SomeCommand(object):
...: def __init__(self, x, y):
...: self.x = x
...: self.y = y
...:
In [3]: class MyActor(pykka.ThreadingActor):
...: def on_receive(self, message):
...: if isinstance(message, SomeCommand):
...: print('Got command with x={} and y={}'.format(message.x, message.y))
...:
In [4]: actor = MyActor.start()
In [5]: actor.tell(SomeCommand(x=1, y=2))
Got command with x=1 and y=2
In [6]: |
Is there any way we can create messages with some kind of class-inheriance, and have some tools for comparing them?
E.g.:
I tried doing this on my own, but doing "name" on a class does not seem to be thread safe! I got really weird errors of actors sending messages of the wrong type!
The text was updated successfully, but these errors were encountered: