run_local_handler

Function run_local_handler 

Source
pub async fn run_local_handler<F, Fut, R, Msg, Context>(
    message_handler: F,
) -> Result<R, Error>
where F: Fn(Msg, Arc<Context>) -> Fut, Fut: Future<Output = Result<R>>, Msg: DeserializeOwned, Context: LocalContext<Msg> + Debug,
Expand description

Executes a message handler against the message provided by the LocalContext.

The run_local_handler function takes care of the following tasks:

  • Sets up tracing to ensure all tracing::<...>!() calls are JSON formatted for consumption by CloudWatch.
  • Initialises a shared context object, which is passed to your handler.
  • Initialises a single message object, which is passed to your handler.

§Writing a message handler

To write a message handler, you need to define four elements:

  • The Message structure, which defines the structure of the messages which will be sent to your message handler.
  • The Context structure, which represents the shared state that will be passed into your message handler. This structure needs to implement the LocalContext trait.
  • The message_handler function, which accepts a Message and a Context, and performs the desired actions.

§Example

use anyhow::Result;
use async_trait::async_trait;
use clap::Parser;
use serde::Deserialize;
use std::fmt::Debug;
use std::sync::Arc;

use cobalt_aws::lambda::{run_local_handler, Error, LocalContext};

#[tokio::main]
async fn main() -> Result<(), Error> {
    let result = run_local_handler(message_handler).await?;
    Ok(())
}

/// The structure of the messages to be processed by our message handler.
#[derive(Debug, Deserialize)]
pub struct Message {
    pub target: String,
}


/// Shared context we build up before invoking the local runner.
#[derive(Debug)]
pub struct Context {
    pub greeting: String,
}

#[async_trait]
impl LocalContext<Message> for Context {
    /// Initialise a shared context object which will be
    /// passed to the message handler.
    async fn from_local() -> Result<Self> {
        Ok(Context {
            greeting: "Hello".to_string(),
        })
    }

    /// Construct a message to be processed.
    async fn msg(&self) -> Result<Message> {
        Ok(Message {
            target: "World".to_string(),
        })
    }
}

/// Process a single message, within the given context.
async fn message_handler(message: Message, context: Arc<Context>) -> Result<()> {
    tracing::debug!("Message: {:?}", message);
    tracing::debug!("Context: {:?}", context);

    // Log a greeting to the target
    tracing::info!("{}, {}!", context.greeting, message.target);

    Ok(())
}