use std::env;
use chrono::Utc;
use backtrace;
use env as lambda_env;
use error::HandlerError;
use lambda_runtime_client;
#[derive(Default, Clone)]
pub struct Context {
pub memory_limit_in_mb: i32,
pub function_name: String,
pub function_version: String,
pub invoked_function_arn: String,
pub aws_request_id: String,
pub xray_trace_id: String,
pub log_stream_name: String,
pub log_group_name: String,
pub client_context: Option<lambda_runtime_client::ClientContext>,
pub identity: Option<lambda_runtime_client::CognitoIdentity>,
pub(super) deadline: u128,
}
impl Context {
pub(super) fn new(local_settings: lambda_env::FunctionSettings) -> Context {
Context {
xray_trace_id: String::from(""),
memory_limit_in_mb: local_settings.memory_size,
function_name: local_settings.function_name,
function_version: local_settings.version,
log_stream_name: local_settings.log_stream,
log_group_name: local_settings.log_group,
..Default::default()
}
}
pub fn new_error(&self, msg: &str) -> HandlerError {
let mut trace: Option<backtrace::Backtrace> = None;
let is_backtrace = env::var("RUST_BACKTRACE");
if is_backtrace.is_ok() && is_backtrace.unwrap() == "1" {
trace!("Begin backtrace collection");
trace = Option::from(backtrace::Backtrace::new());
trace!("Completed backtrace collection");
}
HandlerError::new(msg, trace)
}
pub fn get_time_remaining_millis(&self) -> u128 {
let millis = Utc::now().timestamp_millis();
self.deadline - millis as u128
}
}
#[cfg(test)]
pub(crate) mod tests {
use super::*;
use env::{self, ConfigProvider};
use std::{thread::sleep, time};
fn get_deadline(secs: u8) -> u128 {
Utc::now().timestamp_millis() as u128 + (u128::from(secs) * 1_000)
}
pub(crate) fn test_context(deadline: u8) -> Context {
Context {
memory_limit_in_mb: 128,
function_name: "test_func".to_string(),
function_version: "$LATEST".to_string(),
invoked_function_arn: "arn:aws:lambda".to_string(),
aws_request_id: "123".to_string(),
xray_trace_id: "123".to_string(),
log_stream_name: "logStream".to_string(),
log_group_name: "logGroup".to_string(),
client_context: Option::default(),
identity: Option::default(),
deadline: get_deadline(deadline),
}
}
#[test]
fn verify_time_remaining() {
let config = env::tests::MockConfigProvider { error: false };
let mut ctx = Context::new(config.get_function_settings().unwrap());
ctx.deadline = get_deadline(10);
println!("Set deadline to: {}", ctx.deadline);
sleep(time::Duration::new(2, 0));
let remaining = ctx.get_time_remaining_millis();
assert!(
remaining > 7800 && remaining < 8200,
"Remaining time in millis outside the expected range: {}",
remaining
);
}
}