Skip to content

Commit

Permalink
Added merge function for the Saga, next to the combine
Browse files Browse the repository at this point in the history
  • Loading branch information
idugalic committed Jan 26, 2025
1 parent 06b9ff0 commit e927684
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 0 deletions.
19 changes: 19 additions & 0 deletions src/saga.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,25 @@ impl<'a, AR, A> Saga<'a, AR, A> {

Saga { react: new_react }
}

/// Merges two sagas into one.
/// Creates a new instance of a Saga by merging two sagas of type `AR`, `A` and `AR`, `A2` into a new saga of type `AR`, `Sum<A, A2>`
pub fn merge<A2>(self, saga2: Saga<'a, AR, A2>) -> Saga<'a, AR, Sum<A2, A>> {
let new_react = Box::new(move |ar: &AR| {
let a: Vec<Sum<A2, A>> = (self.react)(ar)
.into_iter()
.map(|a: A| Sum::Second(a))
.collect();
let a2: Vec<Sum<A2, A>> = (saga2.react)(ar)
.into_iter()
.map(|a2: A2| Sum::First(a2))
.collect();

a.into_iter().chain(a2).collect()
});

Saga { react: new_react }
}
}

/// Formalizes the `Action Computation` algorithm for the `saga` to handle events/action_results, and produce new commands/actions.
Expand Down
65 changes: 65 additions & 0 deletions tests/saga_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,30 @@ fn order_saga<'a>() -> Saga<'a, OrderEvent, ShipmentCommand> {
}
}

fn order_saga_2<'a>() -> Saga<'a, Event, ShipmentCommand> {
Saga {
react: Box::new(|event| match event {
Event::OrderCreated(evt) => {
vec![ShipmentCommand::Create(CreateShipmentCommand {
shipment_id: evt.order_id,
order_id: evt.order_id,
customer_name: evt.customer_name.to_owned(),
items: evt.items.to_owned(),
})]
}
Event::OrderUpdated(_) => {
vec![]
}
Event::OrderCancelled(_) => {
vec![]
}
Event::ShipmentCreated(_) => {
vec![]
}
}),
}
}

fn shipment_saga<'a>() -> Saga<'a, ShipmentEvent, OrderCommand> {
Saga {
react: Box::new(|event| match event {
Expand All @@ -43,15 +67,44 @@ fn shipment_saga<'a>() -> Saga<'a, ShipmentEvent, OrderCommand> {
}
}

fn shipment_saga_2<'a>() -> Saga<'a, Event, OrderCommand> {
Saga {
react: Box::new(|event| match event {
Event::ShipmentCreated(evt) => {
vec![OrderCommand::Update(UpdateOrderCommand {
order_id: evt.order_id,
new_items: evt.items.to_owned(),
})]
}

Event::OrderCreated(_) => {
vec![]
}
Event::OrderUpdated(_) => {
vec![]
}
Event::OrderCancelled(_) => {
vec![]
}
}),
}
}

#[test]
fn test() {
let order_saga: Saga<OrderEvent, ShipmentCommand> = order_saga();
let order_saga2: Saga<OrderEvent, ShipmentCommand> = crate::order_saga();
let order_saga_2: Saga<Event, ShipmentCommand> = crate::order_saga_2();
let shipment_saga: Saga<ShipmentEvent, OrderCommand> = shipment_saga();
let shipment_saga_2: Saga<Event, OrderCommand> = crate::shipment_saga_2();
let combined_saga = order_saga2
.combine(shipment_saga)
.map_action(&sum_to_command)
.map_action_result(&event_from_sum);
let merged_saga = order_saga_2
.merge(shipment_saga_2)
.map_action(&sum_to_command);

let order_created_event = OrderEvent::Created(OrderCreatedEvent {
order_id: 1,
customer_name: "John Doe".to_string(),
Expand All @@ -72,6 +125,7 @@ fn test() {
customer_name: "John Doe".to_string(),
items: vec!["Item 1".to_string(), "Item 2".to_string()],
});

let combined_commands = combined_saga.compute_new_actions(&order_created_event2);
assert_eq!(
combined_commands,
Expand All @@ -82,4 +136,15 @@ fn test() {
items: vec!["Item 1".to_string(), "Item 2".to_string()],
})]
);

let merged_commands = merged_saga.compute_new_actions(&order_created_event2);
assert_eq!(
merged_commands,
[Command::ShipmentCreate(CreateShipmentCommand {
shipment_id: 1,
order_id: 1,
customer_name: "John Doe".to_string(),
items: vec!["Item 1".to_string(), "Item 2".to_string()],
})]
);
}

0 comments on commit e927684

Please sign in to comment.