Skip to main content

arts_n_crafts/core/
command_handler.rs

1use crate::core::base_payload::BasePayload;
2use crate::core::command::Command;
3use async_trait::async_trait;
4use serde::Serialize;
5
6#[async_trait]
7pub trait CommandHandler<TPayload, TResult, TError>
8where
9    TPayload: BasePayload + AsRef<str>,
10    TResult: Serialize + Send + Sync + Clone,
11{
12    async fn execute(&self, a_command: Command<TPayload>) -> Result<TResult, TError>;
13}
14
15#[cfg(test)]
16mod command_handler_tests {
17    use super::*;
18    use crate::domain::with_identifier::WithIdentifier;
19    use rstest::rstest;
20    use serde::{Deserialize, Serialize};
21    use strum_macros::AsRefStr;
22    use uuid::Uuid;
23
24    #[allow(dead_code)]
25    #[derive(Clone, Serialize, Deserialize, Debug, PartialEq)]
26    struct User {
27        pub id: String,
28        pub name: String,
29        pub likes: u8,
30    }
31
32    #[derive(Clone, Serialize, Deserialize, Debug, PartialEq, AsRefStr)]
33    enum UserCommandPayload {
34        CreateUser { name: String },
35        LikeUser,
36    }
37
38    struct CreateUserCommandHandler;
39
40    #[async_trait]
41    impl CommandHandler<UserCommandPayload, WithIdentifier, ()> for CreateUserCommandHandler {
42        async fn execute(
43            &self,
44            a_command: Command<UserCommandPayload>,
45        ) -> Result<WithIdentifier, ()> {
46            Ok(WithIdentifier {
47                id: a_command.aggregate_id,
48            })
49        }
50    }
51
52    #[rstest]
53    #[tokio::test]
54    async fn it_should_return_the_id_of_the_created_user() {
55        let an_aggregate_id = Uuid::now_v7().to_string();
56        let a_payload = UserCommandPayload::CreateUser {
57            name: "John Doe".to_string(),
58        };
59        let a_command = Command::create(an_aggregate_id.clone(), a_payload);
60        let a_command_handler = CreateUserCommandHandler {};
61        let a_result = a_command_handler
62            .execute(a_command)
63            .await
64            .expect("failed to execute command");
65        assert_eq!(a_result.id, an_aggregate_id);
66    }
67}