Adding a lambda target with EventBridge

Unlike Kafka or Kinesis, you don’t really have a concept of a persisted topic or stream to which multiple consumers can consume from. Instead you need to set rules/targets, so it’s more like a concious push than a pull. Arguably, this does add a little bit of coupling in the sense that the producing team is aware of their consumers – but in many scenarios, that may actually be preferred.

Continuing with the example from the previous post, you’d need to add a new rule with the following event pattern.

{
  "source": ["demo-event"]
}

If you are wondering where that came from, here’s how you constructed your event entries. So the pattern above is basically saying, any time an event is pushed to the bus with that source, fire the rule.

PutEventsRequestEntry requestEntry1 = new PutEventsRequestEntry
{
    Source = "demo-event",
    EventBusName = "dev-event-bus",
    DetailType = "mock.client",
    Detail = payload1
};

You can now add a target to the rule. To test it out, the simplest approach is to set a cloudwatch log group as the target. Now you can just use the AWS console to confirm that your events are being received by the bus and that the rule is firing. Once you do that, you can test out the lambda target by creating a very simple lambda in C#.

public class Function
{        
    public async Task FunctionHandler(
        CloudWatchEvent<object> input, 
        ILambdaContext context)
    {
        context.Logger.LogLine($"Lambda: {input.Source}");
    }
}

The main thing is to note the signature for the FunctionHandler method. The events are going to be of type CloudWatchEvent<object>. And the one line of code just logs it to cloudwatch.

Amazon EventBridge

Amazon EventBridge is not an apples-to-apples comparable to Kafka or Kinesis, but it does enable event driven software architectures and is a serverless offering, so if you are heavily invested in AWS, it is very easy to move forward with it. It’s trivial to create an event bus (Amazon calls them custom event buses, but it’s basically just a named bus), and to produce events to it. For each event bus, you can have one or more rules associated with it. The rules dictate what happens when a certain event is fired – and it’s very basic pattern matching against the event schema. Each rule can have one or more targets – you can use lambdas or cloudwatch log groups as targets among others. Recently they added support for API targets – so basically you can point to any REST endpoint.

Producing Events

If your dev stack is .NET Core, you can use the AWSSDK.EventBridge NuGet package (official from AWS). Here’s some sample code that shows how to produce events to a specific bus. You can produce multiple events with a single call, but the bus receives them as individual events. So the example code below produces two separate events – meaning the targets receive them separately.

class Program
{
    static async Task Main()
    {
        string payload1 = JsonConvert.SerializeObject
            (
                new
                {
                    Firstname = "Joe",
                    Lastname = "Spodzter",
                    Email = "joe.s.100@yahoo.com"
                }
            );

        string payload2 = JsonConvert.SerializeObject
            (
                new
                {
                    Firstname = "Mary",
                    Lastname = "Spodzter",
                    Email = "joe.s.100@yahoo.com"
                }
            );

        PutEventsRequestEntry requestEntry1 = new PutEventsRequestEntry
        {
            Source = "demo-event",
            EventBusName = "dev-event-bus",
            DetailType = "mock.client",
            Detail = payload1
        };

        PutEventsRequestEntry requestEntry2 = new PutEventsRequestEntry
        {
            Source = "demo-event",
            EventBusName = "dev-event-bus",
            DetailType = "mock.client",
            Detail = payload2
        };

        using var client = new AmazonEventBridgeClient(RegionEndpoint.USEast2);

        var response = await client.PutEventsAsync
            (
                new PutEventsRequest()
                {
                    Entries =
                    {
                        requestEntry1, requestEntry2
                    }
                }
            );

        Console.WriteLine(response.HttpStatusCode);
    }
}