Skip to content

Commit e6dd6a5

Browse files
committed
Tests added, and API simplified
1 parent 865f905 commit e6dd6a5

10 files changed

+267
-174
lines changed

README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ Confused? Run `cargo pgrx help`
5050
## The structure of the project
5151

5252
The project is structured as follows:
53-
- `lib.rs` file contains the entry point of the package/crate.
53+
- [lib.rs](src/lib.rs) file contains the entry point of the package/crate.
5454
- `framework` module contains the generalized and parametrized implementation of infrastructure and application layers.
5555
- `domain` module contains the domain model. It is the core and pure domain logic of the application!!!
5656
- `application` module contains the application layer. It is the orchestration of the domain model and the infrastructure layer (empty, as it is implemented in the `framework` module).
@@ -59,6 +59,12 @@ The project is structured as follows:
5959
The framework module offers a generic implementation of the infrastructure and application layers, which can be reused across multiple domain models.
6060
Your focus should be on the `domain` module, where you can implement your unique domain model. We have provided a demo domain model of a `restaurant/order management system` to get you started.
6161

62+
## Check the tests
63+
The project contains a set of tests that demonstrate how to use the domain model and the framework.
64+
You can find them in the root: [lib.rs](src/lib.rs).
65+
66+
You will find a command handler function only, which can handle all the commands of the system! Simple!
67+
6268
## References and further reading
6369
- [pgrx](https://github.com/pgcentralfoundation/pgrx)
6470
- [fmodel-rust](https://github.com/fraktalio/fmodel-rust)

src/domain/api.rs

Lines changed: 0 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -166,11 +166,8 @@ pub struct MarkOrderAsPrepared {
166166
#[serde(tag = "type")]
167167
pub enum RestaurantEvent {
168168
Created(RestaurantCreated),
169-
NotCreated(RestaurantNotCreated),
170169
MenuChanged(RestaurantMenuChanged),
171-
MenuNotChanged(RestaurantMenuNotChanged),
172170
OrderPlaced(OrderPlaced),
173-
OrderNotPlaced(OrderNotPlaced),
174171
}
175172

176173
/// Fact/Event that a restaurant was created
@@ -182,16 +179,6 @@ pub struct RestaurantCreated {
182179
pub r#final: bool,
183180
}
184181

185-
/// Fact/Event that a restaurant was not created (with reason)
186-
#[derive(PostgresType, Serialize, Deserialize, Debug, PartialEq, Clone, Eq)]
187-
pub struct RestaurantNotCreated {
188-
pub identifier: RestaurantId,
189-
pub name: RestaurantName,
190-
pub menu: RestaurantMenu,
191-
pub reason: Reason,
192-
pub r#final: bool,
193-
}
194-
195182
/// Fact/Event that a restaurant's menu was changed
196183
#[derive(PostgresType, Serialize, Deserialize, Debug, PartialEq, Clone, Eq)]
197184
pub struct RestaurantMenuChanged {
@@ -200,15 +187,6 @@ pub struct RestaurantMenuChanged {
200187
pub r#final: bool,
201188
}
202189

203-
/// Fact/Event that a restaurant's menu was not changed (with reason)
204-
#[derive(PostgresType, Serialize, Deserialize, Debug, PartialEq, Clone, Eq)]
205-
pub struct RestaurantMenuNotChanged {
206-
pub identifier: RestaurantId,
207-
pub menu: RestaurantMenu,
208-
pub reason: Reason,
209-
pub r#final: bool,
210-
}
211-
212190
/// Fact/Event that an order was placed
213191
#[derive(PostgresType, Serialize, Deserialize, Debug, PartialEq, Clone, Eq)]
214192
pub struct OrderPlaced {
@@ -218,26 +196,14 @@ pub struct OrderPlaced {
218196
pub r#final: bool,
219197
}
220198

221-
/// Fact/Event that an order was not placed (with reason)
222-
#[derive(PostgresType, Serialize, Deserialize, Debug, PartialEq, Clone, Eq)]
223-
pub struct OrderNotPlaced {
224-
pub identifier: RestaurantId,
225-
pub order_identifier: OrderId,
226-
pub line_items: Vec<OrderLineItem>,
227-
pub reason: Reason,
228-
pub r#final: bool,
229-
}
230-
231199
// #### ORDER ####
232200

233201
/// All possible event variants that could be used to update an order
234202
#[derive(PostgresType, Serialize, Deserialize, Debug, PartialEq, Clone)]
235203
#[serde(tag = "type")]
236204
pub enum OrderEvent {
237205
Created(OrderCreated),
238-
NotCreated(OrderNotCreated),
239206
Prepared(OrderPrepared),
240-
NotPrepared(OrderNotPrepared),
241207
}
242208

243209
/// Fact/Event that an order was created
@@ -250,28 +216,10 @@ pub struct OrderCreated {
250216
pub r#final: bool,
251217
}
252218

253-
/// Fact/Event that an order was not created (with reason)
254-
#[derive(PostgresType, Serialize, Deserialize, Debug, PartialEq, Clone, Eq)]
255-
pub struct OrderNotCreated {
256-
pub identifier: OrderId,
257-
pub restaurant_identifier: RestaurantId,
258-
pub line_items: Vec<OrderLineItem>,
259-
pub reason: Reason,
260-
pub r#final: bool,
261-
}
262-
263219
/// Fact/Event that an order was prepared
264220
#[derive(PostgresType, Serialize, Deserialize, Debug, PartialEq, Clone, Eq)]
265221
pub struct OrderPrepared {
266222
pub identifier: OrderId,
267223
pub status: OrderStatus,
268224
pub r#final: bool,
269225
}
270-
271-
/// Fact/Event that an order was not prepared (with reason)
272-
#[derive(PostgresType, Serialize, Deserialize, Debug, PartialEq, Clone, Eq)]
273-
pub struct OrderNotPrepared {
274-
pub identifier: OrderId,
275-
pub reason: Reason,
276-
pub r#final: bool,
277-
}

src/domain/mod.rs

Lines changed: 1 addition & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use crate::domain::api::{
22
ChangeRestaurantMenu, CreateOrder, CreateRestaurant, MarkOrderAsPrepared, OrderCommand,
3-
OrderNotCreated, OrderNotPlaced, OrderNotPrepared, PlaceOrder, RestaurantCommand,
4-
RestaurantMenuNotChanged, RestaurantNotCreated,
3+
PlaceOrder, RestaurantCommand,
54
};
65
use crate::domain::order_decider::{order_decider, Order};
76
use crate::domain::order_saga::order_saga;
@@ -81,15 +80,10 @@ impl Identifier for Command {
8180
#[serde(tag = "type")]
8281
pub enum Event {
8382
RestaurantCreated(RestaurantCreated),
84-
RestaurantNotCreated(RestaurantNotCreated),
8583
RestaurantMenuChanged(RestaurantMenuChanged),
86-
RestaurantMenuNotChanged(RestaurantMenuNotChanged),
8784
OrderPlaced(OrderPlaced),
88-
OrderNotPlaced(OrderNotPlaced),
8985
OrderCreated(OrderCreated),
90-
OrderNotCreated(OrderNotCreated),
9186
OrderPrepared(OrderPrepared),
92-
OrderNotPrepared(OrderNotPrepared),
9387
}
9488

9589
/// Implement the Identifier trait for the Event enum
@@ -101,11 +95,6 @@ impl Identifier for Event {
10195
Event::OrderPlaced(evt) => evt.identifier.0,
10296
Event::OrderCreated(evt) => evt.identifier.0,
10397
Event::OrderPrepared(evt) => evt.identifier.0,
104-
Event::RestaurantNotCreated(evt) => evt.identifier.0,
105-
Event::RestaurantMenuNotChanged(evt) => evt.identifier.0,
106-
Event::OrderNotPlaced(evt) => evt.identifier.0,
107-
Event::OrderNotCreated(evt) => evt.identifier.0,
108-
Event::OrderNotPrepared(evt) => evt.identifier.0,
10998
}
11099
}
111100
}
@@ -119,11 +108,6 @@ impl EventType for Event {
119108
Event::OrderPlaced(_) => "OrderPlaced".to_string(),
120109
Event::OrderCreated(_) => "OrderCreated".to_string(),
121110
Event::OrderPrepared(_) => "OrderPrepared".to_string(),
122-
Event::RestaurantNotCreated(_) => "RestaurantNotCreated".to_string(),
123-
Event::RestaurantMenuNotChanged(_) => "RestaurantMenuNotChanged".to_string(),
124-
Event::OrderNotPlaced(_) => "OrderNotPlaced".to_string(),
125-
Event::OrderNotCreated(_) => "OrderNotCreated".to_string(),
126-
Event::OrderNotPrepared(_) => "OrderNotPrepared".to_string(),
127111
}
128112
}
129113
}
@@ -137,11 +121,6 @@ impl IsFinal for Event {
137121
Event::OrderPlaced(evt) => evt.r#final,
138122
Event::OrderCreated(evt) => evt.r#final,
139123
Event::OrderPrepared(evt) => evt.r#final,
140-
Event::RestaurantNotCreated(evt) => evt.r#final,
141-
Event::RestaurantMenuNotChanged(evt) => evt.r#final,
142-
Event::OrderNotPlaced(evt) => evt.r#final,
143-
Event::OrderNotCreated(evt) => evt.r#final,
144-
Event::OrderNotPrepared(evt) => evt.r#final,
145124
}
146125
}
147126
}
@@ -153,13 +132,8 @@ impl DeciderType for Event {
153132
Event::RestaurantCreated(_) => "Restaurant".to_string(),
154133
Event::RestaurantMenuChanged(_) => "Restaurant".to_string(),
155134
Event::OrderPlaced(_) => "Restaurant".to_string(),
156-
Event::RestaurantNotCreated(_) => "Restaurant".to_string(),
157-
Event::RestaurantMenuNotChanged(_) => "Restaurant".to_string(),
158-
Event::OrderNotPlaced(_) => "Restaurant".to_string(),
159135
Event::OrderCreated(_) => "Order".to_string(),
160136
Event::OrderPrepared(_) => "Order".to_string(),
161-
Event::OrderNotCreated(_) => "Order".to_string(),
162-
Event::OrderNotPrepared(_) => "Order".to_string(),
163137
}
164138
}
165139
}
@@ -182,34 +156,20 @@ pub fn command_to_sum(command: &Command) -> Sum<RestaurantCommand, OrderCommand>
182156
pub fn event_to_sum(event: &Event) -> Sum<RestaurantEvent, OrderEvent> {
183157
match event {
184158
Event::RestaurantCreated(e) => Sum::First(RestaurantEvent::Created(e.to_owned())),
185-
Event::RestaurantNotCreated(e) => Sum::First(RestaurantEvent::NotCreated(e.to_owned())),
186159
Event::RestaurantMenuChanged(e) => Sum::First(RestaurantEvent::MenuChanged(e.to_owned())),
187-
Event::RestaurantMenuNotChanged(e) => {
188-
Sum::First(RestaurantEvent::MenuNotChanged(e.to_owned()))
189-
}
190160
Event::OrderPlaced(e) => Sum::First(RestaurantEvent::OrderPlaced(e.to_owned())),
191-
Event::OrderNotPlaced(e) => Sum::First(RestaurantEvent::OrderNotPlaced(e.to_owned())),
192161
Event::OrderCreated(e) => Sum::Second(OrderEvent::Created(e.to_owned())),
193-
Event::OrderNotCreated(e) => Sum::Second(OrderEvent::NotCreated(e.to_owned())),
194162
Event::OrderPrepared(e) => Sum::Second(OrderEvent::Prepared(e.to_owned())),
195-
Event::OrderNotPrepared(e) => Sum::Second(OrderEvent::NotPrepared(e.to_owned())),
196163
}
197164
}
198165

