ddd_toolkit_core/
async_dispatch.rs1use crate::{AggregateRoot, AsyncDomainEventPublisher};
2use std::future::Future;
3use std::pin::Pin;
4
5struct EventRestorationGuard<'a, A: AggregateRoot> {
6 aggregate: &'a mut A,
7 snapshot: Option<Vec<A::Event>>,
8}
9
10impl<'a, A: AggregateRoot> EventRestorationGuard<'a, A> {
11 fn new(aggregate: &'a mut A, snapshot: Vec<A::Event>) -> Self {
12 Self {
13 aggregate,
14 snapshot: Some(snapshot),
15 }
16 }
17
18 fn events(&self) -> impl Iterator<Item = &A::Event> {
19 self.snapshot.as_deref().into_iter().flatten()
20 }
21
22 fn commit(&mut self) {
23 self.snapshot.take();
24 }
25}
26
27impl<A: AggregateRoot> Drop for EventRestorationGuard<'_, A> {
28 fn drop(&mut self) {
29 if let Some(snapshot) = self.snapshot.take() {
30 for event in snapshot {
31 self.aggregate.record_event(event);
32 }
33 }
34 }
35}
36
37pub fn dispatch_events_async<'a, A, P>(
47 aggregate: &'a mut A,
48 publisher: &'a mut P,
49) -> Pin<Box<dyn Future<Output = Result<(), P::Error>> + Send + 'a>>
50where
51 A: AggregateRoot + Send + 'a,
52 A::Event: Send + Sync + 'a,
53 P: AsyncDomainEventPublisher<Event = A::Event> + Send + 'a,
54 P::Error: 'a,
55{
56 Box::pin(async move {
57 let snapshot = aggregate.pull_events();
58 let mut guard = EventRestorationGuard::new(aggregate, snapshot);
59
60 for event in guard.events() {
61 publisher.publish(event).await?
62 }
63
64 guard.commit();
65 Ok(())
66 })
67}