### Build Multi-Layer Service with Timeout and Error Mapping (Rust) Source: https://context7.com/cloudwego/motore/llms.txt This Rust code demonstrates building a service using Motore's ServiceBuilder. It adds a timeout and a custom error mapping middleware to a core API handler. The example defines RequestContext, ApiRequest, and ApiResponse structs, and the main function orchestrates the service construction and a sample request. ```rust use motore::builder::ServiceBuilder; use motore::service::service_fn; use motore::BoxError; use std::time::Duration; #[derive(Debug, Clone)] struct RequestContext { request_id: String, user_id: Option, } #[derive(Debug)] struct ApiRequest { endpoint: String, payload: String, } #[derive(Debug)] struct ApiResponse { status: u16, body: String, } impl std::fmt::Display for ApiResponse { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "Status: {}, Body: {}", self.status, self.body) } } // Core business logic handler async fn api_handler( cx: &mut RequestContext, req: ApiRequest ) -> Result { println!("[{}] Processing {} with payload: {}", cx.request_id, req.endpoint, req.payload); // Simulate some processing tokio::time::sleep(Duration::from_millis(50)).await; Ok(ApiResponse { status: 200, body: format!("Success: {}", req.payload.to_uppercase()), }) } #[tokio::main] async fn main() -> Result<(), BoxError> { // Build service with multiple middleware layers let service = ServiceBuilder::new() // Add 30-second timeout .timeout(Some(Duration::from_secs(30))) // Map errors to include context .map_err(|e: BoxError| { eprintln!("Service error: {}", e); BoxError::from(format!("Service failed: {}", e)) }) // Build the final service .service_fn(api_handler); // Create request context let mut context = RequestContext { request_id: "req-12345".to_string(), user_id: Some("user-789".to_string()), }; // Make request let request = ApiRequest { endpoint: "/api/process".to_string(), payload: "hello world".to_string(), }; match service.call(&mut context, request).await { Ok(response) => println!("Success: {}", response), Err(e) => eprintln!("Error: {}", e), } Ok(()) } ``` -------------------------------- ### Create Layer from Closure with layer_fn in Rust Source: https://context7.com/cloudwego/motore/llms.txt Shows how to create a Layer from a closure without defining a new struct using layer_fn(). This example implements a LogService middleware that logs requests before forwarding them to the wrapped service. Reduces boilerplate when building simple middleware that doesn't require struct definition. ```rust use motore::layer::{Layer, layer_fn}; use motore::service::{service_fn, Service}; use std::fmt; use std::convert::Infallible; pub struct LogService { target: &'static str, service: S, } impl Service for LogService where S: Service + Send + Sync, Request: fmt::Debug + Send, Cx: Send, { type Response = S::Response; type Error = S::Error; async fn call(&self, cx: &mut Cx, req: Request) -> Result { println!("req = {:?}, target = {:?}", req, self.target); self.service.call(cx, req).await } } #[derive(Debug)] pub struct MotoreContext; async fn handle(cx: &mut MotoreContext, req: String) -> Result { println!("{:?}, {:?}", cx, req); Ok(req.to_uppercase()) } #[tokio::main] async fn main() { let log_layer = layer_fn(|service| LogService { service, target: "motore-docs", }); let uppercase_service = service_fn(handle); let wrapped_service = log_layer.layer(uppercase_service); let result = wrapped_service.call(&mut MotoreContext, "hello".to_string()).await; } ``` -------------------------------- ### Define Core Service Trait in Rust Source: https://context7.com/cloudwego/motore/llms.txt The `Service` trait is the fundamental abstraction in Motore, representing an asynchronous function that transforms a request into a response or an error. This example shows its definition and a basic HTTP server implementation. ```rust use motore::Service; pub trait Service { type Response; type Error; async fn call(&self, cx: &mut Cx, req: Request) -> Result; } // Example implementation for an HTTP server use http::{Request, Response, StatusCode}; struct HelloWorld; impl Service>> for HelloWorld where Cx: 'static + Send, { type Response = Response>; type Error = http::Error; async fn call( &self, _cx: &mut Cx, _req: Request>, ) -> Result { let body: Vec = "hello, world!\n".as_bytes().to_owned(); let resp = Response::builder() .status(StatusCode::OK) .body(body) .expect("Unable to create `http::Response`"); Ok(resp) } } ``` -------------------------------- ### Create Motore Services from Async Functions in Rust Source: https://context7.com/cloudwego/motore/llms.txt This snippet demonstrates how to convert asynchronous functions or closures into `Service` implementations using `service_fn`. It shows a simple service that prints context and request details. ```rust use motore::service::{service_fn, Service}; use motore::BoxError; #[derive(Debug)] struct MotoreContext; #[derive(Debug)] struct Request; struct Response; async fn handle(cx: &mut MotoreContext, req: Request) -> Result { println!("{:?}, {:?}", cx, req); Ok(Response) } #[tokio::main] async fn main() { let mut service = service_fn(handle); let result = service.call(&mut MotoreContext, Request).await; } ``` -------------------------------- ### Compose Services Declaratively with ServiceBuilder in Rust Source: https://context7.com/cloudwego/motore/llms.txt Demonstrates using ServiceBuilder for declarative composition of multiple middleware layers in a pipeline. ServiceBuilder provides a fluent API to apply layers like timeout and error mapping in sequence. Simplifies construction of complex service stacks with readable, chainable method calls. ```rust use motore::builder::ServiceBuilder; use motore::service::service_fn; use motore::BoxError; use std::time::Duration; #[derive(Debug)] struct Context; async fn my_service(cx: &mut Context, req: String) -> Result { println!("Processing: {}", req); Ok(req.to_uppercase()) } #[tokio::main] async fn main() { let service = ServiceBuilder::new() .timeout(Some(Duration::from_secs(10))) .map_err(|e: BoxError| { eprintln!("Error occurred: {}", e); e }) .service_fn(my_service); let result = service.call(&mut Context, "hello world".to_string()).await; match result { Ok(response) => println!("Response: {}", response), Err(e) => eprintln!("Request failed: {}", e), } } ``` -------------------------------- ### BoxCloneService - Cloneable Type-Erased Services in Rust Source: https://context7.com/cloudwego/motore/llms.txt Creates a boxed service wrapper that implements Clone, enabling service instances to be safely shared and cloned across multiple async tasks. Useful for distributed service handling where the same service logic needs to execute in different tokio spawned tasks. Requires the service to implement the Service trait. ```rust use motore::service::{BoxCloneService, Service, service_fn}; use motore::BoxError; #[derive(Debug, Clone)] struct Context; async fn handler(cx: &mut Context, req: String) -> Result { Ok(format!("Processed: {}", req)) } #[tokio::main] async fn main() { let service = service_fn(handler); let boxed_service: BoxCloneService = BoxCloneService::new(service); // Clone the service to use in multiple tasks let service1 = boxed_service.clone(); let service2 = boxed_service.clone(); let handle1 = tokio::spawn(async move { service1.call(&mut Context, "request1".to_string()).await }); let handle2 = tokio::spawn(async move { service2.call(&mut Context, "request2".to_string()).await }); let (result1, result2) = tokio::join!(handle1, handle2); } ``` -------------------------------- ### Stack Layer - Composing Multiple Layers Sequentially in Rust Source: https://context7.com/cloudwego/motore/llms.txt Combines two Layer instances into a single composite layer that applies transformations in sequence, with the second layer applied first (inner) and first layer applied last (outer). Enables layered middleware composition for complex service pipelines. Both layers must be compatible with the service type. ```rust use motore::layer::{Layer, Stack}; use motore::timeout::TimeoutLayer; use motore::service::service_fn; use std::time::Duration; async fn handler(cx: &mut (), req: String) -> Result { Ok(req.to_uppercase()) } #[tokio::main] async fn main() { let service = service_fn(handler); // Create two layers let timeout_layer1 = TimeoutLayer::new(Some(Duration::from_secs(10))); let timeout_layer2 = TimeoutLayer::new(Some(Duration::from_secs(5))); // Stack them together - timeout_layer2 will be applied first (inner), // then timeout_layer1 (outer) let stacked = Stack::new(timeout_layer1, timeout_layer2); let service_with_timeouts = stacked.layer(service); } ``` -------------------------------- ### Either Type - Conditional Branching Between Services in Rust Source: https://context7.com/cloudwego/motore/llms.txt Enum-based utility combining two different service types into a single composite type for runtime conditional selection. Enables middleware selection logic based on context conditions without requiring generic type parameters. Both service branches must have compatible request/response types. ```rust use motore::utils::Either; use motore::service::{Service, service_fn}; use motore::layer::Layer; #[derive(Debug)] struct Context { use_fast_path: bool, } async fn fast_handler(cx: &mut Context, req: String) -> Result { Ok(format!("FAST: {}", req)) } async fn slow_handler(cx: &mut Context, req: String) -> Result { tokio::time::sleep(std::time::Duration::from_millis(100)).await; Ok(format!("SLOW: {}", req)) } #[tokio::main] async fn main() { let fast_service = service_fn(fast_handler); let slow_service = service_fn(slow_handler); let mut context = Context { use_fast_path: true }; // Use Either to select between services at runtime let selected_service = if context.use_fast_path { Either::A(fast_service) } else { Either::B(slow_service) }; let result = selected_service.call(&mut context, "request".to_string()).await; println!("{:?}", result); } ``` -------------------------------- ### ServiceExt - Response and Error Mapping in Rust Source: https://context7.com/cloudwego/motore/llms.txt Extension trait providing map_response and map_err adapters for transforming service responses and errors at the call site. Enables convenient chaining of response/error transformations without creating intermediate service wrappers. Applies transformations to the output of service calls. ```rust use motore::service::{service_fn, ServiceExt}; use motore::BoxError; #[derive(Debug)] struct Context; #[derive(Debug)] struct CustomError(String); impl std::fmt::Display for CustomError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "CustomError: {}", self.0) } } impl std::error::Error for CustomError {} async fn handler(cx: &mut Context, req: i32) -> Result { if req < 0 { Err("Negative number".into()) } else { Ok(req * 2) } } #[tokio::main] async fn main() { let service = service_fn(handler) .map_response(|response| format!("Result: {}", response)) .map_err(|err| CustomError(err.to_string())); let result = service.call(&mut Context, 42).await; match result { Ok(resp) => println!("{}", resp), Err(e) => eprintln!("{}", e), } } ``` -------------------------------- ### UnaryService - Context-Free Service Trait in Rust Source: https://context7.com/cloudwego/motore/llms.txt Simplified Service trait variant that accepts only a request parameter without requiring a mutable context reference. Useful for stateless operations like calculations or pure transformations. Automatically implemented for Arc and Box types wrapping UnaryService implementers. ```rust use motore::UnaryService; use std::sync::Arc; struct Calculator; impl UnaryService<(i32, i32)> for Calculator { type Response = i32; type Error = std::io::Error; async fn call(&self, req: (i32, i32)) -> Result { let (a, b) = req; Ok(a + b) } } #[tokio::main] async fn main() { let calc = Calculator; let result = calc.call((5, 7)).await; println!("5 + 7 = {:?}", result); // UnaryService is automatically implemented for Arc and Box let arc_calc = Arc::new(Calculator); let result2 = arc_calc.call((10, 20)).await; println!("10 + 20 = {:?}", result2); } ``` -------------------------------- ### Implement Timeout Middleware for Motore Services in Rust Source: https://context7.com/cloudwego/motore/llms.txt This Rust code implements a `Timeout` middleware for Motore services. It wraps an inner service and applies a time limit to its execution using `tokio::select`, returning a timeout error if the operation exceeds the specified duration. ```rust use motore::{Service, BoxError}; use std::time::Duration; pub struct Timeout { inner: S, duration: Option, } impl Timeout { pub const fn new(inner: S, duration: Option) -> Self { Self { inner, duration } } } impl Service for Timeout where Req: 'static + Send, S: Service + 'static + Send + Sync, Cx: 'static + Send, S::Error: Send + Sync + Into, { type Response = S::Response; type Error = BoxError; async fn call(&self, cx: &mut Cx, req: Req) -> Result { match self.duration { Some(duration) => { let sleep = tokio::time::sleep(duration); tokio::select! { r = self.inner.call(cx, req) => { r.map_err(Into::into) }, _ = sleep => Err( std::io::Error::new( std::io::ErrorKind::TimedOut, "service time out" ).into() ), } } None => self.inner.call(cx, req).await.map_err(Into::into), } } } ``` -------------------------------- ### Implement Timeout Middleware Service Source: https://github.com/cloudwego/motore/blob/main/README.md Concrete implementation of a timeout middleware that wraps an inner service and enforces a maximum duration for request processing using tokio::select!. Returns a timeout error if the inner service exceeds the specified duration. Requires Send + Sync bounds for async compatibility. ```rust pub struct Timeout { inner: S, duration: Duration, } impl Service for Timeout where Req: 'static + Send, S: Service + 'static + Send + Sync, Cx: 'static + Send, S::Error: Send + Sync + Into, { type Response = S::Response; type Error = BoxError; async fn call(&self, cx: &mut Cx, req: Req) -> Result { let sleep = tokio::time::sleep(self.duration); tokio::select! { r = self.inner.call(cx, req) => { r.map_err(Into::into) }, _ = sleep => Err(std::io::Error::new(std::io::ErrorKind::TimedOut, "service time out").into()), } } } ``` -------------------------------- ### Implement Layer Trait for Middleware Composition in Rust Source: https://context7.com/cloudwego/motore/llms.txt Demonstrates how to create a custom Layer implementation (TimeoutLayer) that wraps a service with timeout functionality. The Layer trait transforms one service type into another by implementing the layer() method. This pattern enables reusable middleware that can be composed with any compatible service. ```rust use motore::layer::Layer; use motore::timeout::Timeout; use std::time::Duration; #[derive(Clone)] pub struct TimeoutLayer { duration: Option, } impl TimeoutLayer { pub fn new(duration: Option) -> Self { TimeoutLayer { duration } } } impl Layer for TimeoutLayer { type Service = Timeout; fn layer(self, inner: S) -> Self::Service { Timeout::new(inner, self.duration) } } use motore::service::service_fn; async fn my_handler(cx: &mut (), req: String) -> Result { Ok(req.to_uppercase()) } #[tokio::main] async fn main() { let service = service_fn(my_handler); let timeout_layer = TimeoutLayer::new(Some(Duration::from_secs(30))); let service_with_timeout = timeout_layer.layer(service); } ``` -------------------------------- ### Enable Type Erasure with BoxService in Rust Source: https://context7.com/cloudwego/motore/llms.txt Shows how to use BoxService to convert a service into a trait object for dynamic dispatch and storage of heterogeneous service types. BoxService enables runtime polymorphism, allowing different service implementations to be stored in collections or passed between functions without knowing concrete types at compile time. ```rust use motore::service::{BoxService, Service, service_fn}; use motore::BoxError; #[derive(Debug)] struct Context; async fn string_handler(cx: &mut Context, req: String) -> Result { Ok(req.to_uppercase()) } #[tokio::main] async fn main() { let service = service_fn(string_handler); let boxed_service: BoxService = BoxService::new(service); let result = boxed_service.call(&mut Context, "hello".to_string()).await; println!("Result: {:?}", result); } ``` -------------------------------- ### Define Service Trait with Async Call Method Source: https://github.com/cloudwego/motore/blob/main/README.md Core abstraction trait for Motore that defines the contract for services handling requests asynchronously. The Service trait is generic over context (Cx) and Request types, returning a Response or Error. This trait uses AFIT to allow async methods without boxing. ```rust pub trait Service { /// Responses given by the service. type Response; /// Errors produced by the service. type Error; /// Process the request and return the response asynchronously. async fn call(&self, cx: &mut Cx, req: Request) -> Result; } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.