Giter Site home page Giter Site logo

thespianpy / thespian Goto Github PK

View Code? Open in Web Editor NEW
311.0 37.0 64.0 19.05 MB

Python Actor concurrency library

License: MIT License

Shell 0.01% Python 99.13% Promela 0.87%
actor-model actors concurrency fault-tolerance distributed-systems distributed-actors scalability

thespian's Introduction

Thespian Actor Library

This library provides the framework of an Actor model for use by applications implementing Actors.

Thespian Site with Documentation: http://thespianpy.com/doc

Please report any issues here via the Github issue tracker.

Latest PyPI version

Supported Python versions

Stability

Travis CI build status

Contacts:

ChangeLog

See the Thespian Release Notes.

History

Thespian was developed at GoDaddy as part of the support for GoDaddy's dedicate and virtual server product line. At one point, Thespian was helping to manage 10,000 physical servers via a combination of on-server and remote actors.

The primary Thespian author (Kevin Quick) is no longer working at GoDaddy, but through GoDaddy's willingness to open-source the Thespian code and transfer the rights to this author, this repository is still being maintained and developed. With heartfelt thanks to the Vertigo team at GoDaddy, this Python Actor model has been developed and refined to provide a highly functional library for general use.

thespian's People

Contributors

asevans48 avatar aytchell avatar danielmitterdorfer avatar kquick avatar kwquick avatar pjz avatar sabaini avatar todd-cook avatar ttimo avatar vidbina avatar waqaraqeel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

thespian's Issues

Thespian Connecting To MongoDb

Here is what i am trying to do

  1. Actor System multiprocTCPBase
  2. Top level Root Creates two Actors
    2.1 Coordinating Node
    2.2 Pinger Node
  3. Coordinating Node queries mongodb

Also When i change to the default system base class , it starts to work.
In here i am getting the error

Top Level Root
class RootNode(Actor): def receiveMessage( self , msg , sender ): print("Initiate") if (msg == "start"): print("Message recieved from the actor System") pingerNode = self.createActor(Pinger) coordinatingNode = self.createActor(Cord) pingerStartMessgae = (sender , "StartPingingToDatabase") cordinatingStartMessage = "Initiate" self.send(pingerNode , pingerStartMessgae) self.send(coordinatingNode , cordinatingStartMessage)

Coordinating Node

   `class Cord(Actor):
       def __init__( self ):
              self.db = database()

  def receiveMessage( self , msg , sender ):
        if (msg == "Initiate"):
              self.getProfileOfNode()
        elif (msg == "Got SomeThing to Proces"):
              self.checkTheDataBasetoFindSomeWork(sender)

  def getProfileOfNode( self ):
        profileData = self.db.getProfileInfo()
        print(profileData)
        NoOfWorkers = profileData[ "noOfworkers" ]
        pingTimeOfWorker = profileData[ "pingTimeofWorkers" ]
        messageSentToEveryWorker = { "message": "Start" , "interval": pingTimeOfWorker }
        print("Send to Create Pool Of actors")
        self.createPoolOfActors(NoOfWorkers , messageSentToEveryWorker)`

Mongodb client

 `class Database:
        def __init__( self ):
                client = MongoClient(connect=False , host="localhost" ,
                             port=27017 ,
                             socketTimeoutMS=100000000 ,
                             connectTimeoutMS=40000 ,
                             serverSelectionTimeoutMS=20000 ,
                             appname="MyAppthespian")
           self.db = client["node"] # node is the database name

     def insertProfile( self ):
           pass

     def getProfileInfo( self ):
           try:
                print ("Getting thge profile Info")
              # nodeprofile is the collection name
              profileInfo = self.db.nodeprofile.find()[ 0 ]
              # print(profileInfo)
              # convertTostring=json.dumps(profileInfo)
              # #print(convertTostring)
              return profileInfo
        except ConnectionFailure:
              print("Server not available")

  def insertActorProfile( self , data ):
        self.db.actorprofile.insert_one(data)

  def findWork( self ):
        data = self.db.fileuploading.find_one({ "status": "uploaded" })
        return data

`
Thespian Logs

2017-11-02 12:47:45.343477 p22079 I Actor cordinating.Cord @ ActorAddr-(T|:44730) second exception on message Initiate: Traceback (most recent call last): File "/usr/local/lib/python2.7/dist-packages/thespian/system/actorManager.py", line 168, in _handleOneMessage actor_result = self.actorInst.receiveMessage(copy.deepcopy(msg), envelope.sender) File "/home/vinoo/work/practice/python/thespian/cordinating.py", line 9, in receiveMessage File "/home/vinoo/work/practice/python/thespian/cordinating.py", line 14, in getProfileOfNode self.checkTheDataBasetoFindSomeWork(sender) File "/home/vinoo/work/practice/python/thespian/database.py", line 12, in getProfileInfo appname="MyAppthespian") IOError: [Errno 32] Broken pipe

No error in the mongodb side

ActorSystem().ask doesn't receive custom message class response

When setting up an ActorSystem to perform an ask followed by a shutdown, the response to the ask is never received if the message sent is a custom message class.

I am using Thespian 2.5.7 as reported and installed by pip, on Python 3.5.1 as shipped in the Anaconda Python Distribution on Ubuntu 15.10 (Wily).

Please refer to the following testcase:

from thespian.actors import ActorSystem, ActorSystemMessage, \
    ActorTypeDispatcher


