Skip to main content

dispatch_retry/
dispatch_retry.rs

1//! Retry event dispatch after a partial failure; observe duplicate delivery.
2//! 保存後に配信が部分失敗したときの再試行と、重複配信を確認する。
3//!
4//! Run: cargo run -p ddd-toolkit --example dispatch_retry --locked
5//! Read main first, then support/mod.rs for the in-memory adapters.
6//! main → support/mod.rs の順に読み、保存・配信・再試行の流れを追う。
7//! Expected: the restored batch retries event 1, producing deliveries [1, 1, 2].
8//! 結果: 先頭の配信成功は取り消せないため、バッチ再試行で [1, 1, 2] となる。
9mod support;
10
11use ddd_toolkit::{AggregateRoot as _, Repository, dispatch_events};
12use support::{Order, Placed, Publisher, Store};
13
14fn main() {
15    let mut order = Order {
16        id: 1,
17        total: 4200,
18        events: vec![],
19    };
20    order.record_event(Placed(1));
21    order.record_event(Placed(2));
22    let mut store = Store::default();
23    store.save(&order).unwrap();
24    let mut loaded = store.find_by_id(&1).unwrap().unwrap();
25    assert_eq!(loaded.total, 4200);
26    assert!(loaded.pull_events().is_empty());
27
28    // Saving succeeded. A later publisher error cannot undo that save.
29    // 保存と配信は別操作。後の配信失敗で保存がロールバックされるわけではない。
30    let mut publisher = Publisher {
31        fail_at: Some(1),
32        ..Publisher::default()
33    };
34    assert_eq!(
35        dispatch_events(&mut order, &mut publisher),
36        Err("broker down")
37    );
38    assert!(store.exists(&1).unwrap()); // Publication failure does not roll back saving.
39    assert_eq!(order.events, vec![Placed(1), Placed(2)]);
40    // The whole batch was restored, including the event already delivered.
41    // 配信済みイベントも含めたバッチ全体が復元される。受信側には重複対策が必要。
42    publisher.fail_at = None;
43    dispatch_events(&mut order, &mut publisher).unwrap();
44    assert!(order.pull_events().is_empty());
45    assert_eq!(publisher.accepted, vec![Placed(1), Placed(1), Placed(2)]);
46    println!("dispatch_retry: saved total=4200; retry delivered [1, 1, 2]");
47}