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
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)?