# Tried this too, just to make sure it wasn't the inheritance
#class TestMessage(object):
#    pass


class TestMessage(ActorSystemMessage):
    pass


class TestActor(ActorTypeDispatcher):
    def receiveMsg_TestMessage(self, msg, sender):
        # Does not result in ActorSystem('multiprocQueueBase') shut down
        # Does not result in ActorSystem('multiprocTCPBase') shut down
        # Does not result in ActorSystem('multiprocUDPBase') shut down
        self.send(sender, msg)

        # Neither does this
        #self.send(sender, TestMessage())

        # This *does* cause the system to shut down.
        # All ActorSystems work as expected, and print <class 'str'>
        #self.send(sender, 'done')


if __name__ == '__main__':
    #ActorSystem('simpleSystemBase')
    #ActorSystem('multiprocQueueBase')
    ActorSystem('multiprocTCPBase')
    #ActorSystem('multiprocUDPBase')

    addr = ActorSystem().createActor(TestActor)

    # multiprocQueueBase never receives response
    # multiprocTCPBase never receives response
    # multiprocUDPBase never receives response
    response = ActorSystem().ask(addr, TestMessage())

    # simpleSystemBase prints:
    # <class 'NoneType'>
    print(type(response))

    ActorSystem().shutdown()

ActorSystem always succeeds

In writing some more general Actors and interfaces to interact with them, it would be nice to have a way to say "get me the Actorsystem if one's running, but don't start one up" so I could throw nicer errors in that case, but currently there's no way to do that, apart from making my own actorsystem singleton, which seems to kind of miss the point. Could some way to do this be added?

Round Robin Troupe Messages

I have an actor set up in a troupe configuration and each member holds a network connection to a server. I'm running into an issue where during light loads the same member is used for all messages (every 4s) and this causes the other troupe member's network connection to timeout.

I wonder if it would be possible to do something like round robin the messages to members of the troupe so they don't become stale. Thoughts?

Actor wakeup

Hi again,

I'm trying to use the wakeupAfter function with no real success. It works but I might just not understand how it supposed to work...
Example:
class MyActor(Actor):

def receiveMessage(self, message, sender):
    self.wakeupAfter(timedelta(seconds=0.5))

hello = ActorSystem().createActor(MyActor)
ActorSystem().ask(hello, message, 1)

Shouldn't this code just run in a loop forever? I manage to receive the WakupMessage but only if I specify a high timeout for the 'ask', like this:
ActorSystem().ask(hello, message, 10)

What is the right approach for starting an actor and just let it run in a loop without waiting forever for responses? what is the right approach for just starting an actor and let it run forever?

Thanks for the help.
DD.

Clarify expectations when passing mutable data in messages for each ActorSystem

