I am trying to call a Java Lambda function asynchronously from within another Java Lambda function. I simply want to fire and forget, but with .invokeAsync(InvokeRequest), I have to call .get() on the Future, which then blocks and breaks the 'fire and forget' use case.
Here is the code I am trying to use:
private void sendToDownloader(String payload) throws InterruptedException, ExecutionException {
log.info(payload);
InvokeRequest invoke = new InvokeRequest();
invoke.withFunctionName("LambdaTwo")
.withPayload(payload)
.withInvocationType(InvocationType.Event);
lambdaClient.invokeAsync(invoke).get();
}
If I remove the .get() method call, it does not actually invoke LambdaTwo.
It should be noted, this lambda function ends immediately after invoking LambdaTwo.
Meanwhile, I tried using the following code:
private void sendToDownloader(String payload) throws InterruptedException, ExecutionException {
log.info(payload);
InvokeAsyncRequest invoke = new InvokeAsyncRequest();
invoke.withFunctionName("LambdaTwo")
.withInvokeArgs(payload);
lambdaClient.invokeAsync(invoke);
}
This code works, however .invokeAsync is deprecated and it says to see "Invoke API", for which I cannot find any documentation.
Can anyone lead me to the right way to invoke a Lambda function in a purely 'fire and forget' fashion?
EDIT 1 Per Mark's suggestion, I have rewritten the code below, however it seems to block while the LambdaTwo function executes.
public void routeEvent(String lambdaName, String cacheName) throws InterruptedException, ExecutionException, JsonProcessingException {
ObjectNode obj = new ObjectNode(JsonNodeFactory.instance);
obj.put("nodeName", cacheName);
InvokeRequest invoke = new InvokeRequest();
invoke.withFunctionName(lambdaName)
.withInvocationType(InvocationType.Event)
.withPayload(OBJECT_MAPPER.writeValueAsString(obj));
log.info(System.currentTimeMillis());
lambdaClient.invoke(invoke);
log.info(System.currentTimeMillis());
}
It prints out the following milliseconds.
2016-11-28 03:41:35 INFO LambdaFunction:97 - 1480304495867
2016-11-28 03:41:41 INFO LambdaFunction:99 - 1480304501432
There is a difference of about 5.5 seconds between the two and the Lambda duration confirms this.
EDIT 2 Just to clarify, I was trying the AWSLambdaAsyncClient calling the .invokeAsync(InvokeRequest) and .invoke(InvokeRequest) and neither worked. When calling invokeAsync, it does not actually invoke the Lambda function unless I call .get() on it, which then blocks while the second Lambda function executes.
What finally worked was calling .invokeAsync(InvokeRequest), however NOT calling .withInvocationType(InvocationType.Event) on the InvokeRequest object. It's not clear why that caused the asynchronous behavior, but that's what worked and not using a deprecated method.
public void routeEventAsync2(String lambdaName, String cacheName) throws InterruptedException, ExecutionException, JsonProcessingException {
ObjectNode obj = new ObjectNode(JsonNodeFactory.instance);
obj.put("nodeName", cacheName);
InvokeRequest invoke = new InvokeRequest();
invoke.withFunctionName(lambdaName)
.withPayload(OBJECT_MAPPER.writeValueAsString(obj));
lambdaAsyncClient.invokeAsync(invoke);
}
For asynchronous invocation, Lambda places the event in a queue and returns a success response without additional information. A separate process reads events from the queue and sends them to your function. To invoke a function asynchronously, set the invocation type parameter to Event .
SNS, S3 & EventBridge, StepFunctions— Are examples of Asynchronous Lambda Invocations. The events coming from those services will be queued up and will be pending to be processed by lambda. If your function returns an error, AWS will automatically retry the invoke twice, for a total of three invocations.
You can now develop AWS Lambda functions using Java 11. You can use Java 11 features such as its improved HTTP Client API and new methods for reading and writing strings when authoring your functions.
With Amazon SQS, you can offload tasks from one component of your application by sending them to a queue and processing them asynchronously. Lambda polls the queue and invokes your Lambda function synchronously with an event that contains queue messages.
The documentation regarding the deprecation of this method is confusing. What they are trying to say is to use AWSLambdaClient.invoke(request)
. You will need to set the InvocationType
to Event
on the request object in order to invoke the Lambda function without waiting for a response.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With