Skip to main content

ddd_toolkit_core/
event_versioning.rs

1use std::marker::PhantomData;
2
3/// **English:** Event name and schema version supplied by the application.
4/// Fields are public and unvalidated: an empty name or version zero is accepted. Equality compares
5/// both fields. This value supplies no registry, serialization format, or migration dispatch.
6///
7/// **日本語:** アプリケーションが指定するイベント名とスキーマバージョンです。
8/// フィールドは公開され検証されません。空の名前やバージョンゼロも許容します。等値比較は
9/// 両フィールドを比較します。レジストリー、直列化形式、移行の振り分けは提供しません。
10#[derive(Clone, Copy, Debug, Eq, PartialEq)]
11pub struct EventIdentity {
12    /// **English:** Static event name; uniqueness and naming conventions are application-defined.
13    ///
14    /// **日本語:** 静的なイベント名です。一意性と命名規則はアプリケーションが定めます。
15    pub name: &'static str,
16
17    /// **English:** Numeric schema version, with no enforced starting value or ordering policy.
18    ///
19    /// **日本語:** 数値のスキーマバージョンです。開始値や順序の方針は強制しません。
20    pub version: u32,
21}
22
23/// **English:** Type-level event identity independent of any particular event instance.
24/// No [`crate::DomainEvent`] bound is required, and the trait does not validate the returned identity.
25///
26/// **日本語:** 個々のイベントインスタンスとは独立した、型単位のイベント識別情報です。
27/// [`crate::DomainEvent`] の境界は要求せず、返された識別情報も検証しません。
28pub trait VersionedEvent {
29    /// **English:** Returns the name and schema version chosen for this event type.
30    /// Implementations define the mapping; no instance data is passed to this function.
31    ///
32    /// **日本語:** このイベント型に選んだ名前とスキーマバージョンを返します。
33    /// 対応付けは実装が定め、この関数にはインスタンスのデータを渡しません。
34    fn identity() -> EventIdentity;
35}
36
37/// **English:** Fallible owned transformation from an event representation back to the same Rust type.
38/// Versions can be represented inside that type, but checking or advancing them is the
39/// implementation's responsibility. No [`VersionedEvent`] bound or automatic version selection is used.
40///
41/// **日本語:** イベント表現を所有して受け取り、同じ Rust 型へ変換する、失敗し得る操作です。
42/// 型の内部にバージョンを表現できますが、その検査や更新は実装が担います。
43/// [`VersionedEvent`] の境界や自動的なバージョン選択は用いません。
44pub trait EventUpcaster<Event> {
45    /// **English:** Transformation failure forwarded unchanged by [`UpcasterChain::apply`].
46    ///
47    /// **日本語:** [`UpcasterChain::apply`] が変更せず伝播する変換の失敗です。
48    type Error;
49
50    /// **English:** Consumes `event`, returning its transformed representation or an error.
51    /// The input is not returned on error; side effects and panic conditions depend on the upcaster.
52    ///
53    /// **日本語:** `event` を消費し、変換後の表現またはエラーを返します。
54    /// エラー時に入力は返しません。副作用とパニックの条件は変換器に依存します。
55    fn upcast(&self, event: Event) -> Result<Event, Self::Error>;
56}
57
58/// **English:** Insertion-ordered sequence of upcasters of a single concrete type.
59/// Each stage consumes the preceding output. The chain does not select stages by event identity,
60/// sort versions, or restore an event after failure. Use an enum or another common upcaster type
61/// when stages need different behaviors. It stores no event value and adds no locking.
62///
63/// **日本語:** 同じ具体型の変換器を追加順に保持する列です。
64/// 各段階は直前の出力を消費します。イベント識別情報による段階の選択、バージョンの並べ替え、
65/// 失敗後のイベント復元はしません。異なる動作の段階には列挙型などの共通の変換器型を用います。
66/// イベント値は保持せず、ロックも追加しません。
67///
68/// **English:** Add stages explicitly; each successful result becomes the next input.
69///
70/// **日本語:** 段階を明示的に追加すると、各段階の成功結果が次の入力になります。
71///
72/// ```rust
73/// use ddd_toolkit_core::{EventUpcaster, UpcasterChain};
74///
75/// struct Append(&'static str);
76/// impl EventUpcaster<String> for Append {
77///     type Error = std::convert::Infallible;
78///     fn upcast(&self, mut event: String) -> Result<String, Self::Error> {
79///         event.push_str(self.0);
80///         Ok(event)
81///     }
82/// }
83/// let mut chain = UpcasterChain::new();
84/// chain.push(Append("-v2"));
85/// chain.push(Append("-v3"));
86/// assert_eq!(chain.apply(String::from("v1")).unwrap(), "v1-v2-v3");
87/// assert_eq!(chain.len(), 2);
88/// ```
89pub struct UpcasterChain<Event, Upcaster> {
90    upcasters: Vec<Upcaster>,
91    marker: PhantomData<fn() -> Event>,
92}
93
94impl<Event, Upcaster> Default for UpcasterChain<Event, Upcaster> {
95    fn default() -> Self {
96        Self::new()
97    }
98}
99
100impl<Event, Upcaster> UpcasterChain<Event, Upcaster> {
101    /// **English:** Creates an empty chain, also used by [`Default::default`].
102    /// Applying an empty chain returns the input unchanged.
103    ///
104    /// **日本語:** [`Default::default`] でも使う空の列を作ります。
105    /// 空の列を適用すると、入力を変更せず返します。
106    pub fn new() -> Self {
107        Self {
108            upcasters: Vec::new(),
109            marker: PhantomData,
110        }
111    }
112
113    /// **English:** Appends `upcaster` as the last stage without inspecting its version or running it.
114    ///
115    /// **日本語:** バージョンを調べたり実行したりせず、`upcaster` を最後の段階に追加します。
116    pub fn push(&mut self, upcaster: Upcaster) {
117        self.upcasters.push(upcaster);
118    }
119
120    /// **English:** Returns the number of stored stages, not the number of supported event versions.
121    ///
122    /// **日本語:** 対応するイベントバージョン数ではなく、保持する段階数を返します。
123    pub fn len(&self) -> usize {
124        self.upcasters.len()
125    }
126
127    /// **English:** Returns `true` when no upcasters have been added.
128    ///
129    /// **日本語:** 変換器を一つも追加していない場合に `true` を返します。
130    pub fn is_empty(&self) -> bool {
131        self.upcasters.is_empty()
132    }
133
134    /// **English:** Runs all stages in insertion order and returns the final owned event.
135    /// The first error stops evaluation and is returned unchanged; later stages are not called.
136    /// Earlier side effects are not rolled back. An empty chain returns `Ok(event)`.
137    /// Panics from a stage propagate, and the chain itself remains stored for future calls.
138    ///
139    /// **日本語:** 全段階を追加順に実行し、最後の所有されたイベントを返します。
140    /// 最初のエラーで評価を止め、変更せず返します。後続の段階は呼び出しません。
141    /// 先行する副作用は取り消しません。空の列は `Ok(event)` を返します。
142    /// 段階のパニックは伝播し、列自体は後続の呼び出しにも使えるよう保持されます。
143    pub fn apply(&self, mut event: Event) -> Result<Event, Upcaster::Error>
144    where
145        Upcaster: EventUpcaster<Event>,
146    {
147        for upcaster in &self.upcasters {
148            event = upcaster.upcast(event)?;
149        }
150        Ok(event)
151    }
152}