Skip to main content

appcore_core/
handler.rs

1// =============================================================================
2//        #######
3//     ###       ###     F: handler.rs
4//    ##   ## ##   ##    P: AppCore-Runtime
5//         ## ##
6//                       C: 2026/05/29 20:47:35 by dnettoRaw
7//    ##   ## ##   ##    U: 2026/06/04 11:51:29 by dnettoRaw
8//      ###########      S: 0.6.0
9// =============================================================================
10
11//! Command handler contracts without execution engine concerns.
12
13use crate::context::RuntimeContext;
14use crate::envelope::{CommandEnvelope, EventEnvelope};
15use crate::error::RuntimeResult;
16use crate::ids::CommandName;
17
18/// Structured command handling result.
19#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
20pub struct CommandResult {
21    accepted: bool,
22    events: Vec<EventEnvelope>,
23    message: Option<String>,
24}
25
26impl CommandResult {
27    /// Creates an accepted result with emitted fact events.
28    pub fn accepted(events: Vec<EventEnvelope>) -> Self {
29        Self {
30            accepted: true,
31            events,
32            message: None,
33        }
34    }
35
36    /// Creates a controlled rejection without emitted events.
37    pub fn rejected(message: impl Into<String>) -> Self {
38        Self {
39            accepted: false,
40            events: Vec::new(),
41            message: Some(message.into()),
42        }
43    }
44
45    /// Reports whether the command was accepted.
46    pub fn is_accepted(&self) -> bool {
47        self.accepted
48    }
49
50    /// Returns events emitted by an accepted command.
51    pub fn events(&self) -> &[EventEnvelope] {
52        &self.events
53    }
54
55    /// Returns the controlled rejection message, when present.
56    pub fn message(&self) -> Option<&str> {
57        self.message.as_deref()
58    }
59}
60
61/// Command handler contract.
62pub trait CommandHandler: Send + Sync {
63    /// Returns the command name handled by this implementation.
64    fn command_name(&self) -> CommandName;
65
66    /// Handles one validated command in a read-only Runtime context.
67    fn handle(
68        &self,
69        command: &CommandEnvelope,
70        context: &dyn RuntimeContext,
71    ) -> RuntimeResult<CommandResult>;
72}
73
74#[cfg(test)]
75#[path = "handler_tests.rs"]
76mod tests;