-
Notifications
You must be signed in to change notification settings - Fork 925
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
Clean up and fix task executor type hierarchy #4760
Clean up and fix task executor type hierarchy #4760
Conversation
Motivation: There are a few issues in our task executor type hierarchy. - We don't provide the context-aware version of the following task executor types: - `Executor` -> `ContextAwareExecutor` - `ExecutorService` -> `ContextAwareExecutorService` - `BlockingTaskExecutor` -> `ContextAwareBlockingTaskExecutor` - There are no `RequestContext.makeContextAware()` and `makeContextPropagating()` that accept the aforementioned executor types. - `blockingTaskExecutor` properties often use `ScheduledExecutorService` rather than `BlockingTaskExecutor`. Modifications: - Added `ContextAwareExecutor`. - Made `ContextAwareExecutorService` public. - Added `ContxtAwareBlockingTaskExecutor`. - Added the implementation of the aforementioned types. - Added the context-propagating version of the aforementioned types. - Merged `common.RequestContextUtil` to `internal.common.RequestContextUtil` for less confusion. - Added `BlockingTaskExecutor.of(ScheduledExecutorService)`. - Changed the type of `blockingTaskExecutor` from `ScheduledExecutorService`. - Added an overloaded builder method `blockingTaskExecutor(BlockingTaskExecutor)`. - Removed the problematic wrapping of `blockingTaskExecutor` in `DefaultServerConfig.monitorBlockingTaskExecutor()`. - The wrapped executor is only used when a user gets the executor via `ServerConfig.blockingTaskExecutor()`, which is often not the case. A user gets the executor via `ServiceRequestContext.blockingTaskExecutor()` and thus the wrapped executor is never used. Result: - API completeness - (Breaking change) The type of `blockingTaskExecutor` property has been changed from `ScheduledExecutorService` to `BlockingTaskExecutor`. - Simply recompiling your code should be enough in most cases because `BlockingTaskExecutor` is a `ScheduledExecutorService`.
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.
Bad rename detection
@@ -15,14 +15,12 @@ | |||
*/ | |||
package com.linecorp.armeria.common; | |||
|
|||
final class RequestContextUtil { |
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.
This class has been merged to com.linecorp.armeria.internal.common.RequestContextUtil
to avoid confusion.
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.
Large portion of this class has been pulled up from AbstractContextAwareExecutorService
.
bfb1f04
to
df7152c
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.
Looks good all in all! 😄
core/src/main/java/com/linecorp/armeria/common/AbstractContextAwareExecutor.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/common/util/BlockingTaskExecutor.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/common/RequestContext.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/common/util/BlockingTaskExecutor.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/common/ContextAwareExecutor.java
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/common/RequestContext.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/linecorp/armeria/common/RequestContext.java
Outdated
Show resolved
Hide resolved
46ed94b
to
cb13cb6
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.
Overall looks good. I'm happy with these changes if TimedScheduledExecutorService
metrics are resolved.
executor = new TimedScheduledExecutorService(meterRegistry, executor, | ||
"blockingTaskExecutor", "armeria.", | ||
ImmutableList.of()); |
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.
Some users might be surprised that TimedScheduledExecutorService
-related metrics will disappear from their monitoring dashboard. What do you think of adding TimedBlockingTaskExecutor
by extending TimedScheduledExecutorService
?
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.
It's very likely that those metrics are all zero already because the executor returned by ctx.blockingTaskExecutor()
is not a TimedScheduledExecutorService
. 😱 How about having a separate PR for 1.24?
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 didn't know that execution times are not recorded already.
If it is not a regression made by this PR, it makes sense to handle that separately.
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 for cleaning up! 🙇♂️ 👍
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 a lot! 👍
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.
Left some minor comments but looks good to me! Thanks for the cleanup @trustin ! 🙇 👍 🙇
* If this executor is only used from a single request then it's better to use | ||
* {@link #makeContextAware(Executor)} | ||
*/ | ||
static Executor makeContextPropagating(Executor executor) { |
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 understood that Propagating*
is different from ContextAware*
in that it doesn't have store a RequestContext
and thus doesn't have additional methods to expose. (i.e. ContextAwareExecutor#context
). This is why we return the Executor
interface as opposed to a custom interface like the ContextAware*
series does.
I suppose technically Propagating*
can also share a #withoutContext
method, but I guess there might not be much use-cases.
I think the current approach is fine, but just wanted to point this out 👍
* Returns the {@link Executor} that executes the submitted tasks without setting | ||
* the {@link RequestContext}. | ||
*/ | ||
Executor withoutContext(); |
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 strong on this, but I'm wondering if unwrap
could be better naming to match that of BlockingTaskExecutor#unwrap
. (in the case of ContextAwareBlockingTaskExecutor
, both unwrap
and withoutContext
will be available which I think may return the same executor anyways)
I'm fine with either naming though 😄
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.
withoutContext()
was already there in other public subtypes such as ContextAwareScheduledExecutorService
, so I'd like to keep it consistent. I also think unwrap()
doesn't convey this method's original intention - 'return the version that doesn't propagate context'.
Thanks! 👍 👍 👍 |
Thanks a lot for merging this in. |
Motivation:
There are a few issues in our task executor type hierarchy.
Executor
->ContextAwareExecutor
ExecutorService
->ContextAwareExecutorService
BlockingTaskExecutor
->ContextAwareBlockingTaskExecutor
RequestContext.makeContextAware()
andmakeContextPropagating()
that accept the aforementioned executor types.
blockingTaskExecutor
properties often useScheduledExecutorService
rather than
BlockingTaskExecutor
.Modifications:
ContextAwareExecutor
.ContextAwareExecutorService
public.ContxtAwareBlockingTaskExecutor
.common.RequestContextUtil
tointernal.common.RequestContextUtil
for less confusion.
BlockingTaskExecutor.of(ScheduledExecutorService)
.blockingTaskExecutor
fromScheduledExecutorService
.blockingTaskExecutor(BlockingTaskExecutor)
.blockingTaskExecutor
inDefaultServerConfig.monitorBlockingTaskExecutor()
.ServerConfig.blockingTaskExecutor()
, which is often not the case.A user gets the executor via
ServiceRequestContext.blockingTaskExecutor()
and thus the wrapped executor is never used.
Result:
BlockingTaskExecutor
by wrapping aScheduledExecutorService
.Executor
andBlockingTaskExecutor
.blockingTaskExecutor
property has beenchanged from
ScheduledExecutorService
toBlockingTaskExecutor
.BlockingTaskExecutor
is aScheduledExecutorService
.RequestContext.makeContextAware()
methodshave been changed to the context-aware types, e.g.
makeContextAware(Executor)
returnsContextAwareExecutor
instead ofExecutor
.makeContextAware(ScheduledExecutorService)
returnsContextAwareScheduledExecutorService
instead ofScheduledExecutorService
.