Message transfer between actors

36 views
Skip to first unread message

Srinivas Aditya

unread,
Jul 21, 2022, 7:37:22 AM7/21/22
to thespian.py
Hi,

I am trying to test a concept in which I need to send and receive messages between two actors which are concurrently running on actor system (in two different .py files). I tried using self.send to send msg from one actor to other but unable to figure out how to get msg back from other to first one. Please help.
P.S. One idea is to create third actor to send back the msg to first one from second actor, Is this correct way or only way to do it?

Thanks.

Kevin Quick

unread,
Jul 21, 2022, 3:41:42 PM7/21/22
to Srinivas Aditya, thespian.py
Hi Srinivas,

Actors are able to send messages between themselves in both directions without needing intermediaries.  Without knowing the details of what issues you are encountering, my best recommendation is that you take a look at the examples (https://github.com/kquick/Thespian/tree/master/examples) and start with the hellogoodbye.py example.   If you have more details on specific problems please post back here and I'm happy to help.

Regards,
  Kevin


--
You received this message because you are subscribed to the Google Groups "thespian.py" group.
To unsubscribe from this group and stop receiving emails from it, send an email to thespianpy+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/thespianpy/041ee4c6-e243-44d4-b47c-f442b1c379fdn%40googlegroups.com.


--
-KQ

Srinivas Aditya

unread,
Jul 25, 2022, 5:12:01 AM7/25/22
to thespian.py
Hi Kevin,

Apologies for posting an unclear query. Please find explanation below.
I'm trying to create actor Generator in generate.py file, which shall continuously generate random numbers.

from thespian.actors import *

class Generator(Actor):
     def receiveMessage(self, msg, sender):
         if msg == "start":            
             while True:
                  temp = uniform(20.0, 21.0)
                  msg = str(temp)
                 # NEED TO SEND msg AND RECEIVE MULTIPLIED RESULT
                  time.sleep(1)

if __name__ == '__main__':
    system = ActorSystem('multiprocTCPBase')
    sub = system.createActor(Generator)
    system.tell(sub,"start")
    ...
 
then I'm creating actor Subscriber in subscribe.py file, which shall continuously receive those random numbers, multiply with a factor and send back result.

from thespian.actors import *

class Subscriber(Actor):
     def receiveMessage(self, msg, sender):
         # DO SOME OPERATION ON msg SUCH AS MULTIPLY AND SEND BACK RESULT
         self.send(sender, msg)

if __name__ == '__main__':
    system = ActorSystem('multiprocTCPBase')
    sub = system.createActor(Subscriber)
    ...
 
Now my query is, how can Generator actor can send and receive the msgs in this situation? As the actor class is not defined in the same python file. Importing the subscribe.py file into generate.py would be same as creating Subscriber actor in same file (isn't it?)
What I understood from other conversations in the group is, creating actors in this way will be part of same actor system (?)

Please help me understand.
thanks.

Kevin Quick

unread,
Jul 25, 2022, 1:21:29 PM7/25/22
to Srinivas Aditya, thespian.py
Hi Srinivas,

I believe I understand better your questions, which are primarily about the Generator.  I understand you have just provided a made-up sample, so I apologize in advance for any comments I make below that are about portions you didn't intend to be a realistic representation.  Here's the reproduction of the Generator from your message:

class Generator(Actor):
     def receiveMessage(self, msg, sender):
         if msg == "start":            
             while True:
                  temp = uniform(20.0, 21.0)
                  msg = str(temp)
                 # NEED TO SEND msg AND RECEIVE MULTIPLIED RESULT
                  time.sleep(1)

There are several observations I can make about this (and will in more detail below) but the main observation is that Actors are intended to process and respond to messages, and if an Actor does not allow receiveMessage to be called with new messages then it won't have the ability to perform that core intention.

* The `while True:` loop never exits, so once the Generator receives the "start" message it can never receive any other messages.
* The `time.sleep(1)` is a busy wait that will block the entire Actor from running, including sending and receiving messages.  I recommend the use of timer messages (https://thespianpy.com/doc/using.html#hH-9cc1acd4-7f35-44ac-94fc-0326dc87a7a5) instead of `time.sleep`, which allows the handling of messages during the delay.
* When Generator sends messages to Subscriber, you'll need to decide what should trigger each message (after everything is started via the "start" message): a time interval? receipt of a previous message from the Subscriber?  Some other event?

Here's a version of Generator that addresses the above, sending Subscriber a new message each time Subscriber responds:

class Generator(Actor):
     def receiveMessage(self, msg, sender):
         if isinstance(msg, tuple) and msg[0] == "start":
              # Got ("start", AddrOfSubscriber)            
              temp = uniform(20.0, 21.0)
              self.send(msg[1], temp)
        if isinstance(msg, float):
              # This is the response from Subscriber (because only Subscriber is sending this Actor a Float... could use some specific
              # message type or structure if better distinction was needed.
              # ... do something with received multiplied result ...
             temp = uniform(20.0, 21.0)
             self.send(sender, temp)   # Send Subscriber the next value

In this configuration, the startup that runs Generator doesn't send start to Generator (because the Subscriber address isn't known yet):

if __name__ == '__main__':
    system = ActorSystem('multiprocTCPBase')
    sub = system.createActor(Generator, globalName='The Generator')

And when the startup that runs Subscriber starts, it can send Generator the start message.  In this case, it will use the globalName that the Generator registered with to target the Generator.

if __name__ == '__main__':
    system = ActorSystem('multiprocTCPBase')
    sub = system.createActor(Subscriber)
    gen = system.createActor(X, globalName='The Generator')
    system.tell(gen, ("start", sub))

Note that in the above, X could be anything: that createActor call will not actually start a new actor but will instead ignore the first argument and return the address of the already created Generator running under the name 'The Generator'.  Be aware however that if there was no actor running under that globalName then it would try to start one with whatever class X was, so you might want X to be a fake Generator that sent back an error or did nothing, indicating the primary Generator startup hadn't run.  You could also specify X as Generator, but since you indicated that's in a different file, that won't be available here.

Here's an alternate version of the Generator (which uses the same startup) that sends messages to Subscriber based on a 1-second timer:

import datetime

generator_period = datetime.timedelta(seconds=1)

class Generator(Actor):
     def receiveMessage(self, msg, sender):
         if isinstance(msg, tuple) and msg[0] == "start":
              # Got ("start", AddrOfSubscriber)            
              temp = uniform(20.0, 21.0)
              self.send(msg[1], temp)
              # request a wakeup message, with the wakeup .payload = msg[1] = Subscriber address
              self.wakeupAfter(generator_period, msg[1])
        if isinstance(msg, WakeupMessage):
             temp = uniform(20.0, 21.0)
             self.send(msg.payload, temp)   # Send Subscriber the next value
             self.wakeupAfter(generator_period, msg.payload)  # schedule next send to Subscriber
        if isinstance(msg, float):
              # ... do something with Subscriber response ...

Hopefully this gives you some useful suggestions to create the Actor configuration you need in your work.

Regards,
  Kevin




--
-KQ

Srinivas Aditya

unread,
Jul 26, 2022, 12:51:39 PM7/26/22
to thespian.py
Thanks a lot Kevin. this worked like a charm!
And I learnt new implementation techniques as well.

Thanks for your support.
Reply all
Reply to author
Forward
0 new messages