lambda_runtime/
lib.rs

1#![deny(clippy::all, clippy::cargo)]
2#![allow(clippy::multiple_crate_versions)]
3#![warn(missing_docs, nonstandard_style, rust_2018_idioms)]
4
5//! The mechanism available for defining a Lambda function is as follows:
6//!
7//! Create a type that conforms to the [`tower::Service`] trait. This type can
8//! then be passed to the the `lambda_runtime::run` function, which launches
9//! and runs the Lambda runtime.
10use serde::{Deserialize, Serialize};
11use std::{
12    env,
13    fmt::{self, Debug},
14    future::Future,
15    sync::Arc,
16};
17use tokio_stream::Stream;
18use tower::util::ServiceFn;
19pub use tower::{self, service_fn, Service};
20
21/// Diagnostic utilities to convert Rust types into Lambda Error types.
22pub mod diagnostic;
23pub use diagnostic::Diagnostic;
24
25mod deserializer;
26/// Tower middleware to be applied to runtime invocations.
27pub mod layers;
28mod requests;
29mod runtime;
30/// Utilities for Lambda Streaming functions.
31pub mod streaming;
32
33/// Utilities to initialize and use `tracing` and `tracing-subscriber` in Lambda Functions.
34#[cfg(feature = "tracing")]
35pub use lambda_runtime_api_client::tracing;
36
37/// Types available to a Lambda function.
38mod types;
39
40use requests::EventErrorRequest;
41pub use runtime::{LambdaInvocation, Runtime};
42pub use types::{Context, FunctionResponse, IntoFunctionResponse, LambdaEvent, MetadataPrelude, StreamResponse};
43
44/// Error type that lambdas may result in
45pub type Error = lambda_runtime_api_client::BoxError;
46
47/// Configuration derived from environment variables.
48#[derive(Debug, Default, Clone, Eq, PartialEq, Serialize, Deserialize)]
49pub struct Config {
50    /// The name of the function.
51    pub function_name: String,
52    /// The amount of memory available to the function in MB.
53    pub memory: i32,
54    /// The version of the function being executed.
55    pub version: String,
56    /// The name of the Amazon CloudWatch Logs stream for the function.
57    pub log_stream: String,
58    /// The name of the Amazon CloudWatch Logs group for the function.
59    pub log_group: String,
60}
61
62type RefConfig = Arc<Config>;
63
64impl Config {
65    /// Attempts to read configuration from environment variables.
66    pub fn from_env() -> Self {
67        Config {
68            function_name: env::var("AWS_LAMBDA_FUNCTION_NAME").expect("Missing AWS_LAMBDA_FUNCTION_NAME env var"),
69            memory: env::var("AWS_LAMBDA_FUNCTION_MEMORY_SIZE")
70                .expect("Missing AWS_LAMBDA_FUNCTION_MEMORY_SIZE env var")
71                .parse::<i32>()
72                .expect("AWS_LAMBDA_FUNCTION_MEMORY_SIZE env var is not <i32>"),
73            version: env::var("AWS_LAMBDA_FUNCTION_VERSION").expect("Missing AWS_LAMBDA_FUNCTION_VERSION env var"),
74            log_stream: env::var("AWS_LAMBDA_LOG_STREAM_NAME").unwrap_or_default(),
75            log_group: env::var("AWS_LAMBDA_LOG_GROUP_NAME").unwrap_or_default(),
76        }
77    }
78}
79
80/// Return a new [`ServiceFn`] with a closure that takes an event and context as separate arguments.
81#[deprecated(since = "0.5.0", note = "Use `service_fn` and `LambdaEvent` instead")]
82pub fn handler_fn<A, F, Fut>(f: F) -> ServiceFn<impl Fn(LambdaEvent<A>) -> Fut>
83where
84    F: Fn(A, Context) -> Fut,
85{
86    service_fn(move |req: LambdaEvent<A>| f(req.payload, req.context))
87}
88
89/// Starts the Lambda Rust runtime and begins polling for events on the [Lambda
90/// Runtime APIs](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-api.html).
91///
92/// If you need more control over the runtime and add custom middleware, use the
93/// [Runtime] type directly.
94///
95/// # Example
96/// ```no_run
97/// use lambda_runtime::{Error, service_fn, LambdaEvent};
98/// use serde_json::Value;
99///
100/// #[tokio::main]
101/// async fn main() -> Result<(), Error> {
102///     let func = service_fn(func);
103///     lambda_runtime::run(func).await?;
104///     Ok(())
105/// }
106///
107/// async fn func(event: LambdaEvent<Value>) -> Result<Value, Error> {
108///     Ok(event.payload)
109/// }
110/// ```
111pub async fn run<A, F, R, B, S, D, E>(handler: F) -> Result<(), Error>
112where
113    F: Service<LambdaEvent<A>, Response = R>,
114    F::Future: Future<Output = Result<R, F::Error>>,
115    F::Error: Into<Diagnostic> + fmt::Debug,
116    A: for<'de> Deserialize<'de>,
117    R: IntoFunctionResponse<B, S>,
118    B: Serialize,
119    S: Stream<Item = Result<D, E>> + Unpin + Send + 'static,
120    D: Into<bytes::Bytes> + Send,
121    E: Into<Error> + Send + Debug,
122{
123    let runtime = Runtime::new(handler).layer(layers::TracingLayer::new());
124    runtime.run().await
125}