durable_execution_sdk/traits.rs
1//! Trait aliases for common bounds in the AWS Durable Execution SDK.
2//!
3//! This module provides trait aliases that simplify common trait bound combinations
4//! used throughout the SDK. These aliases make function signatures more readable
5//! and maintainable while preserving full type safety.
6//!
7//! # Overview
8//!
9//! The SDK frequently requires types to implement multiple traits for serialization,
10//! thread safety, and lifetime requirements. Instead of repeating these bounds
11//! everywhere, this module provides convenient trait aliases.
12//!
13//! # Available Trait Aliases
14//!
15//! - [`DurableValue`]: For values that can be durably stored and retrieved
16//! - [`StepError`]: The boxed error type returned by step functions
17//! - [`StepFuture`]: Type alias for the future returned by async step functions
18//!
19//! # Example
20//!
21//! ```rust
22//! use durable_execution_sdk::traits::DurableValue;
23//!
24//! // Using DurableValue in a generic function
25//! fn process_value<T: DurableValue>(value: T) -> String {
26//! // T is guaranteed to be Serialize + DeserializeOwned + Send
27//! serde_json::to_string(&value).unwrap_or_default()
28//! }
29//! ```
30
31use serde::{de::DeserializeOwned, Serialize};
32
33/// The error type returned by step functions.
34pub type StepError = Box<dyn std::error::Error + Send + Sync>;
35
36/// Type alias for the future returned by async step functions.
37///
38/// This simplifies signatures that would otherwise need:
39/// ```text
40/// Fut: Future<Output = Result<T, Box<dyn std::error::Error + Send + Sync>>> + Send
41/// ```
42pub type StepFuture<T> =
43 std::pin::Pin<Box<dyn std::future::Future<Output = Result<T, StepError>> + Send>>;
44
45/// Trait alias for values that can be durably stored and retrieved.
46///
47/// This trait combines the necessary bounds for serialization, deserialization,
48/// and thread-safe sending across async boundaries. Any type implementing
49/// `DurableValue` can be:
50///
51/// - Serialized to JSON for checkpointing
52/// - Deserialized from JSON during replay
53/// - Safely sent between threads
54///
55/// # Equivalent Bounds
56///
57/// `DurableValue` is equivalent to:
58/// ```text
59/// Serialize + DeserializeOwned + Send
60/// ```
61///
62/// # Blanket Implementation
63///
64/// This trait is automatically implemented for all types that satisfy the bounds.
65/// You don't need to implement it manually.
66///
67/// # Example
68///
69/// ```rust
70/// use durable_execution_sdk::traits::DurableValue;
71/// use serde::{Deserialize, Serialize};
72///
73/// // This type automatically implements DurableValue
74/// #[derive(Debug, Clone, Serialize, Deserialize)]
75/// struct OrderResult {
76/// order_id: String,
77/// status: String,
78/// total: f64,
79/// }
80///
81/// // Use in generic functions
82/// fn store_result<T: DurableValue>(result: T) {
83/// let json = serde_json::to_string(&result).unwrap();
84/// println!("Storing: {}", json);
85/// }
86///
87/// let result = OrderResult {
88/// order_id: "ORD-123".to_string(),
89/// status: "completed".to_string(),
90/// total: 99.99,
91/// };
92/// store_result(result);
93/// ```
94pub trait DurableValue: Serialize + DeserializeOwned + Send {}
95
96/// Blanket implementation for all types meeting the bounds.
97impl<T> DurableValue for T where T: Serialize + DeserializeOwned + Send {}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102 use serde::{Deserialize, Serialize};
103
104 // Test that common types implement DurableValue
105 #[test]
106 fn test_durable_value_primitives() {
107 fn assert_durable_value<T: DurableValue>() {}
108
109 assert_durable_value::<i32>();
110 assert_durable_value::<i64>();
111 assert_durable_value::<u32>();
112 assert_durable_value::<u64>();
113 assert_durable_value::<f32>();
114 assert_durable_value::<f64>();
115 assert_durable_value::<bool>();
116 assert_durable_value::<String>();
117 assert_durable_value::<()>();
118 }
119
120 #[test]
121 fn test_durable_value_collections() {
122 fn assert_durable_value<T: DurableValue>() {}
123
124 assert_durable_value::<Vec<i32>>();
125 assert_durable_value::<Vec<String>>();
126 assert_durable_value::<std::collections::HashMap<String, i32>>();
127 assert_durable_value::<Option<String>>();
128 }
129
130 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
131 struct TestStruct {
132 id: String,
133 value: i32,
134 }
135
136 #[test]
137 fn test_durable_value_custom_struct() {
138 fn assert_durable_value<T: DurableValue>() {}
139 assert_durable_value::<TestStruct>();
140 }
141
142 #[test]
143 fn test_durable_value_serialization() {
144 fn serialize_value<T: DurableValue>(value: &T) -> String {
145 serde_json::to_string(value).unwrap()
146 }
147
148 fn deserialize_value<T: DurableValue>(json: &str) -> T {
149 serde_json::from_str(json).unwrap()
150 }
151
152 let original = TestStruct {
153 id: "test-123".to_string(),
154 value: 42,
155 };
156
157 let json = serialize_value(&original);
158 let restored: TestStruct = deserialize_value(&json);
159
160 assert_eq!(original, restored);
161 }
162}