Skip to content

Introduce the CancellationScheduler interface#5220

Merged
jrhee17 merged 3 commits intoline:mainfrom
jrhee17:refactor/init-cancel-scheduler-1
Oct 18, 2023
Merged

Introduce the CancellationScheduler interface#5220
jrhee17 merged 3 commits intoline:mainfrom
jrhee17:refactor/init-cancel-scheduler-1

Conversation

@jrhee17
Copy link
Copy Markdown
Contributor

@jrhee17 jrhee17 commented Oct 4, 2023

Motivation:

While working on #5212, I realized that noopResponseCancellationScheduler is an already completed scheduler.
When we create a DefaultClientRequestContext for the upgrade request, we use this scheduler.

null, REQUEST_OPTIONS_FOR_UPGRADE_REQUEST, noopResponseCancellationScheduler,

However, actually what we want is a scheduler which never completes instead of an already completed scheduler.
For this reason, I propose that we separate a

  • CancellationScheduler#noop: signifies a scheduler which never completes
  • CancellationScheduler#finished: signifies a scheduler which already completed

Note that the upgrade request is already bound by connectTimeout, so it is safe to use a CancellationScheduler which never completes.

Modifications:

  • Rename CancellationScheduler to DefaultCancellationScheduler, and reduce visibility
  • Introduce an interface CancellationScheduler
  • Introduce factory methods CancellationScheduler#of, CancellationScheduler#noop, CancellationScheduler#finished

Result:

@jrhee17 jrhee17 added this to the 1.26.0 milestone Oct 4, 2023
@jrhee17 jrhee17 changed the title Refactor cancellation scheduler Introduce the CancellationScheduler interface Oct 4, 2023
@codecov
Copy link
Copy Markdown

codecov Bot commented Oct 4, 2023

Codecov Report

Attention: 68 lines in your changes are missing coverage. Please review.

Comparison is base (9568d56) 0.00% compared to head (0bc6edd) 74.05%.
Report is 12 commits behind head on main.

Additional details and impacted files
@@             Coverage Diff             @@
##             main    #5220       +/-   ##
===========================================
+ Coverage        0   74.05%   +74.05%     
- Complexity      0    19968    +19968     
===========================================
  Files           0     1717     +1717     
  Lines           0    73576    +73576     
  Branches        0     9364     +9364     
===========================================
+ Hits            0    54489    +54489     
- Misses          0    14647    +14647     
- Partials        0     4440     +4440     
Files Coverage Δ
...rp/armeria/client/ClientRequestContextBuilder.java 80.76% <100.00%> (ø)
...armeria/client/HttpClientPipelineConfigurator.java 78.96% <100.00%> (ø)
...a/internal/client/DefaultClientRequestContext.java 90.72% <100.00%> (ø)
...armeria/internal/common/CancellationScheduler.java 100.00% <100.00%> (ø)
.../internal/server/DefaultServiceRequestContext.java 86.33% <100.00%> (ø)
...p/armeria/server/ServiceRequestContextBuilder.java 89.47% <100.00%> (ø)
...ria/internal/common/NoopCancellationScheduler.java 45.00% <45.00%> (ø)
.../internal/common/DefaultCancellationScheduler.java 77.38% <77.38%> (ø)

... and 1709 files with indirect coverage changes

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@jrhee17 jrhee17 marked this pull request as ready for review October 4, 2023 14:02
Copy link
Copy Markdown
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 great! 👍

Comment thread core/src/main/java/com/linecorp/armeria/client/ClientRequestContextBuilder.java Outdated
import io.netty.util.concurrent.EventExecutor;

