Learn
Application
Commands

Commands

Commands describe an intent to change the system's state. They have side-effects and interact with the write model. They are used to encapsulate application logic and are often used to implement use cases. They don't return a value, but they can fail.

  • Intent-Driven: Commands represent a clear intention to change the system's state.
  • Action-Oriented: Unlike queries, which request data, commands perform actions that modify state.
  • Task-Specific: Each command is designed for a specific operation, ensuring clarity and purpose.

Creating Commands

It is recommended to create a command for each application use case.

application/src/command.rs
pub enum Command {
    AddTask { name: String },
    RemoveTask { index: usize },
    CompleteTask { index: usize },
}

Implementing Commands

application/src/command.rs
#[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(())
    }
}