Two major selling points for me on Thespian have been (1) supporting distributed concurrency transparently and (2) keeping actors truly atomic/private (apologies as I'm probably not using the correct technical terminology).

When considering users who are reading docs and comparing Thespian to other actor system implementations, I think it is helpful to differentiate on these two points in the docs explicitly. The first is already pretty clear, I think. For the second, compare to this statement in the Pykka docs:

For performance reasons, Pykka does not clone the dict you send before delivering it to the receiver. You are yourself responsible for either using immutable data structures or to copy.deepcopy() the data you’re sending off to other actors.

With some reasoning, one can figure out when Thespian would probably behave like this (simpleSystemBase) and when it wouldn't (the others), but I think a note at a higher level of abstraction would be good. That is, this statement:

All Actors run synchronously in the context of the current process thread.

Implies that mutable data structures are probably being passed around instead of copied or pickled, but you could certainly still be doing the copying/pickling in this implementation.

A silly test:

from thespian.actors import ActorSystem, ActorSystemMessage, \
    ActorTypeDispatcher


class SendDictMsg(object):
    def __init__(self, d):
        self.d = d


class ModDictMsg(object):
    pass


class TestActor(ActorTypeDispatcher):
    def receiveMsg_SendDictMsg(self, msg, sender):
        self.d = msg.d
        print('received: ', end='')
        print(repr(self.d))

    def receiveMsg_ModDictMsg(self, msg, sender):
        self.d['modkey'] = 'modvalue'
        print('modified: ', end='')
        print(repr(self.d))
        self.send(sender, 'done')

def run_system(system):
    ActorSystem(system)

    addr = ActorSystem().createActor(TestActor)

    test_d = {'one':1}

    print('original: ', end='')
    print(repr(test_d))

    ActorSystem().tell(addr, SendDictMsg(test_d))
    ActorSystem().ask(addr, ModDictMsg())

    print('after mod: ', end='')
    print(repr(test_d))

    ActorSystem().shutdown()

if __name__ == '__main__':
    for system in ('simpleSystemBase', 'multiprocQueueBase', 'multiprocTCPBase', 'multiprocUDPBase'):
        print(system)
        run_system(system)
        print()

Output:

simpleSystemBase
original: {'one': 1}
received: {'one': 1}
modified: {'one': 1, 'modkey': 'modvalue'}
after mod: {'one': 1, 'modkey': 'modvalue'}

multiprocQueueBase
INFO:Thespian.Admin:ActorSystem Administrator startup @ ActorAddr-Q.ThespianQ
original: {'one': 1}
received: {'one': 1}
modified: {'one': 1, 'modkey': 'modvalue'}
after mod: {'one': 1}

multiprocTCPBase
INFO:Thespian.Admin:ActorSystem Administrator startup @ ActorAddr-(TCP|192.168.1.155:1900)
original: {'one': 1}
received: {'one': 1}
modified: {'one': 1, 'modkey': 'modvalue'}
after mod: {'one': 1}

multiprocUDPBase
INFO:Thespian.Admin:ActorSystem Administrator startup @ ActorAddr-(UDP|192.168.1.155:1029)
original: {'one': 1}
received: {'one': 1}
modified: {'one': 1, 'modkey': 'modvalue'}
after mod: {'one': 1}

This does raise the question as to whether this is a "bug" in simpleSystemBase, since, if it is used mostly for testing, wouldn't it be desirable to keep its behavior as close to the other systems as possible?

duplicated log messages

We updated Thespian from 3.4.0 to 3.6.0 and we notice that all the logs emitted by an Actor are duplicated using the Python default formatting (and not the logs emitted by the main thread).

So the output looks like this for instance:

2017-01-12 11:42:35,787 - sandman.actors.actor:41[29] - INFO - Creating actor Client
INFO:sandman.actors.actor:Creating actor Client

We are using the multiprocTCPBase system base. I'm manually configuring my local loggers and setting up the thespian loggers using the configuration provided in the documentation.

Are we doing something wrong?

State

Hi,

First, thank you for this great project!
I'm working with other frameworks like Akka and I'm trying to understand how to manage Actor state in this project. Since one Actor is not supposed to update another's state, but is able to modify its own I have several questions:

  1. What is the best way to use your API to manage internal Actor state?
  2. Can this state long live failures and restarts?

Thanks in advance,
DD

Sending message to remote actor systems

I just recently started using Thespian, its features are really great. However, I have just ran into a limitation/bug, which I cannot solve. My situation is the following.

I have multiple actor systems on different machines, including a dedicated system that has a coordinator actor (this system is the convention leader). I would like to distribute the address of the coordinator actor for some specific actors in other, remote actor systems (to be able to send back results of jobs). I am currently using the convention update system message for this purpose (the coordinator actor is subscribed to this).

My problem here is that I cannot send a message to the actor system that is just connected to the convention. Using the message handler of the coordinator I am sending a message to the remoteAdminAddress (received in the convention update message). However, this message is not being delivered to the remote, recently connected system (the remote waits for a message with ActorSystem.listen()).

Also note that the coordinator does not throw any exception, the sending finishes successfully. I have tried configuring admin routing as well, but it did not help.

"nodename nor servname provided, or not known" for ActorSystem("multiprocTCPBase")

Problem description

When creating an ActorSystem("multiprocTCPBase") I get: socket.gaierror: [Errno 8] nodename nor servname provided, or not known

Full trace:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.5/site-packages/thespian/actors.py", line 465, in __init__
    systemBase, capabilities, logDefs)
  File "/usr/local/lib/python3.5/site-packages/thespian/actors.py", line 491, in _startupActorSys
    module = importlib.import_module('thespian.system.%s'%systemBase)
  File "/usr/local/Cellar/python3/3.5.2/Frameworks/Python.framework/Versions/3.5/lib/python3.5/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 986, in _gcd_import
  File "<frozen importlib._bootstrap>", line 969, in _find_and_load
  File "<frozen importlib._bootstrap>", line 958, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 673, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 665, in exec_module
  File "<frozen importlib._bootstrap>", line 222, in _call_with_frames_removed
  File "/usr/local/lib/python3.5/site-packages/thespian/system/multiprocTCPBase.py", line 16, in <module>
    from thespian.system.transport.TCPTransport import TCPTransport
  File "/usr/local/lib/python3.5/site-packages/thespian/system/transport/TCPTransport.py", line 88, in <module>
    from thespian.system.transport.IPBase import TCPv4ActorAddress
  File "/usr/local/lib/python3.5/site-packages/thespian/system/transport/IPBase.py", line 45, in <module>
    thisSystem = ThisSystem()
  File "/usr/local/lib/python3.5/site-packages/thespian/system/transport/IPBase.py", line 18, in __init__
    for usage in [0, socket.AI_PASSIVE]
  File "/usr/local/lib/python3.5/site-packages/thespian/system/transport/IPBase.py", line 20, in <listcomp>
    for rslt in socket.getaddrinfo(useAddr, 0, af, socktype, proto, usage)
  File "/usr/local/Cellar/python3/3.5.2/Frameworks/Python.framework/Versions/3.5/lib/python3.5/socket.py", line 732, in getaddrinfo
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno 8] nodename nor servname provided, or not known

Steps to reproduce

  1. pip3 install thespian
  2. Run the following Python shell session:
