Skip to main content

serverless_fn/
client.rs

1//! Client runtime for invoking serverless functions.
2//!
3//! Handles initiating remote calls to serverless functions.
4
5use std::collections::HashMap;
6
7use crate::{
8    config::{Config, DeployStrategy},
9    error::ServerlessError,
10    serializer::{Serializer, get_default_serializer},
11    transport::{Transport, get_default_transport},
12};
13
14/// Client for invoking serverless functions.
15pub struct Client {
16    config: Config,
17    transport: Box<dyn Transport>,
18    serializer: Serializer,
19}
20
21impl Client {
22    /// Creates a new client with default configuration.
23    ///
24    /// # Errors
25    ///
26    /// Returns an error if the client cannot be created.
27    pub fn new() -> Result<Self, ServerlessError> {
28        let config = Config::from_env();
29        let serializer = get_default_serializer();
30        let transport = get_default_transport(config.timeout, config.retries);
31
32        Ok(Self {
33            config,
34            transport,
35            serializer,
36        })
37    }
38
39    /// Creates a new client with custom configuration.
40    ///
41    /// # Errors
42    ///
43    /// Returns an error if the client cannot be created.
44    pub fn with_config(config: Config) -> Result<Self, ServerlessError> {
45        let serializer = get_default_serializer();
46        let transport = get_default_transport(config.timeout, config.retries);
47
48        Ok(Self {
49            config,
50            transport,
51            serializer,
52        })
53    }
54
55    /// Calls a serverless function by name with the given payload.
56    ///
57    /// # Arguments
58    ///
59    /// * `function_name` - Name of the function to call
60    /// * `payload` - Serialized function arguments
61    /// * `headers` - Optional HTTP headers for the request
62    ///
63    /// # Errors
64    ///
65    /// Returns an error if the function call fails.
66    pub async fn call_function(
67        &self,
68        function_name: &str,
69        payload: Vec<u8>,
70        headers: Option<HashMap<String, String>>,
71    ) -> Result<Vec<u8>, ServerlessError> {
72        match self.config.deploy_strategy() {
73            DeployStrategy::Remote => self.transport.call(function_name, payload, headers).await,
74            DeployStrategy::Local => Err(ServerlessError::Generic(
75                "Local call mode should not reach client runtime".into(),
76            )),
77            DeployStrategy::Mock => Ok(b"{}".to_vec()),
78        }
79    }
80
81    /// Returns a reference to the underlying transport.
82    #[must_use]
83    pub fn transport(&self) -> &dyn Transport {
84        self.transport.as_ref()
85    }
86
87    /// Returns a reference to the underlying serializer.
88    #[must_use]
89    pub fn serializer(&self) -> &Serializer {
90        &self.serializer
91    }
92}
93
94impl Default for Client {
95    fn default() -> Self {
96        Self::new().expect("Failed to create default Client")
97    }
98}
99
100#[cfg(test)]
101mod tests {
102    use super::*;
103
104    #[test]
105    fn test_client_default() {
106        let client = Client::default();
107        assert_eq!(client.config.base_url, "http://localhost:3000");
108    }
109}