Skip to content

Commit 3f9c557

Browse files
authored
Merge pull request #9 from fraktalio/feature/upgrade
upgraded fmodel (0.8.1) and pgrx (0.16)
2 parents e243a1d + 556b112 commit 3f9c557

14 files changed

Lines changed: 285 additions & 262 deletions

Cargo.toml

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,23 @@ edition = "2021"
77
crate-type = ["cdylib", "lib"]
88

99
[features]
10-
default = ["pg15"]
11-
pg12 = ["pgrx/pg12", "pgrx-tests/pg12" ]
10+
default = ["pg16"]
1211
pg13 = ["pgrx/pg13", "pgrx-tests/pg13" ]
1312
pg14 = ["pgrx/pg14", "pgrx-tests/pg14" ]
1413
pg15 = ["pgrx/pg15", "pgrx-tests/pg15" ]
1514
pg16 = ["pgrx/pg16", "pgrx-tests/pg16" ]
1615
pg_test = []
1716

1817
[dependencies]
19-
pgrx = "0.12.6"
20-
serde = { version = "1.0.210", features = ["derive"] }
21-
fmodel-rust = "0.7.0"
22-
serde_json = "1.0.131"
23-
uuid = { version = "1.11.0", features = ["serde", "v4"] }
24-
thiserror = "1.0.64"
18+
pgrx = "0.16.0"
19+
serde = { version = "1.0.217", features = ["derive"] }
20+
fmodel-rust = "0.8.1"
21+
serde_json = "1.0.138"
22+
uuid = { version = "1.13.1", features = ["serde", "v4"] }
23+
chrono = {version = "0.4.41", features = ["serde"]}
2524

2625
[dev-dependencies]
27-
pgrx-tests = "0.12.6"
26+
pgrx-tests = "0.16.0"
2827

2928
[profile.dev]
3029
panic = "unwind"
@@ -37,4 +36,4 @@ codegen-units = 1
3736

3837
[[bin]]
3938
name = "pgrx_embed_fmodel_rust_postgres"
40-
path = "./src/bin/pgrx_embed.rs"
39+
path = "./src/bin/pgrx_embed.rs"

src/domain/api.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use crate::framework::domain::api::Identifier;
2-
use pgrx::FromDatum;
32
use pgrx::{PostgresEnum, PostgresType};
43
use serde::{Deserialize, Serialize};
54
use std::fmt;

src/domain/mod.rs

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::domain::order_decider::{order_decider, Order};
66
use crate::domain::order_saga::order_saga;
77
use crate::domain::restaurant_decider::{restaurant_decider, Restaurant};
88
use crate::domain::restaurant_saga::restaurant_saga;
9-
use crate::framework::domain::api::{DeciderType, EventType, Identifier, IsFinal};
9+
use crate::framework::domain::api::{DeciderType, DomainError, EventType, Identifier, IsFinal};
1010
use api::{
1111
OrderCreated, OrderEvent, OrderPlaced, OrderPrepared, RestaurantCreated, RestaurantEvent,
1212
RestaurantMenuChanged,
@@ -29,7 +29,7 @@ pub mod restaurant_view;
2929
/// A convenient type alias for the combined Decider
3030
/// This decider is used to combine the Restaurant and Order deciders into a single decider that can handle both Restaurant and Order commands.
3131
pub type OrderAndRestaurantDecider<'a> =
32-
Decider<'a, Command, (Option<Restaurant>, Option<Order>), Event>;
32+
Decider<'a, Command, (Option<Restaurant>, Option<Order>), Event, DomainError>;
3333

3434
/// A convenient type alias for the combined Saga
3535
/// This saga is used to combine the Restaurant and Order choreography sagas into a single orchestrating saga that can handle both Restaurant and Order events, and produce Restaurant and Order commands as a result.
@@ -39,16 +39,15 @@ pub type OrderAndRestaurantSaga<'a> = Saga<'a, Event, Command>;
3939
pub fn order_restaurant_decider<'a>() -> OrderAndRestaurantDecider<'a> {
4040
restaurant_decider()
4141
.combine(order_decider())
42-
.map_command(&command_to_sum)
43-
.map_event(&event_to_sum, &sum_to_event)
42+
.map_command(command_to_sum)
43+
.map_event(event_to_sum, sum_to_event)
4444
}
4545

46-
/// Combined Saga, combining the Restaurant and Order choreography sagas into a single orchestrating saga that can handle both Restaurant and Order events, and produce Restaurant and Order commands as a result.
46+
/// Merged Saga, merging the Restaurant and Order choreography sagas into a single orchestrating saga that can handle all events, and produce Restaurant and Order commands as a result.
4747
pub fn order_restaurant_saga<'a>() -> OrderAndRestaurantSaga<'a> {
4848
restaurant_saga()
49-
.combine(order_saga())
50-
.map_action_result(&event_to_sum2)
51-
.map_action(&sum_to_command)
49+
.merge(order_saga())
50+
.map_action(sum_to_command)
5251
}
5352

5453
/// All possible commands in the order&restaurant domains
@@ -138,6 +137,18 @@ impl DeciderType for Event {
138137
}
139138
}
140139

