-
Notifications
You must be signed in to change notification settings - Fork 104
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added shutdown() -> EventLoopFuture<Void>
to the ByteBufferLambdaHandler
#122
Added shutdown() -> EventLoopFuture<Void>
to the ByteBufferLambdaHandler
#122
Conversation
@@ -164,6 +164,14 @@ public protocol ByteBufferLambdaHandler { | |||
/// - Returns: An `EventLoopFuture` to report the result of the Lambda back to the runtime engine. | |||
/// The `EventLoopFuture` should be completed with either a response encoded as `ByteBuffer` or an `Error` | |||
func handle(context: Lambda.Context, event: ByteBuffer) -> EventLoopFuture<ByteBuffer?> | |||
|
|||
/// The method to clean up your resources. | |||
/// Concrete Lambda handlers implement this method to shutdown their `HTTPClient`s and database connections. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it worth adding a mention about if your create/init future failed then this would not be invoked so take special case about any resources that need to be torn down there (as we discussed that case on chat)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ktoso fixed below
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks good
881312b
to
feb35c7
Compare
try handler.syncShutdown() | ||
} catch { | ||
logger.error("Error shutting down handler: \(error)") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@fabianfett why not surface the handler shutdown error into the finishPromise?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea, we might overwrite a previous error though? Do we want that? wdyt? @tomerd
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe roll them up to a "ShutdownError" of sorts that contain a collection/array of the underlying errors?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks good, one question
// If the lambda is terminated (e.g. LocalServer shutdown), we make sure | ||
// developers have the chance to cleanup their resources. | ||
do { | ||
try handler.syncShutdown() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think the handler
would expect to be called from outside the EventLoop
to do the shutdown. I think you need to require the caller to provide an asynchronous shutdown method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, you could also document that it'll be called on another thread but that's maybe a bit weird. AHC's syncShutdown
is thread-safe but I don't think we can expect that from everybody.
Also: If shutdown is synchronous, then often the startup is also synchronous, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you need to require the caller to provide an asynchronous shutdown method.
I tend to agree this fits better with the rest of APIs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a2e87b7
to
6488d9a
Compare
syncShutdown() throws
to the ByteBufferLambdaHandler
shutdown() -> EventLoopFuture<Void>
to the ByteBufferLambdaHandler
b7cc3af
to
23688d5
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good now @fabianfett 👍
/// | ||
/// - Note: In case your Lambda fails while creating your LambdaHandler in the `HandlerFactory`, this method | ||
/// **is not invoked**. In this case you must cleanup the created resources immediately in the `HandlerFactory`. | ||
func shutdown(context: Lambda.ShutdownContext) -> EventLoopFuture<Void> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this invoked once per lambda invocation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no. only in debug mode for shutdown. or if the lambda occurs an recoverable error. and the lambda is therefore closed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@fabianfett ah right. In that case, couldn't we run it synchronously after MTELG.withCallingThreadAsEventLoop
returns?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah no, doesn't make sense. Shutdown probably needs the EL :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ignore my comments. This looks good.
@@ -95,7 +95,7 @@ private extension Lambda.Context { | |||
} | |||
|
|||
// TODO: move to nio? | |||
private extension EventLoopFuture { | |||
extension EventLoopFuture { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this change leftover from previous iteration?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no it's needed, since I use mapResult
in another file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also: Please don't use any access qualifiers (especially not public
) in front of extension
. It makes code reviews really difficult because a func foo() {}
can be public if maybe 100 lines above there's a public extension XYZ
. I think all qualifiers should be banned in front of extension
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I hope there's some linter for this perhaps? Maybe time to look around for one hm
.flatMap { (handler, result) -> EventLoopFuture<Int> in | ||
let shutdownContext = ShutdownContext(logger: logger, eventLoop: self.eventLoop) | ||
return handler.shutdown(context: shutdownContext).recover { error in | ||
logger.error("Error shutting down handler: \(error)") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not a blocker, since this is debug mode only, but ideally the shutdown error would bubble into the shutdownPromise
instead of being logged
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tomerd I hope I fixed this with my last push.
a772032
to
35fb3ab
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, LGTM!
b779861
to
6188493
Compare
6188493
to
ed7d57a
Compare
Motivation
This fixes #121.
Before we also had a small bug in the code:
Look out for the
// ^--
comments in the code above. If a factory failed before, the Lambda was not shutdown, which ultimately led to a leakedEventLoop
andLifecycle
. This pr addresses this issue as well and provides a test for it.Changes
syncShutdown()
throws to theByteBufferLambdaHandler
protocol and provided a default implementation (empty).shutdownFuture
as well.