dm@io:~ $ python3
Python 3.5.2 (default, Jun 29 2016, 13:43:58)
[GCC 4.2.1 Compatible Apple LLVM 7.3.0 (clang-703.0.31)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import thespian.actors
>>> thespian.actors.ActorSystem("multiprocTCPBase")

This produces the before-mentioned trace.

Environment info

  • thespian: 3.0.2
  • OS: Darwin io 15.6.0 Darwin Kernel Version 15.6.0: Thu Jun 23 18:25:34 PDT 2016; root:xnu-3248.60.10~1/RELEASE_X86_64 x86_64
  • Python: Python 3.5.2

Pickling error attempting to create 'multiprocxxx' Actor system

Hi there

Thanks for releasing what looks like a really promising project. I'm keen to get started with it, but am encountering an issue with starting a 'multiprocTCPBase' Actor system (or any 'multiproc' Actor system) in a Windows environment. It looks like in multiprocCommon.py in _startAdmin (line 102) a reference to the multiprocessing module itself is being passed to a new process as an argument? This seems to lead to a pickling error...
trace.txt

multiprocTCPBase Message Send Queuing?

Hi

First off thanks so much for creating a great library.

I have implemented an actor which is sending messages to another actor (multiprocTCPBase) every 10-15 secs.

I've noticed that the 1st message is always sent okay, immediately. But the subsequent messages appear to always queue (and never send).

In particular, in system.systemCommon.py, class systemCommonBase in method _send_intent(self, intent) - the 1st message send satisfies

self._finalTransmitPending.set_last_intent(
self._sCBStats,
intent.targetAddr,
sendAddr,
intent)

and so appears to send immediately.

Subsequent messages don't satify this (i.e. False is returned) and so appear to be queued.

I've tried to play with the settings in hysteresis.py without success.

I would also add that the message send is triggered by a Wakeup message, sent every 0.5 secs with the data consume from a deque populated by a thread running in the same process (thre thread populates the queue and sleeps for around 15 secs after successfully placing data on the queue).

Could you please provide some guidance on what I can do to ensure the messages do not queue up and are sent in a timely manner?

Apologies if I have overlooked the obvious.

Thanks in advance, Hong...

Troupe Member Initialization

I'm wanting to use an actor that persists records to a database in troupe configuration but can't come up with a way to initialize the actor with its configuration settings.

Right now I send it a Settings message type when it is first created and it configures itself based on the message. However, if I set up a troupe, that Settings message will only be send to one actor.

Ideas? I prefer not to have a global "configuration" that is imported my actors.

How do I use actor supervisor with Thespian?

Hi,

I wonder how do I create an actor supervisor strategy with Thespian library? I want to create some actors dynamically and if the operation fails I want to restart the actor, and of course, there will be a threshold to restart the actor.

Kind Regards,
Felipe

Actorsystem is 'killable'

Try running:

from thespian.actors import Actor, ActorExitRequest, ActorSystem

class Kill_The_Messenger(Actor):
    def receiveMessage(self, message, sender):
        self.send(sender, ActorExitRequest())

def main():
    asys = ActorSystem()
    ktm = asys.createActor(Kill_The_Messenger)
    asys.tell(ktm, "Test message")
    asys.tell(ktm, ActorExitRequest())

if __name__ == '__main__':
    main()

so you can see:

Traceback (most recent call last):
  File "buglet.py", line 15, in <module>
    main()
  File "buglet.py", line 12, in main
    asys.tell(ktm, ActorExitRequest())
  File "/tmp/bugl/local/lib/python2.7/site-packages/thespian/actors.py", line 497, in tell
    self._systemBase.tell(actorAddr, msg)
  File "/tmp/bugl/local/lib/python2.7/site-packages/thespian/system/simpleSystemBase.py", line 456, in tell
    self._pendingSends.append(PendingSend(self.actorRegistry['System:ExternalRequester'].address, msg, anActor))
AttributeError: 'NoneType' object has no attribute 'address'

...which I believe is caused by the receiveMessage of Kill_The_Messenger sending an ActorExitRequest as a response to the "Test Message" which causes the ActorSystem to break internal bookkeeping.

Periodic actor creation failure

The stress testing in the thespian/test/test_createActor.py reveals an occasional problem in creating Actors. The frequency of the issue appears to be very low in local testing (approx 1 failure in each 10 runs, where each run creates ~60+ actors), independent of the system base (manifests for multiprocQueueBase, multiprocUDPBase, and multiprocTCPBase), but occurs sporadically. Further investigation is required to identify and resolve this issue.

Advice: Actor State in Convention

First, thank you for creating Thespian. I've been working with it all week and it's great!

I have a working ActorSystem on a single host and am now working to move it to multiple systems in a convention. The trouble that I'm having is shared state. My main Actor (Calc) receives messages from an external source, processes them, updates its state, sends the updated state to a persistence Actor, and sends the updated state back to the external source.

My issues:

  1. I want all clients across the convention to use the same Calc Actor, updating and using it's updated state.
  2. I need the Calc Actor to be restarted on a new ActorSystem if the one it's on is shutdown.

I've been been checking out the docs and see Actors with state like this are less than ideal. I can't come up with an alternative. Any advice on solutions or alternatives would be greatly appreciated.

Also, do you prefer these kinds of question to be submitted to the mailing list instead?

Potential message delivery issue in 3.6.2

I am currently investigating what may be a message delivery issue regression in the 3.6.2 release. I have not confirmed this yet, nor isolated it to just 3.6.2, but there is preliminary indication of occasional non-delivery issues using this release.

I will post more here as information becomes available.

Testing Thespian and facing a couple of issues

Thanks for releasing this great and promising project. We are still testing and doing some tests with Thespian and we are facing a couple of issues. We would like to know if we are using a good pattern.

Our current architecture.

We are using multiple Actor Systems, one master and several workers. Each of the actor system is located on different hosts and we are using the multiprocTCPBase base system.

We have two kind of actors:

  • a TaskManager located on the master. This actor is responsible of maintaining a pool of connected TaskExecutors and scheduling some tasks.
  • a TaskExecutor located on the worker. It is responsible of executing tasks.

When starting the master actor system, a TaskManager actor is created. The TaskManager is then listening at convention updates. On the worker side, the actor system is connecting to the master address and no actor is created.
When the TaskManager is notified that a new actor system is joining the convention, it is starting a new TaskExecutor on the remote actor system (this is done by using unique capabilities).
To unregister a TaskExecutor, we are using the ChildActorExited message. It is working as expected when a remote actor system is performing a graceful shutdown.

Maintaining a list of active workers.

We are facing some issues to maintain a list of active TaskExecutors. When a worker is killed, no convention update is received by the master, and no ChildActorExited message is received.
How could we detect that a remote actor system has been killed and that a child actor no longer exist? Could we list all the child actors on a remote actor system?

False convention updates.

From time to time, we received some false convention updates. From time to time, the master receives convention update regarding a worker leaving and joining straight after the convention. Is it an expected behaviour?

Creating other processes.

As said before, the role of the TaskExecutor is to execute tasks. Tasks are executed asynchronously by creating new processes (to avoid blocking the current actor system). According to the documentation it could result in unexpected behaviour. We noticed that while running a background task in a separate process most of the messages are delayed.
How could we deal with it?

Thanks for reading me and thanks again for your time.

MultiprocTCPBase cannot determine socket address when computer is offline

As I plan to do a significant amount of development work while not connected to the internet, I was disappointed to find that all of the Thespian examples using multiprocTCPBase (and multiprocUDPBase are not able to run unless my system is connected to the internet.
The example output below is from when internet is disabled. Connecting to internet fixes the issue.

I am on Debian Ubuntu 16.04.4

Please let me know if there is a solution to this which will allow me to viably develop while offline. (or if I am just missing something)

>>> import thespian.actors
>>> thespian.actors.ActorSystem("multiprocTCPBase")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.5/dist-packages/thespian/actors.py", line 638, in __init__
    systemBase, capabilities, logDefs)
  File "/usr/local/lib/python3.5/dist-packages/thespian/actors.py", line 676, in _startupActorSys
    systemBase = sbc(self, logDefs=logDefs)
  File "/usr/local/lib/python3.5/dist-packages/thespian/system/multiprocTCPBase.py", line 27, in __init__
    super(ActorSystemBase, self).__init__(system, logDefs)
  File "/usr/local/lib/python3.5/dist-packages/thespian/system/multiprocCommon.py", line 84, in __init__
    self.mpcontext)
  File "/usr/local/lib/python3.5/dist-packages/thespian/system/transport/TCPTransport.py", line 271, in __init__
    templateAddr     = ActorAddress(TCPv4ActorAddress(None, 0, external = externalAddr))
  File "/usr/local/lib/python3.5/dist-packages/thespian/system/transport/IPBase.py", line 254, in __init__
    external)
  File "/usr/local/lib/python3.5/dist-packages/thespian/system/transport/IPBase.py", line 150, in __init__
    raise RuntimeError('Unable to determine valid external socket address.')
