Directed message channel between two nodes. An `Edge` buffers at most one in-flight message at a time. It can be opened/closed via a gate, and it becomes *congested* when a message is pending consumption by the receiver.
| 10 | from .node import Node |
| 11 | |
| 12 | class Edge: |
| 13 | """Directed message channel between two nodes. |
| 14 | |
| 15 | An `Edge` buffers at most one in-flight message at a time. It can be opened/closed via a |
| 16 | gate, and it becomes *congested* when a message is pending consumption by the receiver. |
| 17 | """ |
| 18 | |
| 19 | class Hook: |
| 20 | SEND_MESSAGE = 'send_message' |
| 21 | RECEIVE_MESSAGE = 'receive_message' |
| 22 | def __init__(self, |
| 23 | sender:Node, |
| 24 | receiver:Node, |
| 25 | keys:dict[str,dict|str]|None=None): |
| 26 | """ |
| 27 | Args: |
| 28 | sender: Source node. |
| 29 | receiver: Target node. |
| 30 | keys: Message fields forwarded by this edge. |
| 31 | """ |
| 32 | self._sender:Node = sender |
| 33 | self._receiver:Node = receiver |
| 34 | self._keys:dict[str,dict|str] = keys if keys is not None else {"message":""} |
| 35 | self._message:dict = {} |
| 36 | self._is_congested:bool = False |
| 37 | self._gate:Gate = Gate.OPEN |
| 38 | self._hooks = HookManager() |
| 39 | @property |
| 40 | def hooks(self) -> HookManager: |
| 41 | return self._hooks |
| 42 | def hook_register( |
| 43 | self, |
| 44 | hook_key: object, |
| 45 | func: Callable, |
| 46 | recursion: bool = False, |
| 47 | target_type: type | tuple[type, ...] | None = None, |
| 48 | target_filter: Callable[[object], bool] | None = None, |
| 49 | selector: Selector | None = None, |
| 50 | ) -> None: |
| 51 | """ |
| 52 | Register edge hooks with selector filtering. |
| 53 | |
| 54 | Edge objects do not support name filtering. |
| 55 | |
| 56 | Args: |
| 57 | hook_key: Hook stage key. |
| 58 | func: Hook callback function. |
| 59 | recursion: Reserved for API parity. Recursion is implemented by graphs. |
| 60 | target_type: Optional type filter used by the selector. |
| 61 | target_filter: Optional predicate applied to the matched object. |
| 62 | selector: Optional explicit selector. When provided, it overrides `target_type/target_filter`. |
| 63 | """ |
| 64 | predicate = None |
| 65 | if target_filter is not None: |
| 66 | predicate = lambda t: t.obj is not None and target_filter(t.obj) |
| 67 | |
| 68 | selector = build_selector( |
| 69 | selector=selector, |
no outgoing calls
no test coverage detected