Events and Causal History
The Event is the fundamental building block of PyRapide. Every observable occurrence in a distributed system (a sensor reading, an API call, a database write) is modeled as an immutable, uniquely-identified record.
Creating Events
An Event carries three core pieces of information: a name that
classifies what happened, a payload containing the associated data, and a source identifying where it originated.
from pyrapide import Event
event = Event(
name="patient.vitals.recorded",
payload={"heart_rate": 72, "bp_systolic": 120, "bp_diastolic": 80},
source="icu-monitor-7"
)
Each event is automatically assigned a unique identifier upon creation. You never need to manage IDs manually. PyRapide handles identity for you.
Immutability Guarantees
Events are frozen Pydantic models. Once created, no field can be modified. This design gives you several guarantees:
- Immutable: fields cannot be reassigned after construction, preventing accidental mutation in concurrent code.
- Hashable: events can be used as dictionary keys or stored in sets, enabling efficient lookups and deduplication.
- Serializable: events serialize cleanly to JSON, MessagePack, or any format Pydantic supports, making them ideal for network transport and persistence.
Identity and Comparison
Two events are considered equal if and only if they share the same unique ID. Even if two events carry identical names, payloads, and sources, they are distinct records representing distinct occurrences.
e1 = Event(name="sensor.reading", payload={"temp": 22.5}, source="sensor-1")
e2 = Event(name="sensor.reading", payload={"temp": 22.5}, source="sensor-1")
assert e1 != e2 # Different unique IDs
assert e1.id != e2.id # Each event gets its own identity
This identity model mirrors real-world causality: two identical sensor readings taken one second apart are different events, even though their data is the same. The unique ID captures when and that something happened, not just what happened.
name field with dot-separated namespaces (e.g., patient.vitals.recorded) to keep event taxonomies organized as your system grows.Event Anatomy
Every Event instance exposes the following fields:
id: a unique identifier (UUID) assigned at creation time.name: a string classifying the type of occurrence.payload: a dictionary of arbitrary data associated with the event.source: an optional string identifying the originating component or device.timestamp: the wall-clock time at which the event was created.
Events on their own capture what happened. To capture why, including the causal relationships between events, you need Posets.