1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
use crateDomainEvent;
use Future;
use Pin;
/// **English:** Owned cursor identifying progress in a projection's input stream.
///
/// The cursor type and meaning belong to the application. This container performs no ordering,
/// monotonicity, or validity checks and does not store progress by itself.
///
/// **日本語:** プロジェクションの入力ストリームにおける進捗を示す、所有されたカーソルです。
///
/// カーソルの型と意味はアプリケーションが定めます。このコンテナーは順序、単調性、妥当性を
/// 検証せず、単体では進捗を保存しません。
///
/// **English:** Borrow a cursor for inspection, then recover its ownership without cloning.
///
/// **日本語:** カーソルを借用して確認した後、複製せずに所有権を取り出せます。
///
/// ```rust
/// use ddd_toolkit_core::ProjectionCheckpoint;
///
/// let checkpoint = ProjectionCheckpoint::new(String::from("partition-2:17"));
/// assert_eq!(checkpoint.cursor(), "partition-2:17");
/// let cursor = checkpoint.into_cursor();
/// assert_eq!(cursor, "partition-2:17");
/// ```
/// **English:** Successful outcome of [`IdempotentProjection::apply_once`] or
/// [`AsyncIdempotentProjection::apply_once`], distinguishing application from a recognized duplicate.
///
/// **日本語:** [`IdempotentProjection::apply_once`] または [`AsyncIdempotentProjection::apply_once`] の
/// 成功結果であり、適用と認識済みの重複を区別します。
/// **English:** Synchronous persistence port for a projection's checkpoint.
///
/// With no projection identifier parameter, the store instance determines the checkpoint scope.
/// Implementations define replacement, durability, concurrency, panic conditions, and whether
/// saving progress is atomic with read-model updates. This trait supplies no monotonicity check.
///
/// **日本語:** プロジェクションのチェックポイントを同期永続化するポートです。
///
/// プロジェクション識別子の引数がないため、保存対象の範囲はストアのインスタンスが定めます。
/// 置換、永続性、並行処理、パニック条件、読み取りモデル更新との原子的な進捗保存は
/// 実装が定めます。このトレイトは単調性の検証を提供しません。
/// **English:** Opt-in projection contract distinguishing new application from duplicate input.
///
/// This trait is independent of [`crate::Projection`] and [`ProjectionCheckpointStore`].
/// Implementations supply duplicate detection, input identity, read-model changes, and any
/// atomic checkpoint updates or locking. No deduplication algorithm is implemented here;
/// adapters must define failure, retry, and panic behavior for their persistence boundary.
///
/// **日本語:** 新規適用と重複入力を区別する、任意のプロジェクション契約です。
///
/// このトレイトは [`crate::Projection`] と [`ProjectionCheckpointStore`] から独立しています。
/// 重複検出、入力の識別、読み取りモデルの変更、原子的なチェックポイント更新やロックは
/// 実装が提供します。ここでは重複排除アルゴリズムを実装しません。永続化境界における
/// 失敗、再試行、パニック時の挙動はアダプターが定める必要があります。
/// **English:** Checkpoint persistence port returning boxed `Send` futures tied to the store borrow.
///
/// The store instance determines the projection scope, as in [`ProjectionCheckpointStore`].
/// The store must be `Send + Sync`, the cursor `Send + Sync`, and the error `Send`; these bounds
/// do not provide locking, monotonic progress checks, or atomic read-model updates. Implementations
/// define durability, concurrent replacement, partial failures, and panic conditions.
///
/// Dropping a returned future ends that operation's polling, but does not promise rollback or that
/// no I/O occurred. Implementations may perform work before returning a future and must specify
/// cancellation and retry behavior. This trait supplies no executor or transaction coordinator.
///
/// **日本語:** ストアの借用期間に結び付いた、ボックス化された `Send` Future を返す進捗永続化ポートです。
///
/// [`ProjectionCheckpointStore`] と同様に、プロジェクションの範囲はストアのインスタンスが定めます。
/// ストアには `Send + Sync`、カーソルには `Send + Sync`、エラーには `Send` が必要ですが、
/// これらの境界はロック、単調な進捗の検査、読み取りモデルの原子的更新を提供しません。
/// 永続性、並行する置換、部分失敗、パニック条件は実装が定めます。
///
/// 返された Future の破棄はその操作のポーリングを終了しますが、ロールバックや I/O が未実行であることを
/// 保証しません。実装は Future を返す前にも処理でき、キャンセルと再試行の挙動を定める必要があります。
/// このトレイトは実行器やトランザクション調整器を提供しません。
///
/// **English:** Await a write and then read its result; the adapter determines read-after-write consistency.
/// This helper returns `None` if the subsequent load reports no stored checkpoint.
///
/// **日本語:** 書き込みを待ってから結果を読み込みます。書き込み後の読み取り整合性はアダプターが定めます。
/// 後続の読み込みがチェックポイントの不在を報告した場合、このヘルパーは `None` を返します。
///
/// ```rust
/// use ddd_toolkit_core::{AsyncProjectionCheckpointStore, ProjectionCheckpoint};
///
/// async fn save_then_load<S: AsyncProjectionCheckpointStore>(
/// store: &mut S,
/// cursor: S::Cursor,
/// ) -> Result<Option<S::Cursor>, S::Error> {
/// store.save(ProjectionCheckpoint::new(cursor)).await?;
/// Ok(store.load().await?.map(ProjectionCheckpoint::into_cursor))
/// }
/// ```
/// **English:** Asynchronous duplicate-aware projection independent of [`crate::AsyncProjection`]
/// and [`AsyncProjectionCheckpointStore`].
///
/// Implementations provide input identity, duplicate detection, read-model updates, and any atomic
/// checkpoint persistence. The trait itself implements no deduplication. The projection must be `Send`,
/// its event `Sync`, its cursor `Send + Sync`, and its error `Send` for the boxed `Send` future.
/// The projection need not be `Sync`; mutable borrowing prevents overlapping calls on the same value.
///
/// Dropping a future stops polling but does not establish whether changes occurred or were rolled back,
/// even before the first poll: implementations may act during the method call. Adapters must document
/// cancellation, retry, partial-update, and panic behavior at their persistence boundary.
///
/// **日本語:** [`crate::AsyncProjection`] と [`AsyncProjectionCheckpointStore`] から独立した、
/// 重複を区別する非同期プロジェクションです。
///
/// 入力の識別、重複検出、読み取りモデル更新、原子的なチェックポイント永続化は実装が提供します。
/// トレイト自体は重複排除を実装しません。ボックス化された `Send` Future のため、
/// プロジェクションには `Send`、イベントには `Sync`、カーソルには `Send + Sync`、エラーには `Send` が必要です。
/// プロジェクション自体に `Sync` は不要です。同じ値への呼び出しの重複は可変借用が防ぎます。
///
/// Future の破棄はポーリングを止めますが、変更の有無やロールバックを保証しません。
/// メソッド呼び出し中にも処理できるため、初回ポーリング前でも同様です。永続化境界における
/// キャンセル、再試行、部分更新、パニックの挙動はアダプターが文書化する必要があります。