actr_framework/
workload.rs

1//! Workload trait - Executable actor workload
2
3use actr_protocol::ActorResult;
4use async_trait::async_trait;
5
6use crate::{Context, MessageDispatcher};
7
8/// Workload - Executable Actor workload
9///
10/// Represents a complete Actor instance, including:
11/// - Associated dispatcher type (Dispatcher)
12/// - Lifecycle hooks (on_start, on_stop)
13///
14/// # Design Characteristics
15///
16/// - **Bidirectional association**: `Workload::Dispatcher` and `MessageDispatcher::Workload` reference each other
17/// - **Default implementations**: Lifecycle hooks have default no-op implementations, users can optionally override
18/// - **Auto-implementation**: Implemented for wrapper types by code generator
19///
20/// # Code Generation Example
21///
22/// ```rust,ignore
23/// // User-implemented Handler
24/// pub struct MyEchoService { /* ... */ }
25///
26/// impl EchoServiceHandler for MyEchoService {
27///     async fn echo<C: Context>(
28///         &self,
29///         req: EchoRequest,
30///         ctx: &C,
31///     ) -> ActorResult<EchoResponse> {
32///         // Business logic
33///         Ok(EchoResponse { reply: format!("Echo: {}", req.message) })
34///     }
35/// }
36///
37/// // Code-generated Workload wrapper
38/// pub struct EchoServiceWorkload<T: EchoServiceHandler>(pub T);
39///
40/// impl<T: EchoServiceHandler> Workload for EchoServiceWorkload<T> {
41///     type Dispatcher = EchoServiceRouter<T>;
42/// }
43/// ```
44#[async_trait]
45pub trait Workload: Send + Sync + 'static {
46    /// Associated dispatcher type
47    type Dispatcher: MessageDispatcher<Workload = Self>;
48
49    /// Lifecycle hook: Called when Actor starts
50    ///
51    /// # Default Implementation
52    ///
53    /// Default is a no-op, users can optionally override to perform initialization logic.
54    ///
55    /// # Example
56    ///
57    /// ```rust,ignore
58    /// async fn on_start<C: Context>(&self, ctx: &C) -> ActorResult<()> {
59    ///     tracing::info!("Actor {} started", ctx.self_id());
60    ///     // Initialize resources
61    ///     Ok(())
62    /// }
63    /// ```
64    async fn on_start<C: Context>(&self, _ctx: &C) -> ActorResult<()> {
65        Ok(())
66    }
67
68    /// Lifecycle hook: Called when Actor stops
69    ///
70    /// # Default Implementation
71    ///
72    /// Default is a no-op, users can optionally override to perform cleanup logic.
73    ///
74    /// # Example
75    ///
76    /// ```rust,ignore
77    /// async fn on_stop<C: Context>(&self, ctx: &C) -> ActorResult<()> {
78    ///     tracing::info!("Actor {} stopping", ctx.self_id());
79    ///     // Cleanup resources
80    ///     Ok(())
81    /// }
82    /// ```
83    async fn on_stop<C: Context>(&self, _ctx: &C) -> ActorResult<()> {
84        Ok(())
85    }
86}