Skip to main content

openlark_core/trait_system/
executable_builder.rs

1//! ExecutableBuilder trait
2#![allow(async_fn_in_trait)]
3//!
4//! 为“Builder → Request → execute”模式提供统一的 trait 约束,
5//! 以便在各业务 crate 里通过宏批量实现。
6
7use crate::req_option::RequestOption;
8use crate::SDKResult;
9
10/// Builder 可执行抽象
11pub trait ExecutableBuilder<S: Sync, Req, Resp>: Sized {
12    /// 构建请求
13    fn build(self) -> Req;
14
15    /// 执行请求(默认不带 option)
16    async fn execute(self, service: &S) -> SDKResult<Resp>;
17
18    /// 执行请求(可选传入 RequestOption)
19    ///
20    /// 默认实现退化为 `execute`,以兼容仅实现基础 execute 的场景。
21    async fn execute_with_options(self, service: &S, _option: RequestOption) -> SDKResult<Resp> {
22        self.execute(service).await
23    }
24}
25
26#[cfg(test)]
27mod tests {
28    use super::*;
29
30    // 测试用的 mock 类型
31    struct MockService;
32    struct MockRequest {
33        value: String,
34    }
35    struct MockResponse {
36        result: String,
37    }
38
39    struct MockBuilder {
40        value: String,
41    }
42
43    impl ExecutableBuilder<MockService, MockRequest, MockResponse> for MockBuilder {
44        fn build(self) -> MockRequest {
45            MockRequest { value: self.value }
46        }
47
48        async fn execute(self, _service: &MockService) -> SDKResult<MockResponse> {
49            Ok(MockResponse {
50                result: "success".to_string(),
51            })
52        }
53    }
54
55    #[tokio::test]
56    async fn test_executable_builder_build() {
57        let builder = MockBuilder {
58            value: "test".to_string(),
59        };
60        let request = builder.build();
61        assert_eq!(request.value, "test");
62    }
63
64    #[tokio::test]
65    async fn test_executable_builder_execute() {
66        let builder = MockBuilder {
67            value: "test".to_string(),
68        };
69        let service = MockService;
70        let result = builder.execute(&service).await;
71        assert!(result.is_ok());
72        assert_eq!(result.unwrap().result, "success");
73    }
74
75    #[tokio::test]
76    async fn test_executable_builder_execute_with_options() {
77        let builder = MockBuilder {
78            value: "test".to_string(),
79        };
80        let service = MockService;
81        let option = RequestOption::default();
82        let result = builder.execute_with_options(&service, option).await;
83        assert!(result.is_ok());
84    }
85}