Skip to main content

backbone_core/
projection.rs

1//! Projector base trait for CQRS read models.
2//!
3//! Phase 0 generic base for the `projection.rs` generator (Category C).
4//!
5//! Each generated `{Name}Projector` struct applies domain events to its
6//! projection (read model). The structural contract — applying an event and
7//! rebuilding from scratch — is identical for all entities. This trait
8//! captures that contract so generated projectors can implement rather than
9//! independently describe it.
10//!
11//! ## Generated output (after Phase 1):
12//! ```rust,ignore
13//! use backbone_core::projection::Projector;
14//!
15//! #[async_trait]
16//! impl<R: OrderProjectionRepository> Projector<Order, OrderEvent> for OrderProjector<R> {
17//!     async fn project(&self, event: OrderEvent, sequence: i64) -> anyhow::Result<()> {
18//!         // dispatch to on_created / on_updated / on_deleted
19//!     }
20//!     async fn rebuild(&self) -> anyhow::Result<u64> {
21//!         self.repository.rebuild_all().await
22//!     }
23//! }
24//! ```
25
26use async_trait::async_trait;
27
28/// Applies domain events to a CQRS read model (projection).
29///
30/// Type parameters:
31/// - `E`   — entity type the projection is built from
32/// - `Evt` — domain event type (e.g. `OrderEvent` / `CrudEvent<Order>`)
33///
34/// The entity-specific fields of the projection struct, the event handler
35/// methods, and the repository trait remain in the generated module.
36#[async_trait]
37pub trait Projector<E, Evt>: Send + Sync {
38    /// Apply a single domain event to update the read model.
39    ///
40    /// `sequence` is the monotonically-increasing position of the event in
41    /// the event store, used for ordering and idempotency tracking.
42    async fn project(&self, event: Evt, sequence: i64) -> anyhow::Result<()>;
43
44    /// Rebuild all projections from the full event history.
45    ///
46    /// Returns the number of projections rebuilt.
47    async fn rebuild(&self) -> anyhow::Result<u64>;
48}