@SuppressWarnings("UnstableApiUsage")
final class DefaultCancellationScheduler implements CancellationScheduler {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I didn't look at this class because I think there's no logic change. Please let me know If it's. 😎

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Did a diff with the main branch so that review can be done more easily

user@AL02437565 Projects % diff upstream-armeria/core/src/main/java/com/linecorp/armeria/internal/common/CancellationScheduler.java armeria/core/src/main/java/com/linecorp/armeria/internal/common/DefaultCancellationScheduler.java 
39,40c39
< @SuppressWarnings("UnstableApiUsage")
< public final class CancellationScheduler {
---
> final class DefaultCancellationScheduler implements CancellationScheduler {
42c41
<     private static final AtomicReferenceFieldUpdater<CancellationScheduler, CancellationFuture>
---
>     private static final AtomicReferenceFieldUpdater<DefaultCancellationScheduler, CancellationFuture>
44c43
<             CancellationScheduler.class, CancellationFuture.class, "whenCancelling");
---
>             DefaultCancellationScheduler.class, CancellationFuture.class, "whenCancelling");
46c45
<     private static final AtomicReferenceFieldUpdater<CancellationScheduler, CancellationFuture>
---
>     private static final AtomicReferenceFieldUpdater<DefaultCancellationScheduler, CancellationFuture>
48c47
<             CancellationScheduler.class, CancellationFuture.class, "whenCancelled");
---
>             DefaultCancellationScheduler.class, CancellationFuture.class, "whenCancelled");
50c49
<     private static final AtomicReferenceFieldUpdater<CancellationScheduler, TimeoutFuture>
---
>     private static final AtomicReferenceFieldUpdater<DefaultCancellationScheduler, TimeoutFuture>
52c51
<             CancellationScheduler.class, TimeoutFuture.class, "whenTimingOut");
---
>             DefaultCancellationScheduler.class, TimeoutFuture.class, "whenTimingOut");
54c53
<     private static final AtomicReferenceFieldUpdater<CancellationScheduler, TimeoutFuture>
---
>     private static final AtomicReferenceFieldUpdater<DefaultCancellationScheduler, TimeoutFuture>
56c55
<             CancellationScheduler.class, TimeoutFuture.class, "whenTimedOut");
---
>             DefaultCancellationScheduler.class, TimeoutFuture.class, "whenTimedOut");
58c57
<     private static final AtomicReferenceFieldUpdater<CancellationScheduler, Runnable>
---
>     private static final AtomicReferenceFieldUpdater<DefaultCancellationScheduler, Runnable>
60c59
<             CancellationScheduler.class, Runnable.class, "pendingTask");
---
>             DefaultCancellationScheduler.class, Runnable.class, "pendingTask");
62,63c61,62
<     private static final AtomicLongFieldUpdater<CancellationScheduler> pendingTimeoutNanosUpdater =
<             AtomicLongFieldUpdater.newUpdater(CancellationScheduler.class, "pendingTimeoutNanos");
---
>     private static final AtomicLongFieldUpdater<DefaultCancellationScheduler> pendingTimeoutNanosUpdater =
>             AtomicLongFieldUpdater.newUpdater(DefaultCancellationScheduler.class, "pendingTimeoutNanos");
93c92
<     public CancellationScheduler(long timeoutNanos) {
---
>     DefaultCancellationScheduler(long timeoutNanos) {
99c98
<      * Initializes this {@link CancellationScheduler}.
---
>      * Initializes this {@link DefaultCancellationScheduler}.
100a100
>     @Override
137a138
>     @Override
141a143
>     @Override
176a179
>     @Override
295a299
>     @Override
299a304
>     @Override
328a334
>     @Override
336a343
>     @Override
341a349
>     @Override
345a354
>     @Override
349a359
>     @Override
362a373
>     @Override
375a387
>     @Override
394a407
>     @Override
413a427
>     @Override
495,517d508
<     enum State {
<         INIT,
<         INACTIVE,
<         SCHEDULED,
<         FINISHING,
<         FINISHED
<     }
< 
<     /**
<      * A cancellation task invoked by the scheduler when its timeout exceeds or invoke by the user.
<      */
<     public interface CancellationTask {
<         /**
<          * Returns {@code true} if the cancellation task can be scheduled.
<          */
<         boolean canSchedule();
< 
<         /**
<          * Invoked by the scheduler with the cause of cancellation.
<          */
<         void run(Throwable cause);
<     }
< 
user@AL02437565 Projects %

Copy link
Copy Markdown
Contributor

@minwoox minwoox Oct 11, 2023

Choose a reason for hiding this comment

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

So I guess there's no logic changes then. 😉

Copy link
Copy Markdown
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 great, thanks! 😄


@Override
public long timeoutNanos() {
return 0;
Copy link
Copy Markdown
Contributor

@minwoox minwoox Oct 11, 2023

Choose a reason for hiding this comment

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

Will MAX_VALUE be more appropriate?
Never mind, 0 will be fine.

}
}
static CancellationScheduler finished(boolean server) {
final CancellationScheduler cancellationScheduler = of(0);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

minor) Should we cache and reuse?

if (server) {
  return serverfinishedCancellationScheduler;
} else {
  ...
}

@jrhee17 jrhee17 force-pushed the refactor/init-cancel-scheduler-1 branch from 6864add to 0bc6edd Compare October 17, 2023 10:07
Copy link
Copy Markdown
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, @jrhee17 👍👍

@jrhee17 jrhee17 merged commit 6a7f457 into line:main Oct 18, 2023
Bue-von-hon pushed a commit to Bue-von-hon/armeria that referenced this pull request Nov 10, 2023
Motivation:

While working on line#5212, I realized
that `noopResponseCancellationScheduler` is an already completed
scheduler.
When we create a `DefaultClientRequestContext` for the upgrade request,
we use this scheduler.

https://github.com/line/armeria/blob/8e139d972f5137f9d1805ddda4a7aeae60fecd40/core/src/main/java/com/linecorp/armeria/client/HttpClientPipelineConfigurator.java#L550

However, actually what we want is a scheduler which never completes
instead of an already completed scheduler.
For this reason, I propose that we separate a
- `CancellationScheduler#noop`: signifies a scheduler which never
completes
- `CancellationScheduler#finished`: signifies a scheduler which already
completed

Note that the upgrade request is already bound by `connectTimeout`, so
it is safe to use a `CancellationScheduler` which never completes.

Modifications:

- Rename `CancellationScheduler` to `DefaultCancellationScheduler`, and
reduce visibility
- Introduce an interface `CancellationScheduler`
- Introduce factory methods `CancellationScheduler#of`,
`CancellationScheduler#noop`, `CancellationScheduler#finished`

Result:

- It is easier to handle line#5212.
- Cleaner code overall.

<!--
Visit this URL to learn more about how to write a pull request
description:

https://armeria.dev/community/developer-guide#how-to-write-pull-request-description
-->
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.

3 participants