140+
impl DeciderType for Command {
141+
fn decider_type(&self) -> String {
142+
match self {
143+
Command::PlaceOrder(_) => "Restaurant".to_string(),
144+
Command::CreateOrder(_) => "Order".to_string(),
145+
Command::MarkOrderAsPrepared(_) => "Order".to_string(),
146+
Command::CreateRestaurant(_) => "Restaurant".to_string(),
147+
Command::ChangeRestaurantMenu(_) => "Restaurant".to_string(),
148+
}
149+
}
150+
}
151+
141152
/// Mapper functions to convert between the `FModel` Sum type and the more appropriate domain specific Command/API type
142153
/// This is necessary because the `FModel` Sum type is used to combine the Restaurant and Order deciders into a single decider that can handle both Restaurant and Order commands.
143154
/// We don't want to expose the `FModel` Sum type to the API, so we need to convert between the `FModel` Sum type and the more appropriate Command/API type.
@@ -163,16 +174,6 @@ pub fn event_to_sum(event: &Event) -> Sum<RestaurantEvent, OrderEvent> {
163174
}
164175
}
165176

166-
pub fn event_to_sum2(event: &Event) -> Sum<OrderEvent, RestaurantEvent> {
167-
match event {
168-
Event::RestaurantCreated(e) => Sum::Second(RestaurantEvent::Created(e.to_owned())),
169-
Event::RestaurantMenuChanged(e) => Sum::Second(RestaurantEvent::MenuChanged(e.to_owned())),
170-
Event::OrderPlaced(e) => Sum::Second(RestaurantEvent::OrderPlaced(e.to_owned())),
171-
Event::OrderCreated(e) => Sum::First(OrderEvent::Created(e.to_owned())),
172-
Event::OrderPrepared(e) => Sum::First(OrderEvent::Prepared(e.to_owned())),
173-
}
174-
}
175-
176177
pub fn sum_to_command(command: &Sum<OrderCommand, RestaurantCommand>) -> Command {
177178
match command {
178179
Sum::Second(c) => match c {

src/domain/order_decider.rs

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
use fmodel_rust::decider::Decider;
2-
use pgrx::error;
32

4-
use crate::domain::api::{
5-
OrderCommand, OrderCreated, OrderEvent, OrderId, OrderLineItem, OrderPrepared, OrderStatus,
6-
RestaurantId,
3+
use crate::{
4+
domain::api::{
5+
OrderCommand, OrderCreated, OrderEvent, OrderId, OrderLineItem, OrderPrepared, OrderStatus,
6+
RestaurantId,
7+
},
8+
framework::domain::api::DomainError,
79
};
810

911
/// The state of the Order is represented by this struct. It belongs to the Domain layer.
@@ -16,7 +18,7 @@ pub struct Order {
1618
}
1719

1820
/// A convenient type alias for the Order decider
19-
pub type OrderDecider<'a> = Decider<'a, OrderCommand, Option<Order>, OrderEvent>;
21+
pub type OrderDecider<'a> = Decider<'a, OrderCommand, Option<Order>, OrderEvent, DomainError>;
2022

2123
/// Decider is a datatype/struct that represents the main decision-making algorithm. It belongs to the Domain layer.
2224
pub fn order_decider<'a>() -> OrderDecider<'a> {
@@ -26,29 +28,33 @@ pub fn order_decider<'a>() -> OrderDecider<'a> {
2628
decide: Box::new(|command, state| match command {
2729
OrderCommand::Create(command) => {
2830
if state.is_some() {
29-
error!("Failed to create the Order. Order already exists!")
31+
Err(DomainError::OrderNotCreated(
32+
"Failed to create the Order. Order already exists!".to_string(),
33+
))
3034
} else {
31-
vec![OrderEvent::Created(OrderCreated {
35+
Ok(vec![OrderEvent::Created(OrderCreated {
3236
identifier: command.identifier.to_owned(),
3337
restaurant_identifier: command.restaurant_identifier.to_owned(),
3438
status: OrderStatus::Created,
3539
line_items: command.line_items.to_owned(),
3640
r#final: false,
37-
})]
41+
})])
3842
}
3943
}
4044
OrderCommand::MarkAsPrepared(command) => {
4145
if state
4246
.clone()
4347
.is_some_and(|s| OrderStatus::Created == s.status)
4448
{
45-
vec![OrderEvent::Prepared(OrderPrepared {
49+
Ok(vec![OrderEvent::Prepared(OrderPrepared {
4650
identifier: command.identifier.to_owned(),
4751
status: OrderStatus::Prepared,
4852
r#final: true,
49-
})]
53+
})])
5054
} else {
51-
error!("Failed to mark the order as prepared. Order does not exist or is not in the correct state!");
55+
Err(DomainError::OrderNotPrepared(
56+
"Failed to mark the order as prepared. Order does not exist or is not in the correct state!".to_string(),
57+
))
5258
}
5359
}
5460
}),
@@ -68,7 +74,6 @@ pub fn order_decider<'a>() -> OrderDecider<'a> {
6874
line_items: s.line_items,
6975
}),
7076
}),
71-
7277
// The initial state of the decider
7378
initial_state: Box::new(|| None),
7479
}

src/domain/order_saga.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,35 @@
11
use fmodel_rust::saga::Saga;
22

3-
use crate::domain::api::{CreateOrder, OrderCommand, RestaurantEvent};
3+
use crate::domain::{
4+
api::{CreateOrder, OrderCommand},
5+
Event,
6+
};
47

58
/// A convenient type alias for the Order choreography saga
6-
type OrderSaga<'a> = Saga<'a, RestaurantEvent, OrderCommand>;
9+
type OrderSaga<'a> = Saga<'a, Event, OrderCommand>;
710

811
/// The Order choreography saga - represents the central point of control deciding what to execute next.
912
/// It is a function that takes an event and returns a list of commands.
1013
pub fn order_saga<'a>() -> OrderSaga<'a> {
1114
Saga {
1215
react: Box::new(|event| match event {
13-
RestaurantEvent::OrderPlaced(event) => {
16+
Event::RestaurantCreated(..) => {
17+
vec![]
18+
}
19+
Event::OrderPrepared(..) => {
20+
vec![]
21+
}
22+
Event::OrderPlaced(event) => {
1423
vec![OrderCommand::Create(CreateOrder {
1524
identifier: event.order_identifier.to_owned(),
1625
restaurant_identifier: event.identifier.to_owned(),
1726
line_items: event.line_items.to_owned(),
1827
})]
1928
}
20-
RestaurantEvent::Created(..) => {
29+
Event::RestaurantMenuChanged(..) => {
2130
vec![]
2231
}
23-
RestaurantEvent::MenuChanged(..) => {
32+
Event::OrderCreated(..) => {
2433
vec![]
2534
}
2635
}),

src/domain/restaurant_decider.rs

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
use fmodel_rust::decider::Decider;
2-
use pgrx::error;
32

4-
use crate::domain::api::{
5-
OrderPlaced, RestaurantCommand, RestaurantCreated, RestaurantEvent, RestaurantId,
6-
RestaurantMenu, RestaurantMenuChanged, RestaurantName,
3+
use crate::{
4+
domain::api::{
5+
OrderPlaced, RestaurantCommand, RestaurantCreated, RestaurantEvent, RestaurantId,
6+
RestaurantMenu, RestaurantMenuChanged, RestaurantName,
7+
},
8+
framework::domain::api::DomainError,
79
};
810

911
/// The state of the Restaurant is represented by this struct. It belongs to the Domain layer.
@@ -16,7 +18,7 @@ pub struct Restaurant {
1618

1719
/// A convenient type alias for the Restaurant decider
1820
pub type RestaurantDecider<'a> =
19-
Decider<'a, RestaurantCommand, Option<Restaurant>, RestaurantEvent>;
21+
Decider<'a, RestaurantCommand, Option<Restaurant>, RestaurantEvent, DomainError>;
2022

2123
/// Decider is a datatype/struct that represents the main decision-making algorithm. It belongs to the Domain layer.
2224
pub fn restaurant_decider<'a>() -> RestaurantDecider<'a> {
@@ -26,37 +28,43 @@ pub fn restaurant_decider<'a>() -> RestaurantDecider<'a> {
2628
decide: Box::new(|command, state| match command {
2729
RestaurantCommand::CreateRestaurant(command) => {
2830
if state.is_some() {
29-
error!("Failed to create the Restaurant. Restaurant already exists!");
31+
Err(DomainError::RestaurantNotCreated(
32+
"Failed to create the Restaurant. Restaurant already exists!".to_string(),
33+
))
3034
} else {
31-
vec![RestaurantEvent::Created(RestaurantCreated {
35+
Ok(vec![RestaurantEvent::Created(RestaurantCreated {
3236
identifier: command.identifier.to_owned(),
3337
name: command.name.to_owned(),
3438
menu: command.menu.to_owned(),
3539
r#final: false,
36-
})]
40+
})])
3741
}
3842
}
3943
RestaurantCommand::ChangeMenu(command) => {
4044
if state.is_some() {
41-
vec![RestaurantEvent::MenuChanged(RestaurantMenuChanged {
45+
Ok(vec![RestaurantEvent::MenuChanged(RestaurantMenuChanged {
4246
identifier: command.identifier.to_owned(),
4347
menu: command.menu.to_owned(),
4448
r#final: false,
45-
})]
49+
})])
4650
} else {
47-
error!("Failed to change the menu. Restaurant does not exist!");
51+
Err(DomainError::RestaurantMenuNotChanged(
52+
"Failed to change the menu. Restaurant does not exist!".to_string(),
53+
))
4854
}
4955
}
5056
RestaurantCommand::PlaceOrder(command) => {
5157
if state.is_some() {
52-
vec![RestaurantEvent::OrderPlaced(OrderPlaced {
58+
Ok(vec![RestaurantEvent::OrderPlaced(OrderPlaced {
5359
identifier: command.identifier.to_owned(),
5460
order_identifier: command.order_identifier.to_owned(),
5561
line_items: command.line_items.to_owned(),
5662
r#final: false,
57-
})]
63+
})])
5864
} else {
59-
error!("Failed to place the order. Restaurant does not exist!");
65+
Err(DomainError::OrderNotPlaced(
66+
"Failed to place the order. Restaurant does not exist!".to_string(),
67+
))
6068
}
6169
}
6270
}),

src/domain/restaurant_saga.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,29 @@
11
use fmodel_rust::saga::Saga;
22

3-
use crate::domain::api::{OrderEvent, RestaurantCommand};
3+
use crate::domain::{api::RestaurantCommand, Event};
44

55
/// A convenient type alias for the Restaurant choreography saga
6-
type RestaurantSaga<'a> = Saga<'a, OrderEvent, RestaurantCommand>;
6+
type RestaurantSaga<'a> = Saga<'a, Event, RestaurantCommand>;
77

88
/// The Restaurant choreography saga - represents the central point of control deciding what to execute next.
99
/// It is a function that takes an event and returns a list of commands.
1010
/// This Saga is not doing much ;)
1111
pub fn restaurant_saga<'a>() -> RestaurantSaga<'a> {
1212
Saga {
1313
react: Box::new(|_event| match _event {
14-
OrderEvent::Created(..) => {
14+
Event::RestaurantCreated(..) => {
1515
vec![]
1616
}
17-
OrderEvent::Prepared(..) => {
17+
Event::OrderPrepared(..) => {
18+
vec![]
19+
}
20+
Event::OrderPlaced(..) => {
21+
vec![]
22+
}
23+
Event::RestaurantMenuChanged(..) => {
24+
vec![]
25+
}
26+
Event::OrderCreated(..) => {
1827
vec![]
1928
}
2029
}),

0 commit comments

Comments
 (0)