actr_framework/dispatcher.rs
1//! MessageDispatcher trait - Message routing and dispatching
2
3use actr_protocol::{ActorResult, RpcEnvelope};
4use async_trait::async_trait;
5use bytes::Bytes;
6
7use crate::{Context, Workload};
8
9/// MessageDispatcher - Message dispatcher interface
10///
11/// Responsible for routing incoming message envelopes to corresponding handler methods.
12///
13/// # Design Characteristics
14///
15/// - **Static routing**: Implemented via compile-time match statements, no runtime lookup overhead
16/// - **Zero-sized type (ZST)**: Router itself occupies no memory
17/// - **Code generation**: Implementation is auto-generated by `actr-cli` codegen
18///
19/// # Code Generation Example
20///
21/// ```rust,ignore
22/// // Generated by code generator
23/// pub struct EchoServiceRouter<T: EchoServiceHandler>(PhantomData<T>);
24///
25/// #[async_trait]
26/// impl<T: EchoServiceHandler> MessageDispatcher for EchoServiceRouter<T> {
27/// type Workload = EchoServiceWorkload<T>;
28///
29/// async fn dispatch<C: Context>(
30/// workload: &Self::Workload,
31/// envelope: RpcEnvelope,
32/// ctx: &C,
33/// ) -> ActorResult<Bytes> {
34/// match envelope.route_key.as_str() {
35/// "echo.EchoService.Echo" => {
36/// let req = EchoRequest::decode(&*envelope.payload)?;
37/// let resp = workload.0.echo(req, ctx).await?;
38/// Ok(resp.encode_to_vec().into())
39/// }
40/// _ => Err(ProtocolError::Actr(ActrError::UnknownRoute {
41/// route_key: envelope.route_key.to_string()
42/// }))
43/// }
44/// }
45/// }
46/// ```
47#[async_trait]
48pub trait MessageDispatcher: Send + Sync + 'static {
49 /// Associated Workload type
50 type Workload: Workload<Dispatcher = Self>;
51
52 /// Dispatch message to corresponding handler method and execute full request-response cycle
53 ///
54 /// # Responsibilities
55 ///
56 /// 1. **Routing**: Select handler method based on `envelope.route_key`
57 /// 2. **Decoding**: Deserialize payload into concrete message type
58 /// 3. **Dispatching**: Invoke workload's business logic method
59 /// 4. **Encoding**: Serialize response into bytes
60 ///
61 /// # Parameters
62 ///
63 /// - `workload`: Workload instance (contains user business logic)
64 /// - `envelope`: Message envelope (contains route_key and payload)
65 /// - `ctx`: Execution context (generic, supports any Context implementation)
66 ///
67 /// # Returns
68 ///
69 /// Returns serialized response bytes
70 async fn dispatch<C: Context>(
71 workload: &Self::Workload,
72 envelope: RpcEnvelope,
73 ctx: &C,
74 ) -> ActorResult<Bytes>;
75}