|
| 1 | +--- |
| 2 | +sidebar_position: 2 |
| 3 | +title: EventBridge Event Handler |
| 4 | +description: Lambda function for handling an event from Amazon EventBridge |
| 5 | +keywords: [rust,lambda,eventbridge,messaging,putevent] |
| 6 | +--- |
| 7 | + |
| 8 | +As mentioned in several of the other messaging quick starts, the publisher/subscriber (pub/sub) pattern is extremely common in a serverless architecture. Severless encourages micro and someties even nano-sized components that are assembled together by way of contracts as opposed to building everything into a single binary. |
| 9 | + |
| 10 | +AWS' EventBridge is a service that describes itself like this: |
| 11 | + |
| 12 | +> Amazon EventBridge Event Bus is a serverless event bus that helps you receive, filter, transform, route, and deliver events. - AWS |
| 13 | +
|
| 14 | +It provides a Default Bus or you are able to add Custom Event Buses to fit your need. This article will look to showcase how to create a Lambda function that handles an event from an EventBridge custom bus. It also takes the publishing component from the article on [Event Bridge Put Events](./eventbridge-putevent.md) to give a cohesive pub/sub experience. |
| 15 | + |
| 16 | +## How It Works |
| 17 | + |
| 18 | +The sample in this tutorial builds upon a Lambda that listens on a Function URL and then generates an EventBridge PutEvent with a custom domain model. A Rule is defined by the subscriber on the custom event bus that sends any matching messages to a Lambda function. The subscriber Lambda function will deserialize and process the message. |
| 19 | + |
| 20 | +The EventBridge -> Lambda integration is an example of an [async invoke](../../fundamentals/invocation-modes.md#asynchronous-invokes). Internally inside the Lambda service the events are queued up onto an SQS queue managed by Lambda, and your function is invoked from here. |
| 21 | + |
| 22 | +An important note, the sample application deploys the publisher, subscriber and event bus using the same infrastructure as code template. This is for ease of demonstration. Typically the 3 components would be deployed as 3 independent stacks. |
| 23 | + |
| 24 | +## Project Structure |
| 25 | + |
| 26 | +A Lambda and EventBridge Event handler template is found under the [./templates](https://github.com/serverlessdevelopers/serverless-rust/tree/main/templates/patterns/messaging-patterns/eventbridge-handler) directory in the GitHub repo. You can use template to get started building with EventBridge and Lambda. |
| 27 | + |
| 28 | +The template is simple, and is based upon the following structure. |
| 29 | + |
| 30 | +```bash |
| 31 | +lambdas |
| 32 | + - event-handler |
| 33 | + - publisher |
| 34 | + - shared |
| 35 | +``` |
| 36 | + |
| 37 | +## Lambda Code |
| 38 | + |
| 39 | +### Main |
| 40 | + |
| 41 | +<CH.Section> |
| 42 | + |
| 43 | +When handling messages from EventBridge with Lambda your Lambda code will look much like the other services covered as part of the [messaging patterns](../messaging-patterns/). The main function sets up the logging framework, and then starts the Lambda runtime. Passing in the [function to use as the handler](focus://9). |
| 44 | + |
| 45 | +```rust |
| 46 | +#[tokio::main] |
| 47 | +async fn main() -> Result<(), Error> { |
| 48 | + tracing_subscriber::fmt() |
| 49 | + .with_max_level(tracing::Level::INFO) |
| 50 | + .with_target(false) |
| 51 | + .without_time() |
| 52 | + .init(); |
| 53 | + |
| 54 | + run(service_fn(function_handler)).await |
| 55 | +} |
| 56 | +``` |
| 57 | + |
| 58 | +</CH.Section> |
| 59 | + |
| 60 | +### Handler Code |
| 61 | + |
| 62 | +<CH.Section> |
| 63 | +The handler code in this sample is deserializing the `detail` of the event that comes from EventBridge and using a handler from your custom business logic to actually process the message. |
| 64 | + |
| 65 | +The [`LambdaEvent` that comes into your handler function is of type `CloudWatchEvent`](focus://1[26:63]). Before EventBridge became it's own service, it was called CloudWatch events. Hence the name of the struct being `CloudWatchEvent`. |
| 66 | + |
| 67 | +For re-usability, a custom [`InternalMessage`](focus://2) struct is used as a wrapper around the `CloudWatchEvent` type that comes from the [Lambda events Crate](https://docs.rs/aws_lambda_events/latest/aws_lambda_events/). This allows the [`try_into()`](focus://3) function to be used to handle the conversion from the custom CloudWatchEvent type into the `Payload` type used by the application. |
| 68 | + |
| 69 | +Note that if the [`try_into()` call fails](focus://14:16) or the [`handle()` function call fails](focus://11) the handler returns an error. This will return an error back to the Lambda runtime. |
| 70 | + |
| 71 | +```rust |
| 72 | +async fn function_handler(event: LambdaEvent<CloudWatchEvent>) -> Result<(), Error> { |
| 73 | + let payload: Result<Payload, MessageParseError> = InternalMessage(event.payload) |
| 74 | + .try_into(); |
| 75 | + |
| 76 | + match payload { |
| 77 | + Ok(payload) => { |
| 78 | + let _handle_res = PayloadHandler::handle(&payload).await; |
| 79 | + |
| 80 | + match _handle_res { |
| 81 | + Ok(_) => Ok(()), |
| 82 | + Err(e) => Err(e.into()) |
| 83 | + } |
| 84 | + } |
| 85 | + Err(err) => { |
| 86 | + Err(err.into()) |
| 87 | + } |
| 88 | + } |
| 89 | +} |
| 90 | +``` |
| 91 | +</CH.Section> |
| 92 | + |
| 93 | +<CH.Section> |
| 94 | + |
| 95 | +By default, EventBridge retries sending the event for 24 hours and up to 185 times with an exponential back off and jitter, or randomized delay. You can [control this retry behavior](focus://12:16), and the routing to a dead letter queue, using your Lambda event source configuration. This example uses AWS SAM to automatically create an [SQS queue](focus://14:16) for failures, and route any failed messages to the [DLQ after only one retry](focus://13). |
| 96 | + |
| 97 | +```yaml |
| 98 | + EventHandlerFunction: |
| 99 | + Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction |
| 100 | + Metadata: |
| 101 | + BuildMethod: rust-cargolambda |
| 102 | + BuildProperties: |
| 103 | + Binary: event-bridge-handler |
| 104 | + Properties: |
| 105 | + FunctionName: serverless-rust-EventHandler |
| 106 | + CodeUri: . |
| 107 | + Handler: bootstrap |
| 108 | + Runtime: provided.al2023 |
| 109 | + EventInvokeConfig: |
| 110 | + MaximumRetryAttempts: 1 |
| 111 | + DestinationConfig: |
| 112 | + OnFailure: |
| 113 | + Type: SQS |
| 114 | + Architectures: |
| 115 | + - arm64 |
| 116 | + Events: |
| 117 | + Trigger: |
| 118 | + Type: CloudWatchEvent |
| 119 | + Properties: |
| 120 | + EventBusName: !GetAtt RustDemoEventBus.Name |
| 121 | + Pattern: |
| 122 | + source: |
| 123 | + - RustDemo |
| 124 | +``` |
| 125 | +
|
| 126 | +</CH.Section> |
| 127 | +
|
| 128 | +## Deploy |
| 129 | +
|
| 130 | +You can deploy this example directly to your own AWS account using the [provided template](https://github.com/serverlessdevelopers/serverless-rust/tree/main/templates/patterns/messaging-patterns/eventbridge-handler). Simply clone the repo, and then run the below CLI commands from the repo root. |
| 131 | +
|
| 132 | +``` |
| 133 | +cd templates/patterns/messaging-patterns/eventbridge-handler/ |
| 134 | +sam build --beta-features |
| 135 | +sam deploy |
| 136 | +``` |
| 137 | + |
| 138 | +Once deployed, you can send a POST request to the Lambda function URL endpoint with the below body: |
| 139 | + |
| 140 | +```json |
| 141 | +{ |
| 142 | + "name": "James", |
| 143 | + "message": "Hello YouTube" |
| 144 | +} |
| 145 | +``` |
| 146 | + |
| 147 | +After running the POST request and getting back a 200 response, you can use the `sam logs` CLI command to retrieve the logs for your EventBridge handler function. |
| 148 | + |
| 149 | +``` |
| 150 | +sam logs --profile sandbox --stack-name event-bridge-rust |
| 151 | +``` |
| 152 | + |
| 153 | +## Congrats |
| 154 | + |
| 155 | +And that's all there is to it. This was a simple example but highlights how you can use Rust, Lambda and EventBridge to build high performance event driven systems. |
| 156 | + |
0 commit comments