Skip to content
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

An example where multiprocUDPBase works but multiprocTCPBase doesn't #45

Open
yoavkantor opened this issue Apr 14, 2019 · 2 comments
Open
Labels
documentation Enhance Documentation

Comments

@yoavkantor
Copy link

yoavkantor commented Apr 14, 2019

============code=============
from thespian.actors import *

class BusyActor(Actor):
def receiveMessage(self, message, sender):
i = 0
while True:
i += 1
if i == 1000000:
i = 0

a1 = ActorSystem("multiprocTCPBase").createActor(BusyActor)
a2 = ActorSystem("multiprocTCPBase").createActor(BusyActor)
ActorSystem().ask(a1, 'hi', 1)
ActorSystem().ask(a2, 'hi', 1)

time.sleep(600)
============code=============

This fails with:
thespian.actors.InvalidActorSpecification: Invalid Actor Specification: <class 'main.BusyActor'> (module 'main' has no attribute 'BusyActor')

However using "multiprocUDPBase" ActorSystems works.
Any idea why?
Thanks!

@kquick
Copy link
Owner

kquick commented Apr 14, 2019

When you start one of the 'multiproc...Base' actor systems, it creates the actors as separate processes, including a 'MultiProcAdmin' actor that manages the system for you. The current process is intended to be a client of the actor system, not the owner of the actor system; the actor system is intended to persist beyond the existence of the current process, until it is explicitly shutdown. The MultiProcAdmin acts as the owner of the actor system in this configuration.

One subtle side effect of that is that when you create actors, the local process simply sends a message to the MultiProcAdmin, and it is the latter that actually creates the actors. However, the MultiProcAdmin can only create actors from source that it knowns about, which means either the version of the source that it was started with, or a loaded source (https://thespianpy.com/doc/using.html#hH-955ec990-a267-4d08-8f4d-5f980c777173).

I suspect that you initially created a multiprocTCPBase system with code that did not define BusyActor, which is why you got the failure message above, but that when you tried the multiprocUDPBase you had already defined the BusyActor by that point, which is why it worked.

My advice for simple exploratory programs like the above, where you do not want to have the actor system persist beyond the run of the program is to use the following pattern:

asys = ActorSystem("multiprocTCPBase")
try:
    ... do stuff with asys ...
finally:
    asys.shutdown()

This will stop the actor system at the end of the program, so that if you make changes and re-run it then the new actor system will see the new code.

I would also recommend the multisystem example tutorial (https://github.com/kquick/Thespian/tree/master/examples/multi_system) which will discuss this in more detail. If you want to use loadable sources, the Thespian Director (https://thespianpy.com/doc/director.html) can be useful (although not required).

@yoavkantor
Copy link
Author

Thanks a lot for the thorough explanation.
Hope it will help others as well :)

@kquick kquick added the documentation Enhance Documentation label Apr 22, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Enhance Documentation
Projects
None yet
Development

No branches or pull requests

2 participants