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}