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

Server-side AsyncContext initialized in lifecycle observer is lost #3111

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

idelpivnitskiy
Copy link
Member

Motivation:

If users put any data into AsyncContext inside HttpLifecycleObserver configured via HttpServerBuilder.lifecycleObserver(...) it won't be visible for filters and service because
ClearAsyncContextHttpServiceFilter is appended after HttpLifecycleObserverServiceFilter inside applyInternalFilters.

Modifications:

  1. Move ClearAsyncContextHttpServiceFilter from the beginning of noOffloadServiceFilters to applyInternalFilters. However, this move discovered another bug in path that handles
    noOffloadServiceFilters.isEmpty() case because it never adds OffloadingFilter.
  2. Refactor listenForService method to always make a copy of filters lists, then prepend/append internal filters to those copies in easy to read/understand way, and construct a single filters Stream for buildService method.
  3. Refactor OffloadingFilter to act as a regular filter factory instead of taking all further serviceFilters as pre-built factory.
  4. Rename ClearAsyncContextHttpServiceFilter singleton instance.
  5. Fix another bug when OptionalSslNegotiator binder takes a raw service instead of filteredService (user-defined filters were never applied for this path).
  6. Modify AbstractHttpServiceAsyncContextTest to test AsyncContext propagation from lifecycle observer and non-offloading filters.
  7. Modify AbstractHttpServiceAsyncContextTest to test AsyncContext initialized by early/late connection acceptor is not visible at request path.
  8. Add BlockingHttpServiceAsyncContextTest and HttpServiceAsyncContextTest to make sure AsyncContext propagation for blocking/async aggregated services is also tested.
  9. Use ParameterizedTest where possible.

Results:

  1. AsyncContext initialized inside server's lifecycle observer is visible through filter chain and services.
  2. Construction of server-side filter chain is consistent and sequential.
  3. Filters are applied for servers with optional TLS.

Motivation:

If users put any data into `AsyncContext` inside `HttpLifecycleObserver`
configured via `HttpServerBuilder.lifecycleObserver(...)` it won't be
visible for filters and service because
`ClearAsyncContextHttpServiceFilter` is appended after
`HttpLifecycleObserverServiceFilter` inside `applyInternalFilters`.

Modifications:
1. Move `ClearAsyncContextHttpServiceFilter` from the beginning of
`noOffloadServiceFilters` to `applyInternalFilters`. However, this move
discovered another bug in path that handles
`noOffloadServiceFilters.isEmpty()` case because it never adds
`OffloadingFilter`.
2. Refactor `listenForService` method to always make a copy of filters
lists, then prepend/append internal filters to those copies in easy to
read/understand way, and construct a single filters `Stream` for
`buildService` method.
3. Refactor `OffloadingFilter` to act as a regular filter factory
instead of taking all further `serviceFilters` as pre-built factory.
4. Rename `ClearAsyncContextHttpServiceFilter` singleton instance.
5. Fix another bug when `OptionalSslNegotiator` binder takes a raw
service instead of `filteredService` (user-defined filters were never
applied for this path).
6. Modify `AbstractHttpServiceAsyncContextTest` to test `AsyncContext`
propagation from lifecycle observer and non-offloading filters.
7. Modify `AbstractHttpServiceAsyncContextTest` to test `AsyncContext`
initialized by early/late connection acceptor is not visible at request
path.
8. Add `BlockingHttpServiceAsyncContextTest` and
`HttpServiceAsyncContextTest` to make sure `AsyncContext` propagation
for blocking/async aggregated services is also tested.
9. Use `ParameterizedTest` where possible.

Results:

1. `AsyncContext` initialized inside server's lifecycle observer is
visible through filter chain and services.
2. Construction of server-side filter chain is consistent and
sequential.
3. Filters are applied for servers with optional TLS.
Copy link
Contributor

@daschl daschl left a comment

Choose a reason for hiding this comment

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

Change looks good to me, I think it is an improvement also in follow-ability through the filter bootstrapping of the server. Just one nit, feel free to ignore.

One separate thing @idelpivnitskiy - since it changes the code quite a bit, just wanted to make sure that it is double checked that the new order is good and nothing ended up accidentally in the wrong spot of the filter chain. Doesn't look like it to me, just checking.

return unmodifiableList(filters);
}

private List<StreamingHttpServiceFilterFactory> initNonOffloadsServiceFilters(
Copy link
Contributor

Choose a reason for hiding this comment

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

I would suggest renaming this method to something that includes the word default so its understood that those are the default ones always added

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.

2 participants