### Thespian Multi-System Example Setup Source: https://github.com/thespianpy/thespian/blob/master/examples/multi_system/act5/README.org Demonstrates setting up multiple Thespian Actor Systems with overlapping capabilities to provide fault tolerance and failover. ```bash python start.py 1900 python start.py 10000 "morse,Caesar cipher" python start.py 10101 "64bit encoder,morse,Caesar cipher" ``` -------------------------------- ### Thespian Hello World Actor Example Source: https://github.com/thespianpy/thespian/blob/master/doc/index.org A basic 'Hello World' example demonstrating the creation of an actor, sending it a message, receiving a response, and then exiting the actor. It showcases the fundamental interaction patterns within Thespian. ```python from thespian.actors import * class Hello(Actor): def receiveMessage(self, message, sender): self.send(sender, 'Hello, World!') if __name__ == "__main__": hello = ActorSystem().createActor(Hello) print(ActorSystem().ask(hello, 'hi', 1)) ActorSystem().tell(hello, ActorExitRequest()) ``` -------------------------------- ### Thespian Actor Initialization Example Source: https://github.com/thespianpy/thespian/blob/master/doc/using.org Example of initializing an actor with specific messages and a completion signal. It also demonstrates setting a transient timeout for the actor. ```python from thespian.actors import ActorTypeDispatcher from thespian.messages import initializing_messages from datetime import timedelta class Msg1: pass class ActorAddress: pass @initializing_messages([('init_m1', Msg1, True), ('init_tgt', ActorAddress), ('frog', str)], initdone='init_completed') @transient(timedelta(seconds=2, milliseconds=250)) class FooActor(ActorTypeDispatcher): pass ``` -------------------------------- ### Install Thespian Python Package Source: https://github.com/thespianpy/thespian/blob/master/doc/index.org Installs the Thespian library on the local system using pip. This is the first step to using the Thespian Actor System. ```bash $ pip install thespian ``` -------------------------------- ### Start Thespian Actor System Source: https://github.com/thespianpy/thespian/blob/master/doc/index.org Starts a default Thespian Actor System on the current host. This initializes the actor system, allowing actors to be created and managed. ```python from thespian.actors import * ActorSystem("multiprocTCPBase") ``` -------------------------------- ### Start Thespian Actor System Source: https://github.com/thespianpy/thespian/blob/master/examples/multi_system/act5/README.org Starts a Thespian Actor System with a specified administrator port and a comma-separated list of capabilities. The first system started on port 1900 becomes the convention leader. ```bash export PYTHONPATH=../../..:$PYTHONPATH python start.py 1900 python start.py 10000 "morse,Caesar cipher" python start.py 10101 "64bit encoder" ``` -------------------------------- ### Python Logging Configuration Example Source: https://github.com/thespianpy/thespian/blob/master/doc/using.org An example of a Python dictionary used for configuring logging definitions in Thespian. This includes handlers and loggers with specific levels. ```python { 'handlers' : { 'h1': {'class': 'logging.StreamHandler', 'formatter': 'f1'}, 'h2': {'class': 'logging.StreamHandler', 'formatter': 'f2'}}, 'formatters': {'f1': {'format': '%(asctime)s %(levelname)s %(name)s %(message)s'}}, 'root': {'handlers': ['h1'], 'level': logging.WARNING}, 'loggers' : { '': {'handlers': ['h1', 'h2'], 'level': logging.DEBUG}} } ``` -------------------------------- ### Start Thespian Actor System Source: https://github.com/thespianpy/thespian/blob/master/doc/using.html An ActorSystem is initiated by instantiating an ActorSystem() object. You can specify the type of ActorSystem base, such as 'multiprocTCPBase', and any optional capabilities. ```python from thespian.actors import ActorSystem asys = ActorSystem('multiprocTCPBase') ``` -------------------------------- ### Multi-System Communication and Conventions Source: https://context7.com/thespianpy/thespian/llms.txt This example illustrates how to set up Thespian actor systems to communicate across different hosts using conventions. It includes actors that require specific capabilities and monitors system registration changes. ```python from thespian.actors import Actor, ActorSystem, ActorSystemConventionUpdate, requireCapability # Actor that requires specific capabilities @requireCapability('has_gpu') class GPUWorker(Actor): def receiveMessage(self, message, sender): self.send(sender, f"GPU processing: {message}") # Actor that monitors convention membership class ConventionMonitor(Actor): def __init__(self): super().__init__() self.known_systems = [] def receiveMessage(self, message, sender): if message == 'start_monitoring': self.notifyOnSystemRegistrationChanges(True) self.send(sender, 'Monitoring convention changes') elif isinstance(message, ActorSystemConventionUpdate): if message.remoteAdded: self.known_systems.append({ 'address': str(message.remoteAdminAddress), 'capabilities': message.remoteCapabilities }) print(f"System joined: {message.remoteCapabilities}") else: print(f"System left: {message.remoteAdminAddress}") elif message == 'list_systems': self.send(sender, self.known_systems) # System 1: Convention Leader asys1 = ActorSystem('multiprocTCPBase', { 'Admin Port': 1900, 'Convention Address.IPv4': ('localhost', 1900), 'has_gpu': False }) monitor = asys1.createActor(ConventionMonitor) asys1.ask(monitor, 'start_monitoring', timeout=1) # System 2: Convention Member with GPU capability # (Would typically run on different host) # asys2 = ActorSystem('multiprocTCPBase', { # 'Admin Port': 1901, # 'Convention Address.IPv4': ('192.168.1.100', 1900), # Leader address # 'has_gpu': True # }) # Create actor on remote system with specific capabilities # gpu_worker = asys1.createActor(GPUWorker) # Created on system with has_gpu ``` -------------------------------- ### Configure Thespian ActorSystem Source: https://github.com/thespianpy/thespian/blob/master/doc/director.org Examples of defining ActorSystem configuration parameters by creating individual files within the THESPIAN_DIRECTOR_DIR directory, where each file contains a direct Python value. ```bash cat convleader.cfg 192.168.32.19 cat othercaps.cfg { 'Worker': True, 'Slot': 19, 'nproc': 2 } cat thesplog.cfg { 'version': 1, 'formatters': { 'normal': { 'format': '%(asctime)s,%(msecs)d %(actorAddress)s/PID:%(process)d %(name)s %(levelname)s %(message)s', 'datefmt': '%Y-%m-%d %H:%M:%S' } }, 'root': {'level': 20, 'handlers': ['foo_log_handler']}, 'loggers': { 'subsysA': {'level':30, 'propagate': 0, 'handlers': ['foo_log_handler']} }, 'handlers': { 'foo_log_handler': { 'filename': 'fooapp.log', 'class': 'logging.handlers.TimedRotatingFileHandler', 'formatter': 'normal', 'level': 20, 'backupCount':3, 'filters': ['isActorLog'], 'when': 'midnight' } }, 'filters': {'isActorLog': {'()': 'thespian.director.ActorAddressLogFilter'}} } ``` -------------------------------- ### Dynamic Actor Creation and Communication Flow Source: https://github.com/thespianpy/thespian/blob/master/doc/in_depth.org Illustrates how actors can create other actors and how messages are routed between them, using the hellogoodbye.py example. ```APIDOC ## Dynamic Actor Creation and Communication Flow (hellogoodbye.py) ### Description This example demonstrates how actors can dynamically create other actors and how messages are passed between them, including indirect responses back to the original sender. ### Actors Involved * **Hello Actor**: Creates a `World` actor and sends a message containing the original sender's address and a greeting. * **World Actor**: Receives a tuple, extracts the original sender and greeting, appends ' world!', and sends the result back to the original sender. * **Goodbye Actor**: A simple actor that responds with 'Goodbye' when messaged. ### Code Example (`hellogoodbye.py`) ```python from thespian.actors import * class Hello(Actor): def receiveMessage(self, message, sender): if message == 'are you there?': world = self.createActor(World) worldmsg = (sender, 'Hello,') self.send(world, worldmsg) class World(Actor): def receiveMessage(self, message, sender): if isinstance(message, tuple): orig_sender, pre_world = message self.send(orig_sender, pre_world + ' world!') class Goodbye(Actor): def receiveMessage(self, message, sender): self.send(sender, 'Goodbye') def run_example(systembase=None): # ActorSystem() is a singleton hello = ActorSystem().createActor(Hello) goodbye = ActorSystem().createActor(Goodbye) # Using ask() to get a response greeting = ActorSystem().ask(hello, 'are you there?', 1.5) print(greeting + '\n' + ActorSystem().ask(goodbye, None, 0.1)) # Shutdown the actor system ActorSystem().shutdown() if __name__ == "__main__": import sys run_example(sys.argv[1] if len(sys.argv) > 1 else None) ``` ### Execution Flow 1. `run_example` is called. 2. A `Hello` actor and a `Goodbye` actor are created. 3. `ActorSystem().ask(hello, 'are you there?', 1.5)` is called. 4. The `Hello` actor's `receiveMessage` is invoked. 5. `Hello` creates a `World` actor using `self.createActor(World)`. 6. `Hello` sends a tuple `(sender, 'Hello,')` to the `World` actor. 7. The `World` actor's `receiveMessage` is invoked with the tuple. 8. `World` sends `Hello, world!` back to the original sender (which is the `run_example` function's context). 9. The `ask()` call in `run_example` receives `'Hello, world!'`. 10. `ActorSystem().ask(goodbye, None, 0.1)` is called, and the `Goodbye` actor responds with `'Goodbye'`. 11. Both results are printed. 12. `ActorSystem().shutdown()` is called to clean up. ### Expected Output ``` Hello, world! Goodbye ``` ``` -------------------------------- ### Create and Interact with a Thespian Actor Source: https://github.com/thespianpy/thespian/blob/master/doc/in_depth.org This example demonstrates how to define a basic Actor class by inheriting from thespian.actors.Actor, implementing the receiveMessage method, and using the ActorSystem to create the actor and send a message with a timeout. ```python from thespian.actors import * class Hello(Actor): def receiveMessage(self, message, sender): self.send(sender, 'Hello, world!') def say_hello(): hello = ActorSystem().createActor(Hello) print(ActorSystem().ask(hello, 'are you there?', 1.5)) if __name__ == "__main__": say_hello() ``` -------------------------------- ### ActorSystem Initialization Source: https://github.com/thespianpy/thespian/blob/master/doc/using.html Demonstrates how to initialize an ActorSystem with various configuration options. ```APIDOC ## ActorSystem Initialization ### Description Initializes an ActorSystem instance with specified configurations for system base, capabilities, and logging. If `systemBase` is not provided, it defaults to a previously created ActorSystem's base or `simpleSystemBase`. ### Method `ActorSystem(systemBase=None, capabilities=None, logDefs=None, transientUnique=False)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **systemBase** (object) - Optional - Specifies the ActorSystem implementation base. - **capabilities** (dict) - Optional - A dictionary of capability keys and values. - **logDefs** (dict or False) - Optional - A logging configuration dictionary or False to disable logging configuration. - **transientUnique** (bool) - Optional - If True, creates a new, unregistered ActorSystem. ### Request Example ```python from thespian.actors import ActorSystem # Initialize with default settings asys_default = ActorSystem() # Initialize with specific system base and capabilities # Assuming cfg is a configuration object with system_base and foo_capability # cfg = read_config_file() # asys_custom = ActorSystem(systemBase=cfg.system_base, capabilities={'foo': cfg.foo_capability}) # Initialize to create a transient unique system asys_transient = ActorSystem(transientUnique=True) ``` ### Response #### Success Response (200) - **ActorSystem object** - An instance of the ActorSystem. #### Response Example ```python # The returned object is an ActorSystem instance # Example: ``` ``` -------------------------------- ### Create and Use ActorSystem in Python Source: https://github.com/thespianpy/thespian/blob/master/doc/using.org Demonstrates creating an ActorSystem, either by retrieving an existing one or creating a new one with specific configurations. It also shows how to create actors and send messages within the system. ```python def start_system(): cfg = read_config_file() ActorSystem(systemBase=cfg.system_base, capabilities = { 'foo': cfg.foo_capability, ...}, ...) def do_something(): mine = ActorSystem().createActor(MyActor) r = ActorSystem().ask(mine, 'ready?', timedelta(seconds=3)) ... if __name__ == "__main__": start_system() do_something() ``` ```python def start_system(): cfg = read_config_file() asys = ActorSystem(systemBase=cfg.system_base, capabilities = { 'foo': cfg.foo_capability, ...}, ...) return asys def do_something(asys): mine = asys.createActor(MyActor) r = asys.ask(mine, 'ready?', timedelta(seconds=3)) ... if __name__ == "__main__": asys = start_system() do_something(asys) ``` -------------------------------- ### Actor Capability Check with @requireCapability Decorator Source: https://github.com/thespianpy/thespian/blob/master/doc/in_depth.org Illustrates using the `@requireCapability` decorator to enforce specific capabilities for an Actor. Multiple decorators can be stacked, and they can be used alongside the `actorSystemCapabilityCheck` method. This example requires 'Has DB access' and 'LDAP installed' capabilities, and further checks if the 'LDAP zone' capability is 'Active'. ```python from thespian.actors import * from database import dbclass @requireCapability('Has DB access') @requireCapability('LDAP installed') class DBUpdateFromLDAP(Actor): @staticmethod def actorSystemCapabilityCheck(capabilities, requirements): return capabilities.get('LDAP zone', None) == 'Active' def receiveMessage(self, message, sender): ... ``` -------------------------------- ### Initializing an Actor System Source: https://github.com/thespianpy/thespian/blob/master/doc/using.org Shows how to instantiate an ActorSystem using a specific base, such as 'multiprocTCPBase', which determines the underlying communication and execution strategy. ```python asys = ActorSystem('multiprocTCPBase') ``` -------------------------------- ### Startup Actor System with Capabilities and Convention Source: https://github.com/thespianpy/thespian/blob/master/doc/in_depth.org Shows how to initialize an Actor System with specific capabilities and join a convention. Capabilities like 'Convention Address.IPv4' and dynamically set ones like 'Has DB access' are declared. This allows Actor Systems to communicate and share actors across different nodes. ```python from thespian.actors import * from database import dbclass capabilities = { 'Convention Address.IPv4': '10.5.1.1:1900' } try: dbconn = dbclass.connect(...) if dbconn and 1 == dbconn.runquery('select 1=1'): capabilities['Has DB access'] = True except DBError: pass ActorSystem('multiprocTCPBase', capabilities) ``` -------------------------------- ### POST /ActorSystem/create Source: https://github.com/thespianpy/thespian/blob/master/doc/using.html Initializes a new ActorSystem instance with a specified system base. ```APIDOC ## POST /ActorSystem/create ### Description Initializes the Thespian ActorSystem. The system base determines the underlying communication mechanism (e.g., multiprocTCPBase). ### Method POST ### Endpoint ActorSystem(systemBase) ### Parameters #### Request Body - **systemBase** (string) - Required - The type of system base to use (e.g., 'multiprocTCPBase') ### Request Example { "systemBase": "multiprocTCPBase" } ### Response #### Success Response (200) - **asys** (object) - The initialized ActorSystem instance #### Response Example { "status": "success", "instance": "ActorSystem" } ``` -------------------------------- ### Initialize and Use Thespian ActorSystem Source: https://github.com/thespianpy/thespian/blob/master/doc/using.html Demonstrates how to initialize an ActorSystem with custom configurations and how to interact with actors using the system instance. It covers both the singleton access pattern and explicit instance passing. ```python from thespian.actors import ActorSystem from datetime import timedelta def start_system(): cfg = read_config_file() ActorSystem(systemBase=cfg.system_base, capabilities = { 'foo': cfg.foo_capability }, ...) def do_something(): mine = ActorSystem().createActor(MyActor) r = ActorSystem().ask(mine, 'ready?', timedelta(seconds=3)) if __name__ == "__main__": start_system() do_something() ``` ```python def start_system(): cfg = read_config_file() asys = ActorSystem(systemBase=cfg.system_base, capabilities = { 'foo': cfg.foo_capability }, ...) return asys def do_something(asys): mine = asys.createActor(MyActor) r = asys.ask(mine, 'ready?', timedelta(seconds=3)) if __name__ == "__main__": asys = start_system() do_something(asys) ``` -------------------------------- ### Initialize Thespian ActorSystem Source: https://context7.com/thespianpy/thespian/llms.txt Demonstrates initializing the ActorSystem with different system bases for various deployment needs, including simple testing, distributed TCP/UDP, and local multiprocessing. It also shows how to configure custom logging. ```python from thespian.actors import ActorSystem # Simple system base for testing and development asys = ActorSystem('simpleSystemBase') # TCP-based distributed system for production asys = ActorSystem('multiprocTCPBase', { 'Admin Port': 1900, 'Convention Address.IPv4': ('192.168.1.100', 1900) }) # UDP-based system for lightweight networking asys = ActorSystem('multiprocUDPBase', { 'Admin Port': 1901 }) # Queue-based multiprocessing for local parallelism asys = ActorSystem('multiprocQueueBase') # Custom logging configuration import logging log_config = { 'version': 1, 'handlers': { 'file': { 'class': 'logging.FileHandler', 'filename': 'thespian.log', 'level': logging.DEBUG } }, 'root': {'level': logging.DEBUG, 'handlers': ['file']} } asys = ActorSystem('multiprocTCPBase', logDefs=log_config) # Cleanup when done asys.shutdown() ``` -------------------------------- ### Get Role Address using DirectorControl (Python) Source: https://github.com/thespianpy/thespian/blob/master/doc/director.org This snippet demonstrates retrieving the address of an actor associated with a specific role using DirectorControl. It shows how to get the address for 'MainFoo' and handle cases where the role is not found, including suppressing error output with `silent=True`. ```python from thespian.director import DirectorControl dc = DirectorControl() r = dc.get_role_address('MainFoo') print(r) r = dc.get_role_address('unknown role name') print(r) r = dc.get_role_address('unknown role name', silent=True) print(r) ``` -------------------------------- ### Create Actor using ActorSystem Source: https://github.com/thespianpy/thespian/blob/master/doc/director.org Demonstrates how to instantiate an actor using the ActorSystem.createActor method by providing the actor class path. ```python good_addr = ActorSystem().createActor('foo.fooActor.FooActor', ...) ``` -------------------------------- ### Process Startup Configuration Source: https://github.com/thespianpy/thespian/blob/master/doc/using.org Configures the multiprocessing startup method for the ActorSystem. ```APIDOC ## Process Startup Method ### Description Specifies the multiprocessing context startup method used by the ActorSystem. ### Parameters - **method** (string) - Optional - Values: "fork", "spawn", or "forkserver". Default: "fork" (Unix) or "spawn" (Windows). ### Usage Set via system configuration before the ActorSystem starts. ### Example { "process_startup_method": "spawn" } ``` -------------------------------- ### Interact with Director Actor via Messages (Python) Source: https://github.com/thespianpy/thespian/blob/master/doc/director.org This snippet demonstrates how to interact with the Director Actor by sending messages. It shows how to create an ActorSystem, get the Director's address, and send a 'RetrieveAll' operation to get information about loaded sources. The response is then printed. ```python import thespian.actors asys = ActorSystem() director_addr = asys.createActor('thespian.director', globalName='Director') resp = asys.ask(director_addr, { "DirectorOp": "RetrieveAll"}) print(str(resp)) ``` -------------------------------- ### Python: Initialize and Shutdown Actor System Source: https://github.com/thespianpy/thespian/blob/master/doc/in_depth.org Demonstrates the creation of an Actor System, creation of an Actor, sending a message using ask(), and finally shutting down the Actor System to release resources. The ActorSystem() constructor acts as a singleton. ```python from thespian.actors import * actorsys = ActorSystem() hello = actorsys.createActor(Hello) print(actorsys.ask(hello, 'are you there?', 1.5)) actorsys.shutdown() ``` -------------------------------- ### GET /listen Source: https://github.com/thespianpy/thespian/blob/master/doc/using.org Waits for a message to be received by the local endpoint. ```APIDOC ## GET /listen ### Description Blocks the execution to wait for any message sent to the local ActorSystem endpoint. Optionally accepts a timeout. ### Method GET ### Endpoint /listen ### Parameters #### Query Parameters - **timeout** (timedelta/int/float) - Optional - Time to wait for a message before returning None. ### Request Example None ### Response #### Success Response (200) - **message** (any) - The received message or None if timed out. #### Response Example { "message": "data" } ``` -------------------------------- ### Python Actor Message Mutability Example Source: https://github.com/thespianpy/thespian/blob/master/doc/using.html Illustrates a potential issue with message mutability in Thespian. ActorA sends a message to ActorB, and ActorB modifies it. This example shows how ActorA's assertion about the message content might fail depending on the system base used, especially with the simpleSystemBase. ```python class ActorA(Actor): def receiveMessage(self, message, sender): ... actorb = self.createActor(ActorB) newmsg = NewMessage(foo="foo") self.messages.append(newmsg) self.send(actorb, newmsg) ... for each in self.messages: assert each.foo == "foo" class ActorB(Actor): def receiveMessage(self, message, sender): message.foo = "bar" ``` -------------------------------- ### POST /ActorSystem Source: https://github.com/thespianpy/thespian/blob/master/doc/using.org Initializes or connects to an ActorSystem instance. This is the primary entry point for interacting with actors. ```APIDOC ## POST /ActorSystem ### Description Creates a new ActorSystem or returns a reference to an existing one. The system manages actor lifecycles and communication. ### Method POST ### Parameters #### Request Body - **systemBase** (string) - Optional - The implementation base to use for the ActorSystem. - **capabilities** (dict) - Optional - A dictionary of capability keys and values. - **logDefs** (dict/bool) - Optional - Logging configuration dictionary or False to disable. - **transientUnique** (bool) - Optional - If true, creates a new, un-registered ActorSystem instance. ### Request Example { "systemBase": null, "capabilities": {"region": "us-east"}, "transientUnique": false } ### Response #### Success Response (200) - **ActorSystem** (object) - The initialized ActorSystem instance. #### Response Example { "status": "success", "instance": "ActorSystemObject" } ``` -------------------------------- ### Import Thespian Library Source: https://github.com/thespianpy/thespian/blob/master/doc/using.html To use Thespian, it must be installed and then imported into your Python environment. This makes all Thespian features available. ```python import thespian ``` -------------------------------- ### Message Mutability and Sending Source: https://github.com/thespianpy/thespian/blob/master/doc/using.org Discusses message mutability and provides examples of safe and potentially unsafe message sending patterns. ```APIDOC ## Message Mutability ### Description Thespian sends messages directly without automatic copying. While efficient, this means that if a sending Actor maintains a reference to a sent message, the message data may be modified by the recipient. It is recommended to avoid holding references to sent messages after calling `.send()`. ### Method N/A ### Endpoint N/A ### Parameters N/A ### Request Example ```python # Safe pattern: Message not referenced after send class MyActor(Actor): def receiveMessage(self, message, sender): ... self.send(actor2, NewMessage(...)) ... ``` ```python # Potentially unsafe pattern: Reference maintained to sent message class ActorA(Actor): def receiveMessage(self, message, sender): ... actorb = self.createActor(ActorB) newmsg = NewMessage(foo="foo") self.messages.append(newmsg) # Reference maintained self.send(actorb, newmsg) ... for each in self.messages: assert each.foo == "foo" # Potential modification by recipient ``` ### Response N/A ``` -------------------------------- ### Instantiate ActorSystem with Optional Parameters in Python Source: https://github.com/thespianpy/thespian/blob/master/doc/using.org This Python code shows how to instantiate the ActorSystem class, allowing for optional configuration of the system base, capabilities, logging definitions, and transient unique behavior. If parameters are None, default values or existing system configurations are used. ```python actorSys = ActorSystem(systemBase = None, capabilities = None, logDefs = None, transientUnique = False) ``` -------------------------------- ### Actor System Initialization and Lifecycle Source: https://github.com/thespianpy/thespian/blob/master/doc/in_depth.org Covers the creation, usage, and shutdown of the Actor System. ```APIDOC ## Actor System Initialization and Lifecycle ### Description This section describes how to initialize, use, and properly shut down the Actor System. ### Initialization * **ActorSystem()** * Description: Creates an Actor System. This call is a singleton; the first invocation creates the system, and subsequent calls return the existing instance. * Usage: `actorsys = ActorSystem()` ### Actor Creation * **createActor(ActorClass)** * Description: Creates an instance of the specified Actor class within the Actor System. * Usage: `actor_instance = actorsys.createActor(ActorClass)` ### Shutdown * **shutdown()** * Description: Releases all resources associated with the Actor System and terminates all running actors within it. * Usage: `actorsys.shutdown()` ### Example Usage ```python from thespian.actors import ActorSystem # Initialize the Actor System (singleton) actorsys = ActorSystem() # Create an actor # hello = actorsys.createActor(Hello) # Send a message and wait for a response # response = actorsys.ask(hello, 'are you there?', 1.5) # print(response) # Shut down the Actor System actorsys.shutdown() ``` ``` -------------------------------- ### Send Message to Thespian Application Source: https://github.com/thespianpy/thespian/blob/master/examples/multi_system/act5/README.org Sends a message to the running Thespian application. This is typically used after starting one or more actor systems. ```bash echo "This is a multi-system test" | python app.py ``` -------------------------------- ### Creating a Transient ActorSystem Source: https://github.com/thespianpy/thespian/blob/master/doc/using.html Details on how to create a new, independent ActorSystem instance. ```APIDOC ## Creating a Transient ActorSystem ### Description Setting the `transientUnique` argument to `True` during ActorSystem initialization ensures that a new, unregistered ActorSystem is created, rather than retrieving or reusing an existing singleton instance. Other arguments should specify the configuration for this new system. ### Method `ActorSystem(transientUnique=True, ...)` ### Endpoint N/A (This is a function call, not an HTTP endpoint) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **transientUnique** (bool) - Required - Set to `True` to create a new, unique ActorSystem. - Other ActorSystem initialization parameters can also be provided. ### Request Example ```python from thespian.actors import ActorSystem # Create a new, transient ActorSystem transient_asys = ActorSystem(transientUnique=True) # This new ActorSystem is independent of any previously created ones. ``` ### Response #### Success Response (200) - **ActorSystem object** - A newly created, transient ActorSystem instance. #### Response Example ```python # ``` ``` -------------------------------- ### Accessing the Singleton ActorSystem Source: https://github.com/thespianpy/thespian/blob/master/doc/using.html Explains how to access the process-wide singleton ActorSystem instance. ```APIDOC ## Accessing the Singleton ActorSystem ### Description When called without arguments, `ActorSystem()` returns a reference to the previously created ActorSystem in the current process. If no ActorSystem has been created, it initializes one with default parameters. ### Method `ActorSystem()` ### Endpoint N/A (This is a function call, not an HTTP endpoint) ### Parameters None ### Request Example ```python from thespian.actors import ActorSystem # Get the existing ActorSystem instance current_asys = ActorSystem() # Use the ActorSystem to create an actor # my_actor = current_asys.createActor(MyActorClass) ``` ### Response #### Success Response (200) - **ActorSystem object** - The singleton ActorSystem instance for the process. #### Response Example ```python # ``` ``` -------------------------------- ### Implement Dead Letter Handling Source: https://context7.com/thespianpy/thespian/llms.txt This example demonstrates how actors can register to receive messages that are sent to non-existent actors. It shows the implementation of a DeadLetterHandler actor that collects and reports these messages. ```python from thespian.actors import Actor, ActorSystem, ActorExitRequest, DeadEnvelope import time class DeadLetterHandler(Actor): def __init__(self): super().__init__() self.dead_letters = [] def receiveMessage(self, message, sender): if message == 'register': self.handleDeadLetters(True) self.send(sender, 'Registered for dead letters') elif isinstance(message, DeadEnvelope): self.dead_letters.append({ 'original_message': message.deadMessage, 'intended_recipient': str(message.deadAddress) }) self.send(sender, f"Dead letter received: {message.deadMessage}") elif message == 'get_dead_letters': self.send(sender, self.dead_letters) elif message == 'unregister': self.handleDeadLetters(False) self.send(sender, 'Unregistered from dead letters') class TemporaryActor(Actor): def receiveMessage(self, message, sender): if message == 'get_address': self.send(sender, self.myAddress) elif isinstance(message, ActorExitRequest): pass asys = ActorSystem('simpleSystemBase') # Set up dead letter handler handler = asys.createActor(DeadLetterHandler) print(asys.ask(handler, 'register', timeout=1)) # Create and then kill an actor temp = asys.createActor(TemporaryActor) temp_address = asys.ask(temp, 'get_address', timeout=1) asys.tell(temp, ActorExitRequest()) # Send message to dead actor - will be routed to handler time.sleep(0.1) # Allow exit to complete asys.tell(temp_address, 'This message has nowhere to go') # Check dead letters time.sleep(0.1) dead_letters = asys.ask(handler, 'get_dead_letters', timeout=1) print(f"Dead letters: {dead_letters}") asys.shutdown() ``` -------------------------------- ### Thespian Internal Logging Environment Variables Source: https://github.com/thespianpy/thespian/blob/master/doc/using.org Environment variables used to control Thespian's internal logging file path and maximum file size. These must be set before starting the ActorSystem. ```bash # Set the filepath for Thespian internals logging export THESPLOG_FILE=~/thespian_internal.log # Set the maximum size for the Thespian internals logging file (e.g., 100KB) export THESPLOG_FILE_MAXSIZE=100000 ```