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

Fix duration comparison bug in timeout filters and reduce code duplication #1491

Merged
merged 3 commits into from
Apr 15, 2021

Conversation

idelpivnitskiy
Copy link
Member

@idelpivnitskiy idelpivnitskiy commented Apr 15, 2021

Motivation:

Duration#compareTo is hard to understand, the result of comparison
depends on the order of arguments. This lead to a bug in
TimeoutHttpRequesterFilter and TimeoutHttpServiceFilter which always
fails payload body publisher with TimeoutException. Use a shared
utility to make isPositive check for Duration consistent across all modules.
Also, TimeoutHttpRequesterFilter and TimeoutHttpServiceFilter logic
is identical, we can reduce duplication and share the logic.

Modifications:

  • Introduce a shared DurationUtils class for common operations with
    Duration;
  • Use this utility to reduce mistakes when we check that the passed
    Duration must be positive;
  • Introduce AbstractTimeoutHttpFilterTest to share timeout logic
    between TimeoutHttpRequesterFilter and TimeoutHttpServiceFilter;
  • Add tests to verify behavior correctness for both timeout filters;
  • Adjust how the timeout filters are created in ResponseTimeoutTest
    to avoid NPE;
  • Minor improvements to make javadoc consistent between
    TimeoutHttpRequesterFilter and TimeoutHttpServiceFilter;

Result:

  1. TimeoutHttpRequesterFilter and TimeoutHttpServiceFilter do not
    fail payload body publisher before the actual timeout expires.
  2. No code duplication between timeout filters.
  3. Shared utility to consistently validate Duration in all modules.

…ation

Motivation:

`Duration#compareTo` is hard to understand, the result of comparison
depends on arguments order. This lead to a bug in
`TimeoutHttpRequesterFilter` and `TimeoutHttpServiceFilter` which always
fails payload body publisher with `TimeoutException`. Use a shared
utility to make this consistent across all modules.
Also, `TimeoutHttpRequesterFilter` and `TimeoutHttpServiceFilter` logic
is identical, we can reduce duplication and share to logic.

Modifications:

- Introduce a shared `DurationUtils` class for common operations with
`Duration`;
- Use these utility to reduce mistakes when we check that the passed
`Duration` must be positive;
- Introduce `AbstractTimeoutHttpFilterTest` to share timeout logic
between `TimeoutHttpRequesterFilter` and `TimeoutHttpServiceFilter`;
- Add tests to verify behavior correctness for both timeout filters;
- Adjust how the timeout filters are created in `ResponseTimeoutTest`
to avoid NPE;
- Minor improvements to make javadoc consistent between
`TimeoutHttpRequesterFilter` and `TimeoutHttpServiceFilter`;

Result:

1. `TimeoutHttpRequesterFilter` and `TimeoutHttpServiceFilter` do not
fail payload body publisher before the actual timeout expires.
2. No code duplication between timeout filters.
3. Shared utility to consistently validate `Duration` in all modules.
@@ -168,8 +168,8 @@ private void requestCancellationResetsStreamButNotParentConnection(StreamingHttp
// ignore
}
})
.expectError()
// .thenCancel()
// FIXME: use thenCancel() after await() instead of cancelling from inside then(...) + expectError()
Copy link
Member

Choose a reason for hiding this comment

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

can you create an issue and link it here?

Copy link
Member Author

Choose a reason for hiding this comment

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

#1492
Also added this link for FIXME comments: 43dff7c


return Single.defer(() -> {
final Duration timeout = timeoutForRequest.apply(request);
if (null != timeout && !isPositive(timeout)) {
Copy link
Member

@Scottmitch Scottmitch Apr 15, 2021

Choose a reason for hiding this comment

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

do we need todo the pre-checks? ideally the timeout operators handle this case and we can simplify here. we would pay a bit more cost to construct the operators, but if the operators don't handle this we would have to apply these pre-checks everywhere we use the operators (not ideal).

Copy link
Member Author

Choose a reason for hiding this comment

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

currently - yes. it's a feature of timeoutForRequest. if it returns null, it means no timeout. If it returns ZERO or negative => users want timeout right away.
I will keep it as-is for now. If we will move this logic to timeout operators in a follow-up, we can simplify here. For now, limiting the scope to the filters only

Copy link
Contributor

Choose a reason for hiding this comment

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

The operators do handle it, they explicitly accept negative duration which is expected to occur as a result of calculated timeouts. The appearance here of pre-checks was as a result of earlier review feedback to simplify the flow.

Copy link
Member

@Scottmitch Scottmitch Apr 15, 2021

Choose a reason for hiding this comment

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

null is is intended to impact control flow (e.g. null means "no timeout") so it is expected to check for null before applying timeout operators (e.g. doesn't make sense to apply a timeout if there is no timeout) . however if there is a timeout value the timeout operators should be able to handle it.

Copy link
Member Author

@idelpivnitskiy idelpivnitskiy Apr 15, 2021

Choose a reason for hiding this comment

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

I would consider that as a follow-up only if the operator is improved. Right now operator will always schedule a task, which creates more overhead (also does a thread hop) compare to this check.

Copy link
Member

Choose a reason for hiding this comment

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

followup sounds good: #1494

Copy link
Contributor

@bondolo bondolo left a comment

Choose a reason for hiding this comment

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

Very nice refactoring and much improved tests.

@idelpivnitskiy idelpivnitskiy merged commit 5b0100b into apple:main Apr 15, 2021
@idelpivnitskiy idelpivnitskiy deleted the fix-timeout-filters branch April 15, 2021 19:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants