Skip to content
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

Merged
merged 6 commits into from
Mar 29, 2023

Conversation

trustin
Copy link
Member

@trustin trustin commented Mar 17, 2023

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
    • You can now create a BlockingTaskExecutor by wrapping a ScheduledExecutorService.
    • You can now create context-aware or context-propagating Executor and
      BlockingTaskExecutor.
  • (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.
  • (Breaking change) The return types of RequestContext.makeContextAware() methods
    have been changed to the context-aware types, e.g.
    • makeContextAware(Executor) returns ContextAwareExecutor instead of Executor.
    • makeContextAware(ScheduledExecutorService) returns ContextAwareScheduledExecutorService instead of ScheduledExecutorService.

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`.
@trustin trustin changed the title Clean up task executor type hierarchy Clean up and fix task executor type hierarchy Mar 17, 2023
@trustin trustin added this to the 1.23.0 milestone Mar 17, 2023
Copy link
Member Author

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 {
Copy link
Member Author

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.

Copy link
Member Author

@trustin trustin Mar 17, 2023

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.

@trustin trustin force-pushed the context_aware_blocking_task_executor branch from bfb1f04 to df7152c Compare March 17, 2023 08:19
Copy link
Contributor

@minwoox minwoox left a 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! 😄

@trustin trustin requested review from ikhoon and minwoox March 28, 2023 08:37
@trustin trustin force-pushed the context_aware_blocking_task_executor branch from 46ed94b to cb13cb6 Compare March 28, 2023 08:48
Copy link
Contributor

@ikhoon ikhoon left a 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.

Comment on lines -328 to -330
executor = new TimedScheduledExecutorService(meterRegistry, executor,
"blockingTaskExecutor", "armeria.",
ImmutableList.of());
Copy link
Contributor

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?

Copy link
Member Author

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?

Copy link
Contributor

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.

Copy link
Contributor

@ikhoon ikhoon left a 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! 🙇‍♂️ 👍

Copy link
Contributor

@minwoox minwoox left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot! 👍

Copy link
Contributor

@jrhee17 jrhee17 left a 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) {
Copy link
Contributor

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();
Copy link
Contributor

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 😄

Copy link
Member Author

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'.

@minwoox minwoox merged commit 787467f into line:main Mar 29, 2023
@minwoox
Copy link
Contributor

minwoox commented Mar 29, 2023

Thanks! 👍 👍 👍

@trustin trustin deleted the context_aware_blocking_task_executor branch March 29, 2023 09:02
@trustin
Copy link
Member Author

trustin commented Mar 29, 2023

Thanks a lot for merging this in.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants