edri.dataclass package

Subpackages

Submodules

edri.dataclass.event module

class edri.dataclass.event.Event[source]

Bases: object

as_dict(*, transform: bool, keep_concealed: bool) → dict[str, Any][source]
copy_sender(event: Event) → None[source]
get_context() → dict[str, Any][source]

Retrieve a dictionary of all keyword-only fields from the dataclass.

This method inspects the dataclass and extracts all fields that are marked as kw_only=True, returning their names and current values.

Returns:

A dictionary where the keys are the names of keyword-only

fields and the values are their corresponding values in the dataclass instance.

Return type:

dict[str, Any]

get_response() → Response | None[source]
has_response() → bool[source]
classmethod hash_name() → int[source]
method: HTTPMethod | None = None
remove_response() → None[source]
response: Response | None = None
set_response(response: Response) → None[source]
class edri.dataclass.event.EventHandlingType(*values)[source]

Bases: IntFlag

IntFlag representing different modes of event handling in the system.

The EventHandlingType IntFlag categorizes the ways in which events are handled and dispatched to clients in the API broker system. Each mode defines a distinct strategy for event delivery, ensuring that events reach their intended recipients based on the specified criteria. With IntFlag, multiple modes can be combined using bitwise operations.

Attributes:
  • SPECIFIC (int) -- Handles an event in a 1:1 fashion, responding directly to the

  • client that requested it. This mode ensures that the event is sent only to

  • the client whose request triggered the event. Events in this mode are created

  • exclusively by API handlers to fulfill specific client requests. -- Example APIs: Typically used for REST or HTML requests where a client makes a direct request, and the server provides a direct response.

  • SUBSCRIBED (int) -- Sends the event exclusively to clients who have registered

  • their interest by subscribing to this event type. This mode is used for

  • events meant to notify or update only a specific subset of clients. -- Example APIs: Suitable for APIs with asynchronous capabilities, such as WebSocket or MQTT, where clients subscribe to events and receive notifications asynchronously.

  • ALL (int) -- Broadcasts the event to all clients connected to the system capable

  • of receiving asynchronous events, regardless of their specific subscription status.

  • This mode does not limit the broadcast to only those who subscribed to a specific type. -- Example APIs: Similar to SUBSCRIBED, this mode applies to protocols like WebSocket or MQTT, but the event is sent to all clients, not just those subscribed to a specific type.

Combinations:

SPECIFIC|SUBSCRIBED (int): A flexible mode of event handling where the event can either be a direct 1:1 response to a client's request or be broadcasted to all clients subscribed to that event type. The handling behavior is determined by the context in which the event is created. If the event originates from a REST request or similar, it might behave like a SPECIFIC event. If generated internally as part of core logic, it might be broadcast to subscribers.

Example APIs: Can be used for REST or HTML requests but also applies to asynchronous protocols like WebSocket or MQTT where clients can subscribe to specific events.

SPECIFIC|ALL (int): Similar to SPECIFIC|SUBSCRIBED, but with a broader scope. The event can either be sent as a direct response to the specific client that requested it or broadcasted to all clients capable of receiving events, regardless of their subscription status. The handling behavior is determined by the event's context — it is either specific or for all, but it cannot be both at the same time.

Example APIs: Applies to REST, HTML, WebSocket, or MQTT. The event could either act like a direct response to a client request or be broadcast to every client, but not both simultaneously.

ALL = 4
SPECIFIC = 1
SUBSCRIBED = 2
class edri.dataclass.event.SwitchInfo(router_id: UUID | None = None, received: bool = False)[source]

Bases: object

Per-hop transport state for distributing an event across the Switch.

router_id records which router sent the event on the current hop; received flags an event that arrived from the Switch so the local Router does not echo it straight back (see Router.send()). Both are re-stamped on every send/receive and reset when the event turns into a response.

The event's own stable identity (used by Cache.last_events()/ Cache.events_from() as the Switch resume marker) is Event._id — every event carries one unconditionally, not just shareable ones, so it no longer needs to live here.

received: bool = False
router_id: UUID | None = None
edri.dataclass.event.event(cls: type[_T], /) → type[_T][source]
edri.dataclass.event.event(cls: None = None, /, *, init: bool = True, repr: bool = True, eq: bool = True, order: bool = False, unsafe_hash: bool = False, frozen: bool = False, match_args: bool = True, kw_only: bool = False, slots: bool = False, weakref_slot: bool = False, shareable: bool = False) → Callable[[type[_T]], type[_T]]

edri.dataclass.health_checker module

class edri.dataclass.health_checker.HealthReport(status: Status = Status.OK, ready: bool = True, reason: str | None = None)[source]

Bases: object

A component's self-assessment, returned by its overridable health() probe.

Separates two questions the old single status conflated:

  • status — is the component healthy, impaired, or broken? The base probe derives this from caught exceptions; an override adds dependency checks (e.g. ping the database, downgrade to DEGRADED if it is down).

  • ready — can it accept traffic right now? A component that is alive but still warming up or draining reports ready=False while staying otherwise healthy.

Attributes:
  • status (Status) -- Overall health. Defaults to OK.

  • ready (bool) -- Whether the component is ready to accept work. Defaults to True.

  • reason (Optional[str]) -- Human-readable explanation for a non-OK status or non-ready state, surfaced on the health page. None when there is nothing to say.

ready: bool = True
reason: str | None = None
status: Status = 1
class edri.dataclass.health_checker.Record(name: str, pipe: ~multiprocessing.connection.Connection | None = None, definition: ManagerBase | None = None, timestamp: ~datetime.datetime = datetime.datetime(2026, 10, 15, 7, 43, 27, 863296), status: ~edri.dataclass.health_checker.Status = Status.WARNING, exceptions: list[tuple[str, dict[str, ~typing.Any], str, str, ~datetime.datetime]] = <factory>, vitals: ~edri.dataclass.health_checker.Vitals | None = None, health_rtt_seconds: float | None = None, ready: bool = True, reason: str | None = None)[source]

Bases: object

Represents the health status of a system component.

Attributes:
  • name (str) -- The name of the component.

  • pipe (Optional[Connection]) -- A connection object used for inter-process communication with the component. Defaults to None if not applicable.

  • definition (Optional[ManagerBase]) -- The class definition of the component, if available, providing metadata or configuration details.

  • timestamp (datetime) -- The timestamp of the last recorded health check. Defaults to the current time.

  • status (Status) -- The current health status of the component, represented by a Status enum. Defaults to Status.WARNING.

  • exceptions (list[tuple[str, dict, str, str, datetime]]) -- A list of recorded exceptions related to the component. Each entry contains the event name, event data, error message, traceback, and capture time.

  • vitals (Optional[Vitals]) -- The operational metrics from the component's most recent health-check response. None until the component has answered at least once.

  • health_rtt_seconds (Optional[float]) -- Round-trip latency of the most recent health check, measured by the Router (dispatch → component → back). Rises before a struggling component goes silent, so it is a degradation signal the component cannot report about itself. None until measured.

  • ready (bool) -- Whether the component reported itself ready to accept traffic on its last health check. Defaults to True.

  • reason (Optional[str]) -- The component's explanation for a non-OK status or non-ready state.

definition: ManagerBase | None = None
health_rtt_seconds: float | None = None
pipe: Connection | None = None
ready: bool = True
reason: str | None = None
status: Status = 2
timestamp: datetime = datetime.datetime(2026, 10, 15, 7, 43, 27, 863296)
vitals: Vitals | None = None
class edri.dataclass.health_checker.Status(*values)[source]

Bases: Enum

DEGRADED = 3

Alive and answering, but impaired — typically a dependency a component needs (a database, an upstream API) is unreachable. Self-reported by a component's health() probe; the Router never infers it (it only escalates to WARNING/ERROR from silence).

ERROR = 4
OK = 1
WARNING = 2
class edri.dataclass.health_checker.Vitals(workers_running: int = 0, workers_pending: int = 0, workers_limit: int = -1, workers_oldest_age_seconds: float | None = None, processed: int = 0, failed: int = 0, cpu_seconds: float = 0.0, rss_bytes: int | None = None, rss_peak_bytes: int | None = None, threads: int = 0, open_fds: int | None = None, pid: int = 0, uptime_seconds: float = 0.0, custom: dict[str, ~typing.Any]=<factory>)[source]

Bases: object

Operational metrics a component reports on every health-check round-trip.

The health check is a periodic two-way trip to every Manager that already happens; these are the vitals that ride along on it for free. They describe load and progress, complementing Status (which only says whether the component caught exceptions).

Some fields are point-in-time snapshots (workers_running, workers_oldest_age_seconds, rss_bytes, threads, open_fds), others are deltas accumulated over the interval since the previous check (processed, failed, cpu_seconds). The consumer interprets them accordingly.

Attributes:
  • workers_running (int) -- Workers currently alive (busy worker slots).

  • workers_pending (int) -- Work queued because every worker slot is full. The component's backpressure signal — a healthy component with a growing backlog is an early warning before it falls behind.

  • workers_limit (int) -- The max_workers ceiling. -1 means unbounded.

  • workers_oldest_age_seconds (Optional[float]) -- Age of the longest-running worker, or None when idle. A worker that keeps growing old is how a deadlock surfaces while the main loop still answers health checks — the heartbeat's truth signal.

  • processed (int) -- Events the component dispatched to handlers since the previous health check. Divided by the check interval, this is throughput.

  • failed (int) -- Of those, how many left a FAILED response — the error rate per interval.

  • cpu_seconds (float) -- CPU time (user + system) consumed since the previous check. Divided by the interval, this is the process's CPU utilization.

  • rss_bytes (Optional[int]) -- Resident memory of the component's process in bytes, or None when it cannot be read on this platform.

  • rss_peak_bytes (Optional[int]) -- Peak resident memory (high-water mark) in bytes, or None.

  • threads (int) -- Live threads in the process — a growing count flags a thread leak.

  • open_fds (Optional[int]) -- Open file descriptors, or None when unreadable — an fd-leak detector.

  • pid (int) -- The component process's PID, for correlation with external tools.

  • uptime_seconds (float) -- Seconds since the component process entered its run loop. A small value on a component that should be long-lived points at a crash-loop.

  • custom (dict[str, Any]) -- Application-defined metrics a component adds by overriding collect_custom_vitals(). Empty by default. Values should be JSON-serializable primitives so they survive both the pipe round-trip and the status endpoint's JSON encoding.

cpu_seconds: float = 0.0
failed: int = 0
open_fds: int | None = None
pid: int = 0
processed: int = 0
rss_bytes: int | None = None
rss_peak_bytes: int | None = None
threads: int = 0
uptime_seconds: float = 0.0
workers_limit: int = -1
workers_oldest_age_seconds: float | None = None
workers_pending: int = 0
workers_running: int = 0

edri.dataclass.injection module

class edri.dataclass.injection.Injection(classes: tuple[Callable[[...], Any], ...], parameters: dict[str, Any], _nullable: bool = False)[source]

Bases: object

A class that facilitates the injection of dependencies into one or more classes. It manages the initialization of multiple classes by providing their necessary parameters.

This class iterates over provided classes and dynamically creates callables that can instantiate each class with filtered parameters based on the provided arguments.

Parameters:
  • classes (tuple[Callable]) -- Validator classes or functions to call.

  • parameters (dict[str, Any]) -- A dictionary of parameter names and values that will be passed to the constructors of the classes. Only parameters matching the constructor's signature will be passed to the class.

Use | None to mark an injection as nullable — when the value is None, conversion returns None instead of running validation:

inject(StringValidator, minimum_length=2) | None
Methods:
  • __or__ -- Supports inject(...) | None syntax. Returns a copy of the Injection with _nullable=True.

  • __repr__ -- Returns a string representation of the Injection instance, showing the classes and the parameters that will be passed to their constructors.

edri.dataclass.persistence_failure_policy module

class edri.dataclass.persistence_failure_policy.PersistenceFailurePolicy(*values)[source]

Bases: Enum

Store persistence failure policies.

BUFFER keeps runtime operations available and retries writes in order using an unbounded memory queue. Additional policies can be added here when their behavior is implemented.

BUFFER = 'buffer'

edri.dataclass.response module

class edri.dataclass.response.Response[source]

Bases: object

add_directive(directive: ResponseDirective, /, *, ignore_status: bool = False) → None[source]
as_dict(*, transform: bool, keep_concealed: bool, wrapped: bool = True) → dict[str, Any][source]
get_directives() → list[ResponseDirective][source]
get_status() → ResponseStatus[source]
has_changed() → bool[source]
property is_file_only: bool
set_status(status: ResponseStatus) → None[source]
class edri.dataclass.response.ResponseStatus(*values)[source]

Bases: Enum

FAILED = 3
NONE = 1
OK = 2
edri.dataclass.response.response(cls: type[_R], /) → type[_R][source]
edri.dataclass.response.response(cls: None = None, /, *, init: bool = True, repr: bool = True, eq: bool = True, order: bool = False, unsafe_hash: bool = False, frozen: bool = False, match_args: bool = True, kw_only: bool = False, slots: bool = False, weakref_slot: bool | None = None) → Callable[[type[_R]], type[_R]]

edri.dataclass.topology module

class edri.dataclass.topology.ComponentNode(name: str, requests: list[str], responses: list[str], health: str | None, ready: bool, queue_depth: int, slow: bool, failed: bool, oldest_pending_seconds: float | None)[source]

Bases: object

One connected component in the Router's live routing graph.

requests / responses are the event-type names it is subscribed to. health is the health checker's status name (None when the component has no record yet). queue_depth / slow / failed come from its outbound worker; oldest_pending_seconds is how long the in-flight send has been stuck once it passes ROUTER_OUTBOUND_STALL_SECONDS, None while delivery is healthy.

class edri.dataclass.topology.ConnectorNode(requests: list[str], responses: list[str], queue_depth: int, slow: bool, failed: bool, oldest_pending_seconds: float | None)[source]

Bases: object

The connector edge - which shareable types cross to the Switch.

oldest_pending_seconds follows the same stalled-send rule as ComponentNode.

class edri.dataclass.topology.UnroutedEvent(name: str, direction: str, count: int, last_seen: datetime, known: bool)[source]

Bases: object

An event type the Router dropped because nothing was subscribed.

direction is "request" or "response". count and last_seen tally the drops since the Router started. known is True when the subscription map still holds a key for this type - a handler existed and went away - and False when it was never subscribed at all.

edri.dataclass.worker module

class edri.dataclass.worker.WorkerExit(*values)[source]

Bases: Enum

CANCELLED = 3
KILLED = 5
LOST = 6
RAISED = 2
RETURNED = 1
TERMINATED = 4
class edri.dataclass.worker.WorkerOutcome(*values)[source]

Bases: Enum

CANCELLED = 3
FAILED = 2
SUCCEEDED = 1
TIMED_OUT = 4
class edri.dataclass.worker.WorkerPolicy(queue_timeout: float | None = None, start_timeout: float | None = None, run_timeout: float | None = None, total_timeout: float | None = None, cancel_grace: float = 5.0, terminate_grace: float = 2.0)[source]

Bases: object

class edri.dataclass.worker.WorkerState(*values)[source]

Bases: Enum

PENDING = 1
RUNNING = 3
STARTING = 2
STOPPING = 4
TERMINATING = 5
class edri.dataclass.worker.WorkerStopReason(*values)[source]

Bases: Enum

APPLICATION = 5
CLIENT_DISCONNECT = 4
MANAGER_SHUTDOWN = 3
REQUESTED = 1
TIMEOUT = 2
class edri.dataclass.worker.WorkerTimeout(*values)[source]

Bases: Enum

QUEUE = 1
RUN = 3
START = 2
TOTAL = 4

Module contents