RuntimeError: Unable to determine valid external socket address.

simpleSystemBase logging

Hi,

I have a question regarding logging. I've used an example from docs and as far as I can see, logging works with multiprocTCPBase but it doesn't work with simpleSystemBase. Why is that ?

Logger Aborting with(#0) with Error

ERROR:root:Thespian Logger aborting (#0) with error Traceback (most recent call last): File "/home/soko/Env/soko_env/local/lib/python2.7/site-packages/thespian/system/logdirector.py", line 74, in startupASLogger logrecord = r.message AttributeError: 'Thespian__UpdateWork' object has no attribute 'message' INFO:Thespian.Admin:ActorSystem Administrator startup @ ActorAddr-Q.ThespianQ 'Thespian__UpdateWork' object has no attribute 'message'
I have a "multiprocQueueBase" actor system on my django app but the logger keep on aborting with the above error trace. Sending messages within the actor system is not working. Am I missing some configuration? How do I resolve the issue?

Use CI

I see tox is configured - why not hook this github repo up to travisCI or somesuch to run it automatically? It would give a bit more feedback about PRs.

Low performance sending low latency messages between actors

I using Thespian to develop an application to consume low latency data via sockets. I had created initially two actors: one consumer (socket client connection) and the handler. Testing, I detected some delays between the time used to send one message in the consumer (Actor1) and when this message has arrived in the handler (Actor2).

About message delivery in documentation.

To test that, I had used the following code.

from thespian.actors import ActorSystem, Actor
import time


class Actor1(Actor):
    def receiveMessage(self, handler, sender):
        # benchmark
        data = {'tic': time.perf_counter(), 'lim': 10000}
        print('Elapsed Time to process {} messages'.format(data['lim']))
        for i in range(data['lim']):
            self.send(handler, data)
        # perf
        toc = time.perf_counter() - data['tic']
        print('Actor 1: {} sec'.format(round(toc, 3)))
        # self.actorSystemShutdown()


class Actor2(Actor):
    def __init__(self):
        self.msg_count = 0

    def receiveMessage(self, data, sender):
        self.msg_count += 1
        if self.msg_count == data['lim']:
            toc = time.perf_counter() - data['tic']
            print('Actor 2: {} sec'.format(round(toc, 3)))

def main():
    asys = ActorSystem('multiprocTCPBase')
    consumer = asys.createActor(Actor1)
    handler = asys.createActor(Actor2)
    asys.tell(consumer, handler)

if __name__ == '__main__':
    main()

Results:

Elapsed Time to process 10 messages
Actor 1: 0.002 sec
Actor 2: 0.008 sec

Elapsed Time to process 100 messages
Actor 1: 0.019 sec
Actor 2: 0.099 sec

Elapsed Time to process 1000 messages
Actor 1: 0.131 sec
Actor 2: 0.769 sec

Elapsed Time to process 10000 messages
Actor 1: 1.219 sec
Actor 2: 7.608 sec

Elapsed Time to process 100000 messages
Actor 1: 22.012 sec
Actor 2: 91.419 sec

Looking these results, There is something wrong or missing that I have in my code?, or there is another faster way to send the messages between actors? Also, there is any other benchmark that help us to analyze the performance commented in the documentation.

Actor Not Shutting Down

I have an actor I'm using to do processing on a time interval using:

class Timer(Actor):
    def receiveMessage(self, msg, sender):
        if isinstance(msg, WakeupMessage):

            if not getattr(self, 'time_stepper', None):
                self.time_stepper = seconds_time_stepper(init_now())

            if not getattr(self, 'scheduler', None):
                self.scheduler = self.createActor(Scheduler)

            t = next(self.time_stepper)
            logging.info('Woke up: {0}'.format(t))
            self.send(self.scheduler, t)

            self.wakeupAfter(timedelta(seconds=.1))

However, when I shutdown the ActorSystem, this actor does not get killed. I'm wonder if I'm generating too many messages and the ActorSystem().shutdown() is just timing out waiting for them to complete and gives up trying to kill that actor?

Dynamically creating actors

Hi

I need help in Dynamically creating the actors according to the user requirement (no of actors they need for the job to complete )
as i am placing them in the form id's and names

Actor Initialization

Looking for some guidance on initializing an Actor with its internal state. For example, if I have an Actor that saves messages it receives to a database, what's the best way to pass it the db client it needs? I've gotten it working instantiating the db client in my Actor's __init__ but I prefer to pass it in as it will need to work with different db clients.

Decentralized convention support

Current Thespian system bases (circa version 3.2) are implemented with a single convention leader and form a star topology. This makes the convention leader a single point of failure in the overall architecture. There should be a system base that implements a leadership election (perhaps using something like Raft or Paxos directly) so that the overall environment is tolerant of the failure of any individual system and handle network partitioning events.

Unable to start UDP/TCP

I am unable to use the TCP or UDP system.

My call is

asys = ActorSystem("multiprocTCPBase", capabilities={"Admin Address": 5001})

The error is:

 .... lib/python2.7/site-packages/thespian/system/systemBase.py", line 76, in __init__
 'not a valid or useable ActorSystem Admin')
thespian.actors.InvalidActorAddress: ActorAddr-(TCP|192.168.100.9:1900) is not a valid or useable ActorSystem Admin

I have tried many different ports and none worked out. I am using a Mac OSX Yosemite.

Thanks

Actor total creation error

I am trying to create actors dynamically in for loop like this

  `from thespian.actors import *
   from workers import *
   from database import Database as database
   db=database()
   class Cord(Actor):
        def receiveMessage(self, msg, sender):
              if(msg == "Initiate"):
                 self.getProfileOfNode()
        elif(msg == "Got SomeThing to Proces"):
              self.checkTheDataBasetoFindSomeWork(sender)

  def getProfileOfNode(self):
        profileData = db.getProfileInfo()
        print(profileData)
        NoOfWorkers = profileData["noOfworkers"]
        pingTimeOfWorker=profileData["pingTimeofWorkers"]
        messageSentToEveryWorker = {"message":"Start","interval":pingTimeOfWorker}
        print("Send to Create Pool Of actors")
        self.createPoolOfActors(NoOfWorkers,messageSentToEveryWorker)

  def createPoolOfActors(self,noofworkers,messageSentToEveryWorker):
        print("Inside the Creation of pool of Actors")
        for i in range(0,1):
              print(i) #getting the result till here
              nameofWorker = "Worker"+`i`
              name = eval(nameofWorker)
              nameofWorker = self.createActor(self,name) # sending error here
              self.send(nameofWorker,messageSentToEveryWorker)`

Can you please help me the issue.
The error which i am getting is this
2017-10-31 17:46:35,558 WARNING => Actor total creation error [simpleSystemBase.py:482] Traceback (most recent call last): File "/usr/local/lib/python2.7/dist-packages/thespian/system/simpleSystemBase.py", line 473, in _newRefAndActor .create(actorClass) File "/usr/local/lib/python2.7/dist-packages/thespian/system/utilis.py", line 319, in create return klass(**{ k: self.kwargs[k] for k in initsig if k in self.kwargs }) TypeError: 'Cord' object is not callable

Child actor not exiting correctly

Hello,

For the last few days I have been able to run a game I created and implemented with the Thespian framework. In the game, I have one GameActor that initialises 4 PlayerActor children. Since players are connected to the game over the Internet, the PlayerActor regularly checks if a player has disconnected and terminates if so.
Lately, most of the games are able to run smoothly until the end and the GameActor and its children are gracefully finished. But from time to time, the PlayerActor or GameActor are forcefully terminated (I do not know the cause of their termination, since nothing appears in the logs).
My problem here is that the forcefully terminated PlayerActor actors remain as zombie processes and prevent the parent GameActor actor to terminate as well, thus eating a lot of resources for nothing and leaving the whole system in an unclean state.
Is this related to Thespians way of finishing its processes or rather to the underlying linux distribution running the whole architecture?

For information here are my settings:

  • Thespian v3.7.0
  • Ubuntu 14.04.5
  • Python 3.4

If you need any more information, I would gladly provide more details.

Sincerely.

Constant fail to create actor with global name on second attempt

Hey all,

I just recently started using Thespian and I can only thank you for this great package.

I have an issue with named actors. I have a distributed system where a convention leader gets notified when new actor systems connect. The convention leader backbone actor then starts a site backbone which in turn starts actors that manage devices on site. For various reasons, I thought that the device actors would best be named actors because each device manager can only exist once (although I read that I should probably manage that by hand using the site backbones).

I want to be able to access the device managers from other convention participants (i.e., mainly from the convention leader). Assuming A is the leader, and B is a participant. B starts a device management actor named 'b'. Now A also starts an actor named 'b' to talk to the device. However, A always fails to create that actor!

I created three python scripts that illustrate the issue:

  1. A file thespian_sandbox_testing/global_name_actor with and actor MyActor receiving a simple message:

     from thespian.actors import ActorTypeDispatcher, requireCapability
     
     class Message(object):
     
         def __init__(self, msg):
             self.msg = msg
     
     @requireCapability('Bob')
     class MyActor(ActorTypeDispatcher):
         def __init__(self):
             print('Bob actor created')
     
         def receiveMsg_Message(self, message, sender):
             print('Bob actor received message ' + message.msg +
                   ' from ' + str(sender))
    
  2. A simple starter for the actor system at Alice's side (convention leader):

     from easygui import msgbox
     from thespian.actors import ActorSystem
     
     from thespian_sandbox_testing.global_name_actor import Message, MyActor
     
     
     if __name__ == '__main__':
     
         asys = ActorSystem(systemBase='multiprocTCPBase',
                            capabilities={'Alice': True,
                                          'Admin Port': 1900})
     
         msgbox(msg='Convention leader (Alice) is running.\n\nPress button to proceed.',
                    title='Alice',
                    ok_button='proceed')
     
         bob_actor = asys.createActor(MyActor, globalName='Bob actor')
     
         asys.tell(bob_actor, Message('ALICE'))
     
         msgbox(msg='Convention leader (Alice) is running.\n\nPress button to shut down.',
                title='Alice',
                ok_button='shut down')
     
         print('Bob actor address: ' + str(bob_actor))
     
         asys.shutdown()
    
  3. A simple starter for the actor system at Bob's side (convention participant):

     from easygui import msgbox
     from thespian.actors import ActorSystem
     
     from thespian_sandbox_testing.global_name_actor import Message, MyActor
     
    
     if __name__ == '__main__':
     
         asys = ActorSystem(systemBase='multiprocTCPBase',
                            capabilities={'Bob': True,
                                          'Admin Port': 1902,
                                          'Convention Address.IPv4': ('127.0.0.1', 1900)})
     
         bob_actor = asys.createActor(MyActor, globalName='Bob actor')
     
         asys.tell(bob_actor, Message('BOB'))
     
         msgbox(msg='Convention participant (Bob) is running.\n\nPress button to shut down.',
                title='Bob',
                ok_button='shut down')
     
         print('Bob actor address: ' + str(bob_actor))
     
         asys.shutdown()
    

I start the actor system at Alice's side, wait for the "ready to proceed" box, then start the actor system at Bob's side, and when it runs, I click "proceed" on Alice's side. Now both systems remain until the "shutdown" boxes are clicked.

Alice tries to create a Bob-specific actor, and should instead receive the address of the existing actor at Bob's side. Instead I get this error message (after the timeout of 50 seconds):

thespian.actors.ActorSystemRequestTimeout: No response received to PendingActor request to Admin at ActorAddr-(T|:1900) from ActorAddr-(T|:46523)

What am I doing wrong?

Logging example?

Would it be asking too much to document how logging in an Actor should be done? and where it goes? Adding logging to the 'In Depth' example, perhaps?

use epoll on linux

select.select() is significantly slower on linux than select.epoll(), so, especially in the case of network services, there's a huge performance gain in using epoll.

I see a few ways forward:

  1. declare it WontFix.
  2. abstract the filehandle-watching so it can be switched based on what OS is running
  3. find/use something like libevent() which does the abstraction for you
  4. make completely different SystemBases - one for select(), one for epoll()

Include relevant package docs in Python distribution

Currently things like the license, contributors doc, and README aren't included in the source distribution on PyPI. People installing from this location have to pull in the license manually, and OS packagers would need to do the same for the rest of the docs.

Feature: multicast

It would be nice if .tell()/.send()/.ask() accepted a list for the first arg (actorAddr), meaning to send copies of that message to all of the listed destinations. I believe there's a gain in having thespian do this instead of the user/actor doing it, because thespian can re-use the message serialization.

The motivation for this was pondering the implementation of some pub/sub-ish functionality in thespian.

Fairness in multithreading

Dear all,

I have the following setup: Actor A creates a child actor B and sends an init message. Upon receiving init, B sets some timeouts to itself and performs a series of periodic tasks until it exits.

Unfortunately, instead of delivering the init message to B, the scheduler gives all execution time to actor A. After sending off the init message to B, A sends a message to itself, receives it (so we are in another message handler now), displays a dialog via easygui, and hogs all execution time until the next action at the dialog is initiated (prompting messages to other actors and/or itself). Only then the init message gets delivered to B (often too late to run the periodic tasks).

How can I ensure (or at least increase the probability) that the delivery of init to B interleaves with the execution of A in a fair way? Is there a wait command that would prompt the scheduler to continue with other threads?

Thanks for any kind of help,
greetings to kwquick, highly appreciated your help in earlier issues,
Georg

Add cause to PoisonMessage

Currently, when an uncaught exception occurs in an actor, Thespian sends a PoisonMessage to the sender. However, PoisonMessage only contains the original message. It would be nice, if we could also get the original exception e.g. as a cause property on PoisonMessage.

Runtime and ValueError in TCPTransport.py

Dear Sir,

First of all thank you very much for making thespian available to the public, it is a very nice and easy to use framework.

At the moment I am trying to implement a simple online game using both thespian (as the 'back-end') and Django (as the 'front-end'). In the game only 4 players can interact at a time. A django view has been set up to handle the interaction between the remote player and the back-end. Since django views are stateless, I have implemented a Lookup actor and initialised it as a named actor when launching thespian's ActorSystem. The lookup actor works as one might expect, it receives a special code attributed to each game, look for the corresponding ActorAddress and sends the address back to the view, so that the view can communicate with the game.
Game actors are created on demand and simply treat players' requests.
So far I have been able to create complete games and have different remote players connect to the game. However, once the game begins to play, the view encounters a Runtime Error, closely followed by a Value Error in the TCPTransport.py file.
I have attached the details of the error to this message, in hope that you could help me understand what is going on. Does the exception happen because of an implementation error or is it internal to Thespian?

Thank you very much in advance for your help.
Sincerely.

dj_err.txt

Hashable ActorAddress

Dear Sir,

This is much an issue, but rather a question.
In the implementation of the ActorAddress, I saw that the hash function has been overridden and simply returns a hash of None for all ActorAddress instances. Making is effectively impossible to use an ActorAddress as a key for a dictionary or even insert it into a set.
I was wondering if it was possible to provide another hash function based on the content of aaddr so that addresses could be used in dictionaries and sets? It is not really a deal breaker if it is not possible, but would make keeping track of child actors much simpler.

Sincerely.

Getting exceptions While Using "multiprocTCPBase" and logdefs in virtualenvironment

Process Actor___main__.Rossup__ActorAddr-LocalAddr.0:
Traceback (most recent call last):
File "C:\Program Files\Python36\lib\multiprocessing\process.py", line 258, in _bootstrap
self.run()
File "C:\Program Files\Python36\lib\multiprocessing\process.py", line 93, in run
self._target(*self._args, **self._kwargs)
File "C:\Users\1187598\PycharmProjects\pythonProject1\venv\lib\site-packages\thespian\system\multiprocCommon.py", line 561, in startChild
for key in logDefs ])))
File "C:\Users\1187598\PycharmProjects\pythonProject1\venv\lib\site-packages\thespian\system\multiprocCommon.py", line 549, in
minLevelIn = lambda l: min(list(l)) if list(l) else 0
ValueError: min() arg is an empty sequence

