Skip to main content

replay_aggregate

Function replay_aggregate 

Source
pub fn replay_aggregate<A>(
    id: &<A as Entity>::Id,
    history: &StreamHistory<<A as AggregateRoot>::Event>,
) -> Result<RehydratedAggregate<A>, ReplayError<<A as AggregateReplay>::InitializationError, <A as AggregateReplay>::ApplicationError>>
where A: AggregateReplay,
Expand description

English:
Initializes A for id and applies every event in history in stored order. Returns the reconstructed aggregate and history revision. The first hook error is wrapped in ReplayError; the local aggregate is dropped on error. No storage or publishing is performed, and hook panics propagate. The caller must supply history belonging to id.

This counter restores two historical increments without queuing new events.

日本語:
id の A を初期化し、history の全イベントを保存順に適用します。 復元した集約と履歴リビジョンを返します。最初のフックエラーを ReplayError で包み、 エラー時はローカルな集約を破棄します。保存や発行は行わず、フックのパニックは伝播します。 呼び出し側は id に属する履歴を指定する必要があります。

このカウンターは新規イベントを保留せず、履歴の加算 2 件を復元します。

§Example / 使用例

use std::convert::Infallible;
use ddd_toolkit_core::{
    AggregateReplay, AggregateRoot, AggregateSnapshot, DomainEvent, Entity,
    SnapshotUse, StreamHistory, StreamRevision, replay_aggregate,
};
struct Increment(u64);
impl DomainEvent for Increment {}
struct Counter { id: u64, total: u64, pending: Vec<Increment> }
impl Entity for Counter {
    type Id = u64;
    fn id(&self) -> &u64 { &self.id }
}
impl AggregateRoot for Counter {
    type Event = Increment;
    fn record_event(&mut self, event: Increment) { self.pending.push(event); }
    fn pull_events(&mut self) -> Vec<Increment> { std::mem::take(&mut self.pending) }
}
impl AggregateReplay for Counter {
    type InitializationError = Infallible;
    type ApplicationError = &'static str;
    type Snapshot = u64;
    type SnapshotValidationError = Infallible;
    type SnapshotStateError = Infallible;
    fn initial_state(id: &u64) -> Result<Self, Infallible> {
        Ok(Self { id: *id, total: 0, pending: vec![] })
    }
    fn apply_event(&mut self, event: &Increment) -> Result<(), &'static str> {
        self.total = self.total.checked_add(event.0).ok_or("counter overflow")?;
        Ok(())
    }
    fn classify_snapshot(_: &AggregateSnapshot<u64>, _: StreamRevision)
        -> Result<SnapshotUse, Infallible> { Ok(SnapshotUse::Applicable) }
    fn from_snapshot(id: &u64, snapshot: AggregateSnapshot<u64>) -> Result<Self, Infallible> {
        Ok(Self { id: *id, total: snapshot.into_parts().0, pending: vec![] })
    }
}
let history = StreamHistory::try_new(vec![Increment(2), Increment(3)], StreamRevision::new(1))
    .unwrap();
let mut restored = replay_aggregate::<Counter>(&7, &history).unwrap();
assert_eq!(restored.aggregate.total, 5);
assert_eq!(restored.revision, StreamRevision::new(1));
assert!(restored.aggregate.pull_events().is_empty());
Examples found in repository?
examples/event_sourcing.rs (line 182)
175fn main() {
176    let mut store = MemoryEvents::default();
177    assert!(matches!(store.load(&1).unwrap(), LoadResult::NoStream(_)));
178    let first = store
179        .append(&1, ExpectedRevision::NoStream(NoStream), vec![Added::V1(2)])
180        .unwrap();
181    assert_eq!(first.resulting_revision, StreamRevision::new(0));
182    let mut replayed = replay_aggregate::<Counter>(&1, &history(&store)).unwrap();
183    assert_eq!(replayed.aggregate.value, 2);
184    assert!(replayed.aggregate.pull_events().is_empty());
185    let mut snapshots = MemorySnapshots::default();
186    snapshots
187        .save(
188            &1,
189            AggregateSnapshot::new(replayed.aggregate.value, replayed.revision),
190        )
191        .unwrap();
192    store
193        .append(
194            &1,
195            ExpectedRevision::Revision(replayed.revision),
196            vec![Added::V2 { amount: 3 }],
197        )
198        .unwrap();
199    assert!(matches!(
200        store.append(
201            &1,
202            ExpectedRevision::Revision(replayed.revision),
203            vec![Added::V1(99)]
204        ),
205        Err(AppendError::Conflict(_))
206    ));
207    let history = history(&store);
208    let mut restored =
209        replay_with_optional_snapshot::<Counter>(&1, &history, snapshots.load(&1).unwrap())
210            .unwrap();
211    let full = replay_aggregate::<Counter>(&1, &history).unwrap();
212    assert_eq!(restored.aggregate.value, 5);
213    assert_eq!(restored.aggregate.value, full.aggregate.value);
214    assert_eq!(restored.revision, StreamRevision::new(1));
215    assert!(restored.aggregate.pull_events().is_empty());
216    println!("event_sourcing: upcast v1; rejected stale write; snapshot + tail = 5");
217}