Repository: proxystore/aeris

Issue:
Rename callbacks to `on_startup` and `on_shutdown`
I think this will make it more clear these are callbacks rather than actions.

Discussion:

Solution patch:
diff --git a/aeris/agent.py b/aeris/agent.py
index 625711c..efd58ca 100644
--- a/aeris/agent.py
+++ b/aeris/agent.py
@@ -261,7 +261,7 @@ def start(self) -> None:
             is shutdown.
 
         1. Binds all unbound handles to remote agents to this agent.
-        1. Calls [`Behavior.setup()`][aeris.behavior.Behavior.setup].
+        1. Calls [`Behavior.on_setup()`][aeris.behavior.Behavior.on_setup].
         1. Starts threads for all control loops defined on the agent's
            [`Behavior`][aeris.behavior.Behavior].
         1. Starts a thread for listening to messages from the
@@ -283,7 +283,7 @@ def start(self) -> None:
             )
             self._state = _AgentState.STARTING
             self._bind_handles()
-            self.behavior.setup()
+            self.behavior.on_setup()
             self._action_pool = ThreadPoolExecutor()
             self._loop_pool = ThreadPoolExecutor(
                 max_workers=len(self._loops) + 1,
@@ -314,7 +314,8 @@ def shutdown(self) -> None:
            will be processed.
         1. Waits for the control loop and message listener threads to exit.
         1. Optionally closes the exchange.
-        1. Calls [`Behavior.shutdown()`][aeris.behavior.Behavior.shutdown].
+        1. Calls
+           [`Behavior.on_shutdown()`][aeris.behavior.Behavior.on_shutdown].
 
         Raises:
             Exception: Any exceptions raised inside threads.
@@ -346,7 +347,7 @@ def shutdown(self) -> None:
             if self.close_exchange:
                 self.exchange.close()
 
-            self.behavior.shutdown()
+            self.behavior.on_shutdown()
             self._state = _AgentState.SHUTDOWN
 
             # Raise any exceptions from the loop threads as the final step.
diff --git a/aeris/behavior.py b/aeris/behavior.py
index 0dbd324..7bf8a5b 100644
--- a/aeris/behavior.py
+++ b/aeris/behavior.py
@@ -41,12 +41,12 @@ class Behavior:
     All [`Agent`][aeris.agent.Agent] instances execute a behavior which is
     defined by a subclass of the [`Behavior`][aeris.behavior.Behavior]. Each
     behavior is composed of three parts:
-      1. The [`startup()`][aeris.behavior.Behavior.setup] and
-         [`shutdown()`][aeris.behavior.Behavior.shutdown] methods that are
-         invoked once and the start and end of an agent's execution,
-         respectively. The methods should be used to initialize and cleanup
-         stateful resources. Resource initialization should not be performed
-         in `__init__`.
+      1. The [`on_startup()`][aeris.behavior.Behavior.setup] and
+         [`on_shutdown()`][aeris.behavior.Behavior.shutdown] methods define
+         callbacks that are invoked once at the start and end of an agent's
+         execution, respectively. The methods should be used to initialize and
+         cleanup stateful resources. Resource initialization should not be
+         performed in `__init__`.
       2. Action methods annotated with [`@action`][aeris.behavior.action]
          are methods that other agents can invoke on this agent. An agent
          may also call it's own action methods as normal methods.
@@ -113,14 +113,14 @@ def behavior_handles(self) -> dict[str, Handle[Any]]:
                 handles[name] = attr
         return handles
 
-    def setup(self) -> None:
+    def on_setup(self) -> None:
         """Setup up resources needed for the agents execution.
 
         This is called before any control loop threads are started.
         """
         pass
 
-    def shutdown(self) -> None:
+    def on_shutdown(self) -> None:
         """Shutdown resources after the agents execution.
 
         This is called after control loop threads have exited.
diff --git a/examples/01-actor-client/run-01.py b/examples/01-actor-client/run-01.py
index 4debde2..367af89 100644
--- a/examples/01-actor-client/run-01.py
+++ b/examples/01-actor-client/run-01.py
@@ -14,7 +14,7 @@
 class Counter(Behavior):
     count: int
 
-    def setup(self) -> None:
+    def on_setup(self) -> None:
         self.count = 0
 
     @action
diff --git a/examples/02-agent-loop/run-02.py b/examples/02-agent-loop/run-02.py
index 9b296c1..019a7bd 100644
--- a/examples/02-agent-loop/run-02.py
+++ b/examples/02-agent-loop/run-02.py
@@ -19,7 +19,7 @@
 class Counter(Behavior):
     count: int
 
-    def setup(self) -> None:
+    def on_setup(self) -> None:
         self.count = 0
 
     @loop
diff --git a/testing/behavior.py b/testing/behavior.py
index d0d3f51..9fe2e71 100644
--- a/testing/behavior.py
+++ b/testing/behavior.py
@@ -43,7 +43,7 @@ class CounterBehavior(Behavior):
     def __init__(self) -> None:
         self._count = 0
 
-    def setup(self) -> None:
+    def on_setup(self) -> None:
         self._count = 0
 
     @action
@@ -60,7 +60,7 @@ def __init__(self, loop_sleep: float = 0.001) -> None:
         self.loop_sleep = loop_sleep
         self.steps = 0
 
-    def shutdown(self) -> None:
+    def on_shutdown(self) -> None:
         assert self.steps > 0
 
     @action


Test patch:
diff --git a/tests/agent_test.py b/tests/agent_test.py
index ea188be..2d631df 100644
--- a/tests/agent_test.py
+++ b/tests/agent_test.py
@@ -32,10 +32,10 @@ def __init__(self) -> None:
         self.loop_event = threading.Event()
         self.shutdown_event = threading.Event()
 
-    def setup(self) -> None:
+    def on_setup(self) -> None:
         self.setup_event.set()
 
-    def shutdown(self) -> None:
+    def on_shutdown(self) -> None:
         self.shutdown_event.set()
 
     @loop
@@ -250,7 +250,7 @@ def __init__(
         self.agent_bound = agent_bound
         self.self_bound = self_bound
 
-    def setup(self) -> None:
+    def on_setup(self) -> None:
         assert isinstance(self.unbound, BoundRemoteHandle)
         assert isinstance(self.client_bound, ClientRemoteHandle)
         assert isinstance(self.agent_bound, BoundRemoteHandle)
@@ -263,7 +263,7 @@ def setup(self) -> None:
             == self.self_bound.mailbox_id
         )
 
-    def shutdown(self) -> None:
+    def on_shutdown(self) -> None:
         self.unbound.close()
         self.client_bound.close()
         self.agent_bound.close()
@@ -290,8 +290,8 @@ def test_agent_run_bind_handles(exchange: Exchange) -> None:
 
     agent._bind_handles()
     agent._bind_handles()  # Idempotency check
-    agent.behavior.setup()
-    agent.behavior.shutdown()
+    agent.behavior.on_setup()
+    agent.behavior.on_shutdown()
     # The client-bound and self-bound remote handles should be ignored.
     assert len(agent._multiplexer.bound_handles) == 2  # noqa: PLR2004
 
@@ -300,7 +300,7 @@ class RunBehavior(Behavior):
     def __init__(self, doubler: Handle[DoubleBehavior]) -> None:
         self.doubler = doubler
 
-    def shutdown(self) -> None:
+    def on_shutdown(self) -> None:
         assert isinstance(self.doubler, BoundRemoteHandle)
         self.doubler.shutdown()
 
diff --git a/tests/behavior_test.py b/tests/behavior_test.py
index 309dabe..b4faac9 100644
--- a/tests/behavior_test.py
+++ b/tests/behavior_test.py
@@ -21,7 +21,7 @@ def test_initialize_base_type_error() -> None:
 
 def test_behavior_empty() -> None:
     behavior = EmptyBehavior()
-    behavior.setup()
+    behavior.on_setup()
 
     assert isinstance(behavior, EmptyBehavior)
     assert isinstance(str(behavior), str)
@@ -31,24 +31,24 @@ def test_behavior_empty() -> None:
     assert len(behavior.behavior_loops()) == 0
     assert len(behavior.behavior_handles()) == 0
 
-    behavior.shutdown()
+    behavior.on_shutdown()
 
 
 def test_behavior_actions() -> None:
     behavior = IdentityBehavior()
-    behavior.setup()
+    behavior.on_setup()
 
     actions = behavior.behavior_actions()
     assert set(actions) == {'identity'}
 
     assert behavior.identity(1) == 1
 
-    behavior.shutdown()
+    behavior.on_shutdown()
 
 
 def test_behavior_loops() -> None:
     behavior = WaitBehavior()
-    behavior.setup()
+    behavior.on_setup()
 
     loops = behavior.behavior_loops()
     assert set(loops) == {'wait'}
@@ -57,18 +57,18 @@ def test_behavior_loops() -> None:
     shutdown.set()
     behavior.wait(shutdown)
 
-    behavior.shutdown()
+    behavior.on_shutdown()
 
 
 def test_behavior_handles() -> None:
     handle = ProxyHandle(EmptyBehavior())
     behavior = HandleBehavior(handle)
-    behavior.setup()
+    behavior.on_setup()
 
     handles = behavior.behavior_handles()
     assert set(handles) == {'handle'}
 
-    behavior.shutdown()
+    behavior.on_shutdown()
 
 
 def test_invalid_loop_signature() -> None:
diff --git a/tests/launcher/executor_test.py b/tests/launcher/executor_test.py
index 77f392e..36f1dbf 100644
--- a/tests/launcher/executor_test.py
+++ b/tests/launcher/executor_test.py
@@ -95,7 +95,7 @@ def test_wait_timeout(exchange: Exchange) -> None:
 
 
 class FailOnStartupBehavior(Behavior):
-    def setup(self) -> None:
+    def on_setup(self) -> None:
         raise RuntimeError('Agent startup failed')