cPickle option?

Getting along very well with Thespian, thanks again for a great project.

One possible enhancement that would make a significant performance difference to our use case is the ability to opt for cPickle for the UDP and TCP transports. It seems this would be entirely compatible with the way the transports are serializing messages, and shouldn't break anything?

Actor's parent address

I did some research (docs + google + lib reverse engineering) but I can’t find an answer for my question: is there any way for the child actor to get its parent address ? At the moment I must introduce a “Setup” or “Initialize” message in my code and utilize “sender”. But I guess there is some other way.

If there is no such feature, then my question is: why ? Previously I’ve been using Akka for Scala, and there is such possibility, so I assume it makes some sense from the actors model POV.

I will appreciate any answer .

Actor Troupe, async asks and exception handling.

First of all, thanks for sharing the awesome package.
I have been using it to prototype a data pipeline control layer.
I have some experience with Akka which is biasing my expectations but here are some requests/questions.
Note that I am completely new to Python and some questions probably will sound silly.

Three things threw me off a little although I am getting used to them.

One is the blocking nature of ask.
What would be the best way to ask asynchronously?
Do you have some recommended pattern? Is there a plan to support this out of the box?

Second is Actor Troupe.
This would be really useful feature but the documentation on this is seriously lacking.
Could you provide some examples on how to set this up?

Third is Exception handling.
If I wanted to ensure that all exceptions thrown by the child actor can be caught in the parent actor, would I have to simply catch all and send it to the parent? Or should I just not do that?

Thank you.

Waiting for actor to finish

I have a simple two actor setup:

  • CalulcationActor generates a large set of messages and sends them to its child actor, SaveActor.
  • SaveActor that saves the messages to the database

Once the CalculationActor is finished, I would like the system to shutdown.

However, the CalculationActor finishes well before the SaveActor has received and processed all of its messages. I've tried sending an ActorExitRequest once the CalculationActor is done, which also sends an ActorExitRequest to the SaveActor, but it appears that the exit message is received before the messages to save and exits before all messages have been saved.

Is the due my SaveActor being a ActorTypeDispatcher? Perhaps ActorExitRequest is not queued behind the other messages?

Is there a pattern for shutting down the system after all actors have finished processing?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.