-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
States and projections #1
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,55 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
use crate::port::{TodoListRepository, TodoListStore}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
use domain::todolist_message::TodoListMessage; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
use framework::*; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
use serde::Deserialize; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#[derive(Deserialize)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
pub enum Command { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
AddTask { name: String }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
RemoveTask { index: usize }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
CompleteTask { index: usize }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+7
to
+11
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggestion: Consider adding a docstring to the
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#[derive(Debug, Error)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
pub enum CommandError { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#[error("Task name cannot be empty")] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
TaskNameCannotBeEmpty, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+13
to
+17
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggestion: Consider adding a docstring to the
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
impl TryInto<TodoListMessage> for &Command { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
type Error = CommandError; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
fn try_into(self) -> Result<TodoListMessage, Self::Error> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Ok(match self { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Command::AddTask { name } => TodoListMessage::AddTask( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
name.clone() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.try_into() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.map_err(|_| CommandError::TaskNameCannotBeEmpty)?, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Command::RemoveTask { index } => TodoListMessage::RemoveTask((*index).into()), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Command::CompleteTask { index } => TodoListMessage::CompleteTask((*index).into()), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+19
to
+33
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggestion: Consider adding a docstring to the
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#[async_trait] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
impl<R> Execute<R> for Command | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
where | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
R: TodoListRepository + TodoListStore + Send + Sync, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
async fn execute(&self, runtime: &R) -> AnyResult<()> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let message = self.try_into()?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Pull the current state and apply the message | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let todolist = TodoListStore::pull(runtime).await?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let new_events = todolist.send(&message)?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
TodoListStore::push(runtime, &new_events).await?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Save the projection | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let mut projection = TodoListRepository::fetch(runtime).await?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
projection.apply(&new_events); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
TodoListRepository::save(runtime, &projection).await?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Ok(()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+36
to
+54
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggestion: Consider adding a docstring to the
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
pub mod commands; | ||
pub mod ports; | ||
pub mod projections; | ||
pub mod queries; | ||
pub mod command; | ||
pub mod port; | ||
pub mod projection; | ||
pub mod query; |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -1,5 +1,5 @@ | ||||||
pub use crate::projections::TodoListProjection; | ||||||
pub use domain::{todolist::TodoList, todolist_event::TodoListEvent}; | ||||||
pub use crate::projection::TodoListProjection; | ||||||
pub use domain::{todolist_event::TodoListEvent, todolist_state::TodoList}; | ||||||
use framework::*; | ||||||
|
||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggestion: Consider using a more specific import for the
Suggested change
|
||||||
#[async_trait] | ||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,34 @@ | ||||||||||||||||||||||||
use domain::todolist_event::TodoListEvent; | ||||||||||||||||||||||||
use framework::*; | ||||||||||||||||||||||||
use serde::{Deserialize, Serialize}; | ||||||||||||||||||||||||
use std::collections::HashMap; | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
#[derive(Clone, Default, Debug, Serialize, Deserialize)] | ||||||||||||||||||||||||
pub struct TodoListProjection { | ||||||||||||||||||||||||
pub in_progress: HashMap<usize, String>, | ||||||||||||||||||||||||
pub completed: HashMap<usize, String>, | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
Comment on lines
+6
to
+10
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggestion: Consider adding a docstring to the
Suggested change
|
||||||||||||||||||||||||
|
||||||||||||||||||||||||
impl Projection for TodoListProjection { | ||||||||||||||||||||||||
type Event = TodoListEvent; | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
fn apply(&mut self, events: &[Self::Event]) { | ||||||||||||||||||||||||
for event in events { | ||||||||||||||||||||||||
match event { | ||||||||||||||||||||||||
TodoListEvent::TaskAdded(index, name) => { | ||||||||||||||||||||||||
self.in_progress | ||||||||||||||||||||||||
.insert((*index).into(), name.clone().into()); | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
TodoListEvent::TaskCompleted(index) => { | ||||||||||||||||||||||||
self.completed.insert( | ||||||||||||||||||||||||
(*index).into(), | ||||||||||||||||||||||||
self.in_progress.remove(&(*index).into()).unwrap(), | ||||||||||||||||||||||||
); | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
TodoListEvent::TaskRemoved(index) => { | ||||||||||||||||||||||||
self.in_progress.remove(&(*index).into()); | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
### Retrieve all todolist | ||
GET http://localhost:3000/todolist HTTP/1.1 | ||
|
||
### Create a new task | ||
POST http://localhost:3000/todolist HTTP/1.1 | ||
content-type: application/json | ||
|
||
{ | ||
"AddTask": { | ||
"name": "Some task" | ||
} | ||
} | ||
|
||
### Complete a task | ||
POST http://localhost:3000/todolist HTTP/1.1 | ||
content-type: application/json | ||
|
||
{ | ||
"CompleteTask": { | ||
"index": 0 | ||
} | ||
} | ||
|
||
### Remove a task | ||
POST http://localhost:3000/todolist HTTP/1.1 | ||
content-type: application/json | ||
|
||
{ | ||
"RemoveTask": { | ||
"index": 0 | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: Consider using a more specific import for the
framework::*
module instead of importing all its contents. [best practice]