AWS EventBridge as Lambda destination

2.3k views Asked by At

I have two Lambda functions, an EventProducer and an EventConsumer. The desired scenario is the following: The EventProducer adds an event in a custom AWS EventBridge bus and the EventConsumer reads the event.

I want to achieve this using the Lambda destinations but EventBridge does no seem to be working. I have managed to make an event available to the Consumer by pushing my an event by explicitly calling `AmazonEventBridge::putEvent`` but I have not managed to do so by returning an output and sending the output.

The code works if instead of EventBridge I use Lambda or SQS as a destination. The Consumer also reads messages when I send them using the AWS CLI.

Does anyone have a working example of pushing an event in EventBridge from a Lambda function using Lambda destinations?

My code is the following:

Handler code:

@Override
public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException {
        DataciteDoiRequest sentDirectly = newDataciteDoiRequest();
        logger.info(lOG_HANDLER_HAS_RUN);
        putEventDirectlyToEventBridge(sentDirectly); 

        DataciteDoiRequest sentThroughLambdaDestination =
            sentDirectly.copy().withPublicationId(URI.create("https://localhost/fromOutputStream")).build();
        writeOutput(sentThroughLambdaDestination, output);
    }

    private <I> void writeOutput(I event, OutputStream outputStream)
        throws IOException {
        try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream))) {
            String responseJson = Optional.ofNullable(objectMapper.writeValueAsString(event))
                .map(StringUtils::replaceWhiteSpacesWithSpace)
                .map(StringUtils::removeMultipleWhiteSpaces)
                .orElseThrow();
            logger.info(responseJson);
            writer.write(responseJson);
        }
    }

    private void putEventDirectlyToEventBridge(DataciteDoiRequest dataciteDoiRequest) {
        PutEventsRequestEntry putEventsRequestEntry = new PutEventsRequestEntry()
            .withDetail(dataciteDoiRequest.toString())
            .withEventBusName(environment.readEnv(EVENT_BUS_ENV_VAR))
            .withSource(SOURCE)
            .withDetailType(dataciteDoiRequest.getType());

        PutEventsRequest putEventsRequest = new PutEventsRequest().withEntries(putEventsRequestEntry);
        eventBridgeClient.putEvents(putEventsRequest);
    }


CloudFormation template:

 EventConsumer:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: dynamo-event-to-datacite-request
      Handler: handlers.EventConsumer::handleRequest
      Runtime: java11
      MemorySize: 1400
      Role: !GetAtt LambdaRole.Arn
      Environment:
        Variables:
          EVENT_BUS: !GetAtt EventBus.Name
          AWC_ACCOUNT_ID: !Ref AWS::AccountId
      Events:
        EventBridgeEvent:
          Type: EventBridgeRule
          Properties:
            EventBusName: !GetAtt EventBus.Name
            Pattern: { "detail": { "type": [ "MyType" ] } }
  EventProducer:
    DependsOn:
      - EventBus
      - FailQueue
      - EventConsumer
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: dynamo-event-to-datacite-request
      Handler: handlers.EventProducer::handleRequest
      Runtime: java11
      MemorySize: 1400
      Role: !GetAtt LambdaRole.Arn
      EventInvokeConfig:
        DestinationConfig:
          OnSuccess:
            Type: EventBridge
            Destination: !GetAtt EventBus.Arn
          OnFailure:
            Type: SQS
            Destination: !GetAtt FailQueue.Arn

      Environment:
        Variables:
          EVENT_BUS: !GetAtt EventBus.Name
  EventBus:
    Type: AWS::Events::EventBus
    Properties:
      Name: orestis-event-bus
  FailQueue:
    Type: AWS::SQS::Queue
    Properties:
      MaximumMessageSize: 262144
      QueueName: orestis-failure-queue


1

There are 1 answers

0
Jani Siivola On

Your EventConsumer Events -config doesn't look correct EventBridgeRule to me. The Pattern is missing the source -property. This should match the name of the SOURCE that your sender is using. Also the "detail" property should be "detail-type" if you use it to differentiate different event types: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-events-rule.html

What if you write your Events -config like this (all in Yaml)?

Events:
  EventBridgeEvent:
    Type: EventBridgeRule
    Properties:
      EventBusName: !GetAtt EventBus.Name
      Pattern:
       source:
         - "name.of.the.sender"
       detail-type:
         - "MyType"