199166
pub fn event_to_sum2(event: &Event) -> Sum<OrderEvent, RestaurantEvent> {
200167
match event {
201168
Event::RestaurantCreated(e) => Sum::Second(RestaurantEvent::Created(e.to_owned())),
202-
Event::RestaurantNotCreated(e) => Sum::Second(RestaurantEvent::NotCreated(e.to_owned())),
203169
Event::RestaurantMenuChanged(e) => Sum::Second(RestaurantEvent::MenuChanged(e.to_owned())),
204-
Event::RestaurantMenuNotChanged(e) => {
205-
Sum::Second(RestaurantEvent::MenuNotChanged(e.to_owned()))
206-
}
207170
Event::OrderPlaced(e) => Sum::Second(RestaurantEvent::OrderPlaced(e.to_owned())),
208-
Event::OrderNotPlaced(e) => Sum::Second(RestaurantEvent::OrderNotPlaced(e.to_owned())),
209171
Event::OrderCreated(e) => Sum::First(OrderEvent::Created(e.to_owned())),
210-
Event::OrderNotCreated(e) => Sum::First(OrderEvent::NotCreated(e.to_owned())),
211172
Event::OrderPrepared(e) => Sum::First(OrderEvent::Prepared(e.to_owned())),
212-
Event::OrderNotPrepared(e) => Sum::First(OrderEvent::NotPrepared(e.to_owned())),
213173
}
214174
}
215175

