Projector Examples
Read-side projectors from the poker domain. All code is from the actual examples/ directory.
Projectors subscribe to events and produce read-optimized views: text logs, database tables, search indexes, or external API calls.
Output Projector
Section titled “Output Projector”The Output Projector subscribes to events from multiple domains (player, table, hand) and writes formatted game logs to a file. This demonstrates a multi-domain projector.
examples/cpp/prj-output/src/main.cpp
Projectors are classes with @projects / [Projects] decorators on event-handling methods — the same OO pattern as aggregates and sagas. All six languages use this.
Multi-Domain Subscription
Section titled “Multi-Domain Subscription”Projectors can subscribe to events from multiple domains. The Output projector subscribes to player, table, and hand domains:
flowchart LR
P[player domain] --> O[Output Projector]
T[table domain] --> O
H[hand domain] --> O
O --> F[hand_log.txt]
Each language’s ProjectorHandler/ProjectorBase accepts multiple domain names:
handler = ProjectorHandler("output", "player", "table", "hand")Projector Principles
Section titled “Projector Principles”- Read-only — Projectors never modify domain state, only create read views
- Idempotent — Same events always produce same projections
- Catchup safe — Can replay full event history to rebuild state
- Domain aware — Subscribe to specific domains, filter unwanted events
- Stateful OK — Can maintain local state (caches, maps) for rendering
Running Projectors
Section titled “Running Projectors”With ProjectorHandler (All Languages)
Section titled “With ProjectorHandler (All Languages)”# Pythoncd examples/python && python -m prj-output.main
# Gocd examples/go && go run ./prj-output
# Rustcd examples/rust && cargo run --bin prj-output
# Javacd examples/java && ./gradlew prj-output:run
# C#cd examples/csharp && dotnet run --project Prj/Output
# C++cd examples/cpp && ./build/prj-outputNext Steps
Section titled “Next Steps”- Aggregates — Command handling examples
- Sagas — Cross-domain coordination