ddd_toolkit_core/dispatch.rs
1use crate::event_restoration_guard::EventRestorationGuard;
2use crate::{AggregateRoot, DomainEventPublisher};
3
4/// **English:**<br>
5/// Publishes the events currently held by `aggregate` through `publisher`.
6///
7/// Events are passed to [`DomainEventPublisher::publish`] in the order returned by
8/// [`AggregateRoot::pull_events`]. If a publish operation returns an error, all events pulled at
9/// the start of this call are recorded back into the aggregate before that error is returned.
10/// This restoration does not undo publishes that already succeeded. If every publish succeeds,
11/// the events are removed from the aggregate and the function returns `Ok(())`.
12///
13/// The function may panic if the aggregate's [`AggregateRoot::pull_events`] or
14/// [`AggregateRoot::record_event`] implementation panics. It does not impose additional
15/// synchronization; the aggregate and publisher must be mutably borrowed by the caller for the
16/// duration of the dispatch.
17///
18/// **日本語:**<br>
19/// `aggregate` が現在保持しているイベントを `publisher` 経由で発行します。
20///
21/// イベントは [`AggregateRoot::pull_events`] が返した順序で [`DomainEventPublisher::publish`]
22/// に渡されます。発行処理がエラーを返すと、この呼び出しの開始時に取り出したすべての
23/// イベントを集約へ記録し直してから、そのエラーを返します。すでに成功した発行処理は
24/// 取り消されません。すべての発行に成功した場合、イベントは集約から削除され、`Ok(())`
25/// を返します。
26///
27/// 集約の [`AggregateRoot::pull_events`] または [`AggregateRoot::record_event`] の実装が
28/// パニックすると、この関数もパニックする可能性があります。この関数は追加の同期を
29/// 行わないため、呼び出し側はディスパッチ中、集約とパブリッシャーを可変借用します。
30pub fn dispatch_events<A, P>(aggregate: &mut A, publisher: &mut P) -> Result<(), P::Error>
31where
32 A: AggregateRoot,
33 P: DomainEventPublisher<Event = A::Event>,
34{
35 let snapshot = aggregate.pull_events();
36 let mut guard = EventRestorationGuard::new(aggregate, snapshot);
37
38 for event in guard.events() {
39 publisher.publish(event)?;
40 }
41
42 guard.commit();
43 Ok(())
44}