Skip to main content

usage_example/
usage_example.rs

1//! Example usage of the serverless function library
2
3use serde::{Deserialize, Serialize};
4use serverless_fn::server::Server;
5use serverless_fn::{ServerlessError, serverless};
6
7// Example serverless function
8#[serverless]
9pub async fn read_posts(how_many: usize, query: String) -> Result<Vec<Post>, ServerlessError> {
10    // Simulate reading posts from a database
11    let posts = (0..how_many)
12        .map(|i| Post {
13            id: i as u64,
14            title: format!("{query} {}", i),
15            content: format!("Content of post {}", i),
16        })
17        .collect();
18
19    Ok(posts)
20}
21
22// Another example function
23#[serverless]
24pub async fn create_post(title: String, content: String) -> Result<Post, ServerlessError> {
25    let post = Post {
26        id: 1,
27        title,
28        content,
29    };
30
31    Ok(post)
32}
33
34#[derive(Serialize, Deserialize, Debug)]
35pub struct Post {
36    pub id: u64,
37    pub title: String,
38    pub content: String,
39}
40
41// Main function demonstrating usage
42#[tokio::main]
43async fn main() -> Result<(), ServerlessError> {
44    // Check command line arguments to decide whether to run as server or client
45    let args: Vec<String> = std::env::args().collect();
46
47    if args.len() > 1 && args[1] == "--serve" {
48        // Run as server
49        run_server().await?;
50    } else {
51        // Run as client
52        run_client().await?;
53    }
54
55    Ok(())
56}
57
58async fn run_client() -> Result<(), ServerlessError> {
59    // Initialize logging
60    let config = serverless_fn::config::Config::from_env();
61    config.init_logging();
62
63    // Initialize telemetry if enabled
64    serverless_fn::telemetry::init_telemetry();
65
66    // Call the serverless function as if it were a regular function
67    let posts = read_posts(3, "my search".to_string()).await?;
68    println!("Retrieved {} posts", posts.len());
69
70    for post in &posts {
71        println!("Post {}: {}", post.id, post.title);
72    }
73
74    // Call another function
75    let new_post =
76        create_post("New Post Title".to_string(), "New Post Content".to_string()).await?;
77
78    println!("Created post: {}", new_post.title);
79
80    Ok(())
81}
82
83async fn run_server() -> Result<(), ServerlessError> {
84    println!("Starting serverless function server...");
85    let host = "0.0.0.0";
86    let port = 3000;
87    println!("Server listening on http://{}:{}", host, port);
88
89    // Start the server - all functions marked with #[serverless] are automatically registered
90    // via the inventory crate
91    Server::new()
92        .host(host)
93        .port(port)
94        .start()
95        .await
96        .map_err(|e| ServerlessError::RemoteExecution(e.to_string()))?;
97
98    Ok(())
99}
100
101#[cfg(test)]
102mod tests {
103    use super::*;
104
105    #[tokio::test]
106    async fn test_read_posts() {
107        let posts = read_posts(2, "test".to_string()).await.unwrap();
108        assert_eq!(posts.len(), 2);
109        assert_eq!(posts[0].title, "Post 0");
110        assert_eq!(posts[1].title, "Post 1");
111    }
112
113    #[tokio::test]
114    async fn test_create_post() {
115        let post = create_post("Test Title".to_string(), "Test Content".to_string())
116            .await
117            .unwrap();
118        assert_eq!(post.title, "Test Title");
119        assert_eq!(post.content, "Test Content");
120    }
121}