Open musketyr opened 1 year ago
Shutting down the executor service will break the runtime when the lambda is reused.
You might want to create a custom ExecutorService
that will collect all the tasks and await their completion before the lambda is done.
Thanks for fast response. Is this something which can be done directly in Micronaut libraries, ideally somewhere inside AsyncInterceptor
? I believe this would be helpful for every Micronaut user.
Maybe somewhere in the Lambda project, pretty much you just need a custom scheduler:
@Singleton
@Named("LambdaScheduler")
class LambdaSchedulerScheduler implements ExecutorService {
///...
void awaitTasksCompletion() { ... }
}
@Async("LambdaScheduler")
void myAsyncMethod() {...}
void someLambdaWork() {
//...
lambdaSchedulerScheduler.awaitTasksCompletion();
}
I don't know much about Lamdas implementation, but assuming the context is reused. I haven't found any events that would be automatically triggered at the end of the invocation, those would have been helpful to do the await.
Yes, the context is reused and you were right about the shutdown
. I have created a test function and it looks like your suggestion with registering the futures works. So the question is if you would like to add something like this directly inside micronaut-function
or should I create our own standalone library.
It might be a good idea to have it first as a part of micronaut-aws
and then maybe to move it to micronaut-function
. WDYT @graemerocher
Also, it would be nice to introduce a new event being triggered after the lambda function invocation, and this new scheduler can have a listener and do the awaiting automatically.
BTW: you can use CompletableFuture<Void> runAsync(Runnable runnable, Executor executor)
in the scheduler and CompletableFuture<Void> allOf
to implement await.
Also, it would be nice to introduce a new event being triggered after the lambda function invocation, and this new scheduler can have a listener and do the awaiting automatically.
If we stick directly to the
io.micronaut.function.aws.MicronautRequestHandler
and not more genericio.micronaut.function.executor.FunctionInitializer
(which we are historically using - I believe one time it was a favorite way how to write handlers) then yes, it would be good if a sync event was fired at the end of execution ofhandleRequest
method.
@Override
public final O handleRequest(I input, Context context) {
HandlerUtils.configureWithContext(this, context);
if (!inputType.isInstance(input)) {
input = convertInput(input);
}
O output = this.execute(input);
publishExecutionFinishedEvent(input, output);
return output;
}
The same applies for io.micronaut.function.aws.MicronautRequestStreamHandler
. It should not be a big deal for us to migrate our functions. Once there is a simple way for post-execute hooks then we can simplify a lot of our code, including for example Sentry Integration where we need to wait for flushing the events.
BTW: you can use
CompletableFuture<Void> runAsync(Runnable runnable, Executor executor)
in the scheduler andCompletableFuture<Void> allOf
to implement await.
Thanks for a tip!
I have started the work on the event here https://github.com/micronaut-projects/micronaut-aws/pull/1433
Just a few more details why we would like to keep @Async
even in Lambda environment. We simply have a services which are shared between Micronaut applications and Micronaut functions and we don't want to create pairs of duplicates for sync/async invocations.
In that case, you might want to wrap all the executors in the Lamba environment using a bean listener like this https://github.com/micronaut-projects/micronaut-core/blob/3.6.x/context/src/main/java/io/micronaut/scheduling/instrument/ExecutorServiceInstrumenter.java and await the completion.
Thanks for the link! It may be really handly!
Just one radical idea. Would it be possible to ignore @Async
annotation/interceptor and make publishEventAsync
call synchronous when AWS Lambda function environment is detected?
👍
Any way this work can be progressed.
We are facing same issue with Application hosted as Lambda Functions where is the service response stops lambda execution and do not wait for ASYNC methods to finish.
Feature description
We are trying to move non-business related code into async event listeners but when we are running AWS functions then some of the methods annotated with
@Async
are not executed because the Lambda is put into sleep mode before the code is finished. We we able to make this work with a following snippet:This is pretty primitive approach and I wonder if there could be some bean which would provide such an interface which is more reliable (e.g. will work out of box with any other custom
ExecutorService
). I'm also bit worried what will happen if the Lambda is reused.