@@ -231,17 +191,12 @@ pub fn sum_to_event(event: &Sum<RestaurantEvent, OrderEvent>) -> Event {
231191
match event {
232192
Sum::First(e) => match e {
233193
RestaurantEvent::Created(e) => Event::RestaurantCreated(e.to_owned()),
234-
RestaurantEvent::NotCreated(e) => Event::RestaurantNotCreated(e.to_owned()),
235194
RestaurantEvent::MenuChanged(e) => Event::RestaurantMenuChanged(e.to_owned()),
236-
RestaurantEvent::MenuNotChanged(e) => Event::RestaurantMenuNotChanged(e.to_owned()),
237195
RestaurantEvent::OrderPlaced(e) => Event::OrderPlaced(e.to_owned()),
238-
RestaurantEvent::OrderNotPlaced(e) => Event::OrderNotPlaced(e.to_owned()),
239196
},
240197
Sum::Second(e) => match e {
241198
OrderEvent::Created(e) => Event::OrderCreated(e.to_owned()),
242-
OrderEvent::NotCreated(e) => Event::OrderNotCreated(e.to_owned()),
243199
OrderEvent::Prepared(e) => Event::OrderPrepared(e.to_owned()),
244-
OrderEvent::NotPrepared(e) => Event::OrderNotPrepared(e.to_owned()),
245200
},
246201
}
247202
}

src/domain/order_decider.rs

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
use fmodel_rust::decider::Decider;
2+
use pgrx::error;
23

34
use crate::domain::api::{
4-
OrderCommand, OrderCreated, OrderEvent, OrderId, OrderLineItem, OrderNotCreated,
5-
OrderNotPrepared, OrderPrepared, OrderStatus, Reason, RestaurantId,
5+
OrderCommand, OrderCreated, OrderEvent, OrderId, OrderLineItem, OrderPrepared, OrderStatus,
6+
Reason, RestaurantId,
67
};
78

89
/// The state of the Order is represented by this struct. It belongs to the Domain layer.
@@ -25,13 +26,7 @@ pub fn order_decider<'a>() -> OrderDecider<'a> {
2526
decide: Box::new(|command, state| match command {
2627
OrderCommand::Create(command) => {
2728
if state.is_some() {
28-
vec![OrderEvent::NotCreated(OrderNotCreated {
29-
identifier: command.identifier.to_owned(),
30-
restaurant_identifier: command.restaurant_identifier.to_owned(),
31-
line_items: command.line_items.to_owned(),
32-
reason: Reason("Order already exists".to_string()),
33-
r#final: false,
34-
})]
29+
error!("Failed to create the Order. Order already exists!")
3530
} else {
3631
vec![OrderEvent::Created(OrderCreated {
3732
identifier: command.identifier.to_owned(),
@@ -53,11 +48,7 @@ pub fn order_decider<'a>() -> OrderDecider<'a> {
5348
r#final: true,
5449
})]
5550
} else {
56-
vec![OrderEvent::NotPrepared(OrderNotPrepared {
57-
identifier: command.identifier.to_owned(),
58-
reason: Reason("Order in the wrong status previously".to_string()),
59-
r#final: false,
60-
})]
51+
error!("Failed to mark the order as prepared. Order does not exist or is not in the correct state!");
6152
}
6253
}
6354
}),
@@ -70,16 +61,12 @@ pub fn order_decider<'a>() -> OrderDecider<'a> {
7061
status: event.status.to_owned(),
7162
line_items: event.line_items.to_owned(),
7263
}),
73-
// On error event we choose NOT TO change the state of the Order, for example.
74-
OrderEvent::NotCreated(..) => state.clone(),
7564
OrderEvent::Prepared(event) => state.clone().map(|s| Order {
7665
identifier: event.identifier.to_owned(),
7766
restaurant_identifier: s.restaurant_identifier,
7867
status: event.status.to_owned(),
7968
line_items: s.line_items,
8069
}),
81-
// On error event we choose NOT TO change the state of the Order, for example.
82-
OrderEvent::NotPrepared(..) => state.clone(),
8370
}),
8471

8572
// The initial state of the decider

src/domain/order_saga.rs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,6 @@ pub fn order_saga<'a>() -> OrderSaga<'a> {
1717
line_items: event.line_items.to_owned(),
1818
})]
1919
}
20-
RestaurantEvent::OrderNotPlaced(..) => {
21-
vec![]
22-
}
23-
RestaurantEvent::NotCreated(..) => {
24-
vec![]
25-
}
26-
RestaurantEvent::MenuNotChanged(..) => {
27-
vec![]
28-
}
2920
RestaurantEvent::Created(..) => {
3021
vec![]
3122
}

src/domain/order_view.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,13 @@ pub fn order_view<'a>() -> OrderView<'a> {
2727
status: event.status.to_owned(),
2828
line_items: event.line_items.to_owned(),
2929
}),
30-
// On error event we choose NOT TO change the state of the Order, for example.
31-
OrderEvent::NotCreated(..) => state.clone(),
3230

3331
OrderEvent::Prepared(event) => state.clone().map(|s| OrderViewState {
3432
identifier: event.identifier.to_owned(),
3533
restaurant_identifier: s.restaurant_identifier,
3634
status: event.status.to_owned(),
3735
line_items: s.line_items,
3836
}),
39-
// On error event we choose NOT TO change the state of the Order, for example.
40-
OrderEvent::NotPrepared(..) => state.clone(),
4137
}),
4238

4339
// The initial state of the decider

0 commit comments

Comments
 (0)