Skip to content

Commit a1b30e3

Browse files
committed
more tests...
1 parent 4bf2d83 commit a1b30e3

File tree

1 file changed

+59
-7
lines changed

1 file changed

+59
-7
lines changed

tests/aggregate_not_send_test.rs

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use fmodel_rust::aggregate::{
99
};
1010
use fmodel_rust::decider::Decider;
1111
use fmodel_rust::Identifier;
12+
use tokio::task;
1213

1314
use crate::api::{CreateOrderCommand, OrderCommand, OrderCreatedEvent, OrderEvent, OrderState};
1415
use crate::application::AggregateError;
@@ -149,13 +150,14 @@ fn decider<'a>() -> Decider<'a, OrderCommand, OrderState, OrderEvent> {
149150
async fn es_test_not_send() {
150151
let repository = InMemoryOrderEventRepository::new();
151152

152-
let aggregate = Rc::new(EventSourcedAggregate::new(
153+
let aggregate = EventSourcedAggregate::new(
153154
repository,
154155
decider().map_error(|()| AggregateError::DomainError("Decider error".to_string())),
155-
));
156-
let aggregate2 = Rc::clone(&aggregate);
156+
);
157157

158-
let task1 = async move {
158+
// Does not require `move` and `Rc`
159+
// The futures are created and immediately consumed in the same function where aggregate lives, so the borrow checker can verify that aggregate lives long enough.
160+
let task1 = async {
159161
let command = OrderCommand::Create(CreateOrderCommand {
160162
order_id: 1,
161163
customer_name: "Alice".to_string(),
@@ -165,20 +167,70 @@ async fn es_test_not_send() {
165167
assert!(result.is_ok());
166168
};
167169

168-
let task2 = async move {
170+
let task2 = async {
169171
let command = OrderCommand::Create(CreateOrderCommand {
170172
order_id: 1,
171173
customer_name: "John Doe".to_string(),
172174
items: vec!["Item 1".to_string(), "Item 2".to_string()],
173175
});
174-
let result = aggregate2.handle(&command).await;
176+
let result = aggregate.handle(&command).await;
175177
assert!(result.is_ok());
176178
};
177179

178-
// Run both tasks concurrently on the same thread.
180+
// Run both tasks concurrently on the same thread. Awaited immediately in the same scope
181+
// The futures are created and immediately consumed in the same function where aggregate lives, so the borrow checker can verify that aggregate lives long enough.
179182
tokio::join!(task1, task2);
180183
}
181184

185+
#[tokio::test]
186+
async fn es_test_not_send_with_spawn_local() {
187+
// Create a LocalSet to run !Send futures
188+
let local = task::LocalSet::new();
189+
190+
local
191+
.run_until(async {
192+
let repository = InMemoryOrderEventRepository::new();
193+
let aggregate = Rc::new(EventSourcedAggregate::new(
194+
repository,
195+
decider().map_error(|()| AggregateError::DomainError("Decider error".to_string())),
196+
));
197+
198+
// Clone the Rc for each spawned task
199+
let aggregate1 = Rc::clone(&aggregate);
200+
let aggregate2 = Rc::clone(&aggregate);
201+
202+
// Spawn the first task locally - requires `move` and `Rc`
203+
let handle1 = task::spawn_local(async move {
204+
let command = OrderCommand::Create(CreateOrderCommand {
205+
order_id: 1,
206+
customer_name: "Alice".to_string(),
207+
items: vec!["Item1".to_string()],
208+
});
209+
let result = aggregate1.handle(&command).await;
210+
assert!(result.is_ok());
211+
});
212+
213+
// Spawn the second task locally - also requires `move` and `Rc`
214+
let handle2 = task::spawn_local(async move {
215+
let command = OrderCommand::Create(CreateOrderCommand {
216+
order_id: 2,
217+
customer_name: "Bob".to_string(),
218+
items: vec!["Item2".to_string()],
219+
});
220+
let result = aggregate2.handle(&command).await;
221+
assert!(result.is_ok());
222+
});
223+
224+
// Wait for both tasks to complete
225+
let (result1, result2) = tokio::join!(handle1, handle2);
226+
227+
// Check that both tasks completed successfully
228+
assert!(result1.is_ok());
229+
assert!(result2.is_ok());
230+
})
231+
.await;
232+
}
233+
182234
#[tokio::test]
183235
async fn ss_test_not_send() {
184236
let repository = InMemoryOrderStateRepository::new();

0 commit comments

Comments
 (0)