-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Supporting context-propagation ContextSnapshot restore with an operator #3149
Comments
(1) Explicit approachExplored in #3147 Expected APIThe API is close to interface Wrappers {
<T,R> Function<T, R> function(Function<T, R> original);
//and many others... The one instance created by the operator would use context-propagation API when wrapping functions, but that's transparently done. User needs to call out where and what to wrap though: aStringFlux.withFunctionalWrappers(
source, wrapper -> source.map(wrapper.function(
v -> v.length()
))
) CaveatsThe wrapping resets thread locals the moment the function has finished. This could be hard to grasp for some users, eg. when wrapping a This approach also cannot work if the "scoped" chain of operators is built by third-parties that are not aware of the Possible variantRather than a dedicated operator, use aStringFlux.transformDeferredContextual(
ContextPropagation.withWrappers(
(source, wrapper) -> source.map(wrapper.function(
v -> v.length()
))
)
); User writes a Or add a variant with a configurable resource:
Like in the following: asStringFlux.transformDeferredContextual(
ContextPropagation::wrappers, //instantiate a `Wrappers`
//can be also written as a more verbose Function: ctx -> ContextPropagation.wrappers(ctx),
//separately, define the transformation. except now we get a Wrappers resource
(source, w) -> source.map(w.function(
v -> v.length
))
); |
(2) Scope with Implicit Flag approachWhere to put the Flag and how to define its rangeOne place is the Reactor Another idea would be to consider this flag as "Publisher-level configuration". There is currently no support for this so it implies A LOT of work, with a lot of potential caveats/blind spots. Expected APIWe could introduce a new operator or use the flux
.transformDeferredContextual(f ->
f.map(v -> v)
); The Another option is to have a pair of scope-bounding operators: flux
.startScope()
.map(v -> v)
.endScope(); In both cases, if flux
.contextWrite(c -> c.delete(SCOPED_KEY)
.map(v -> v)
.contextWrite(c -> c.put(SCOPED_KEY, SOMETHING); Behind the scenes, Note that Caveats
In the
In the
|
(3) Sub-API approachExpected API??? CaveatNeed to come up with a signature that the type system understands rather than ending up with something that users will need to massage into the type system.
🚫 This is a blocker, I wasn't able to find an elegant way to supporting this with anything that changes the return type (which includes Benefits
|
(4) Implicit restoration support in a couple of selected operatorsFocusing eg. on Explored in #3180 Caveat
|
This commit adds implicit behavior to `handle` and `tap` operators when used in conjunction with `contextCapture()` down the chain. By way of a marker key added by `contextCapture`, both operators detect context-propagation snapshot capture was performed and they use context-propagation snapshot restoration of thread locals around their respective user-provided code: - `BiConsumer#accept` for `handle` - each method of the `SignalListener` interface for `tap` Relates to #3149.
The goal of this feature request is to support
context-propagation
library, and more specifically the restoration of aContextSnapshot
intoThreadLocal
s, in a more integrated fashion.Namely, we would like to somehow wrap user-provided "functions" (or actually any functional interface required in the Flux/Mono API) so that each restores the thread locals from the Reactor
Context
(and clears after itself).The onus can be put on the users themselves by providing some facility to perform the wrapping, or can be implicit.
Considered Alternatives
Broad alternatives
FunctionalWrappers
instance is exposed to the user which must wrap each of her functions using said instance. one instance perContextView
/subscriptionFlux
API, except it just defines a blueprint that will be applied at subscription time with additional wrapping of the user-provided functionsThe text was updated successfully, but these errors were encountered: