Developer Guide
Design Principles
Message immutability
Once a message (request, response, event, or command) is created, its fields must not be mutated. See Message Bus: message integrity for the ownership rules that follow from this.
The invariant protects several properties the system depends on:
- Determinism: Every consumer sees the same input. Behavior is easier to reason about, replay, and test.
- Temporal integrity: A message preserves what was true when the system emitted it. Events and commands remain factual records instead of containers of drifting state.
- Safer concurrency: Readers do not need coordination to protect message payloads from later rewrites. This removes a common source of races around shared state.
- Easier debugging: Logs, traces, replay tools, and dead-letter inspection remain useful because the message still reflects the original payload.
- Reliable replay and simulation: Replaying a sequence yields the same logical inputs as the original run. This supports backtesting, incident reconstruction, and regression testing.
- Clear ownership boundaries: Components treat incoming messages as input. If a component needs a different representation, it derives new local state or a new message explicitly.
- Better auditability: The system can answer what it knew, when it knew it, and what it did from that information.
- More robust distribution: Serialized messages already cross process and service boundaries as copies. The same ownership rule keeps the in-memory model aligned with that reality.
Environment Setup
For development we recommend using the PyCharm Professional edition IDE, as it interprets Cython syntax. Alternatively, you could use Visual Studio Code...
Coding Standards
The current codebase can be used as a guide for formatting conventions. Additional guidelines are provided below.