docs: add docstrings for actor base components

This commit is contained in:
2026-05-11 14:25:43 +02:00
committed by David Perl
parent 380544bef0
commit d9c1e4787a
3 changed files with 39 additions and 2 deletions
+16
View File
@@ -21,6 +21,18 @@ class ActorCondition(Protocol):
@dataclass
class ActorConditionSet:
"""
An actor condition combines a set of conditions to act as one. The combination mode defines
how they are combined. For example:
```
ActorConditionSet(
conditions = {lambda client: True, lambda client: False},
combination_mode = ConditionCombination.Any
)
```
would evaluate to `True` when called, while with `ConditionCombination.All` it would be `False`.
"""
conditions: set[ActorCondition]
combination_mode: ConditionCombination
@@ -38,3 +50,7 @@ class ActorAction(Protocol):
ActorActionTable = TypeAliasType(
"ActorActionTable", dict[ActorConditionSet | ActorCondition, ActorAction]
)
"""Mapping of action conditions to their actions. Keys are condition callables
which evaluate to booleans, or combinations of such callables. Values are
Actions, callables which accept a BECClient as their only argument, and specify
what to do if a condition returns `True`."""
+11
View File
@@ -2025,6 +2025,9 @@ class AvailableBeamlineStatesMessage(BECMessage):
class ActorStartRequestMessage(BECMessage):
"""Specify an actor class by module and name, to be instantiated and started by the actor
manager."""
msg_type: ClassVar[str] = "actor_start_request"
actor_module: str
@@ -2032,12 +2035,18 @@ class ActorStartRequestMessage(BECMessage):
class ActorStopRequestMessage(BECMessage):
"""Specify an actor to be stopped by the actor manager. By default, the id of a running actor
will be its class as a fully qualified path, since there should be only one of each type of
actor at any time."""
msg_type: ClassVar[str] = "actor_stop_request"
actor_id: str
class ActorExecutionMessage(BECMessage):
"""Message type for internal use to track running actors."""
msg_type: ClassVar[str] = "actor_execution"
queue: str
@@ -2046,6 +2055,8 @@ class ActorExecutionMessage(BECMessage):
class ActorStopMessage(BECMessage):
"""Message for internal use to signal a running actor to stop execution."""
msg_type: ClassVar[str] = "actor_stop"
execution_id: str
+12 -2
View File
@@ -30,6 +30,17 @@ class ActorBase(ABC):
push_status(self.client.connector, self.name, st, exec)
def evaluate(self, *_, **__):
"""
For each `(condition, action)` entry in the `action_table` dictionary, call `condition`, and
if it returns `True`, call `action`. It accepts any args and kwargs but does not use any of
them - subclasses may use this as a callback for a function which returns anything without
overriding it, to trigger evaluation of the actor as a response. Each condition may be a
simple function which evaluates to a boolean, or a `bec_lib.actors.ActorConditionSet` with
a set of such functions and an operation to combine them.
This is called in a loop by the `PollingActor`, and called as a callback to any Redis event
it is subscribed to in the `SubscriptionActor`.
"""
for condition, action in self.action_table.items():
if condition(self.client):
logger.info(
@@ -65,10 +76,9 @@ class SubscriptionActor(ActorBase):
return set()
def evaluate(self, *_, **__):
logger.info(f"{self.__class__.__name__} triggered")
if (now := time.monotonic()) < self.last_evaluated + self.min_delay_s:
logger.info("too little time elapsed since last trigger")
return
logger.info(f"{self.__class__.__name__} triggered")
self.last_evaluated = now
return super().evaluate(*_, **__)