-
Notifications
You must be signed in to change notification settings - Fork 23
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
Adding context to existing CS/CF instances #173
Comments
The possibility of an equivalent on ManagedExecutor for withContextCapture was something that came to mind while working on v1.0, but I had put the thought on hold to finish off the initial release, recognizing that thenCompose does provide a working (albeit ugly) solution as a stopgap measure. I'd rather not see a ManagedExecutor supplied to a ThreadContext.Builder or new variants of the withContextCapture(stage, executor) methods to accept an executor parameter. In both cases, that creates confusion with conflicting context propagation settings (the managed executor's vs the thread context's). Instead, I think the right approach here is to create a parallel interface on ManagedExecutor for the Java 11 CompletableFuture.copy method, which directly matches the behavior one would expect out of a withContextCapture equivalent (
Here's a draft of what the JavaDoc might look like, copying directly from withContextCapture,
The above addresses the first half of the issue, and since the comment is already getting a bit long, I'm going to stop here and post a second comment for the second half discussing configuring/using default executor services. |
Regarding the second set of questions, OpenLiberty doesn't implement a Specifically regarding the proposal, that means I'm fine with the addition of: With respect to having withDefaultExecutorService on ThreadContext.Builder, it seems out of place. ThreadContext ought to only concern thread context and only be used for thread context, so I don't think we should add withDefaultExecutorService there, but hopefully my proposal in the previous comment to add managedExecutor.copy will cover all of the scenarios where that would have been needed. With regard to ManagedExecutor.Builder.withDefaultExecutorService(executor), I'm undecided. I can see where this might provide additional flexibility in some cases, but I can also foresee ambiguity and potential collisions between the supplied executor's behavior and other builder config like the maxQueued/maxAsync settings. With that in mind, a different option could be |
I was suggesting an
|
Cool.
They would indeed, but I thought it would make it more regular, and allow people to specify an
Well, there's always going to be a bit of a question when it comes to that, especially because we can't query the But if you view the
That would be easy to implement for us. But then I feel we could solve a bunch of issues by adding
That is indeed the behaviour I expect. If that seems acceptable, then |
Agreed. I would expect to have signatures for both CompletionStage and CompletableFuture, just like withContextCapture has.
If you want to have a It seems like we have a lot of agreement already on many of the proposed interfaces. new ContextManager.Builder methods: new ThreadContext methods: updated ThreadContext method JavaDoc (to allow async operations using built-in or configured executor) new ManagedExecutor methods: Having just written the above right next to each other, I can see that we need to decide between java.util.concurrent.Executor versus java.util.concurrent.ExecutorService as the parameter type for the first two methods. It doesn't make any difference to me - just make them consistent. If you don't have any other way of deciding, we could just go with Executor because it looks like that is what the CompletableFuture API uses here. |
Ah, good question. Thing is, But you're right that Given that this is on the builder for If we add |
Our global thread pool is an ExecutorService, but our implementation of ManagedExecutor is written such that Executor could alternatively be used if one was supplied, so we are compatible with either way.
This was never a concern when the default executor was a ManagedExecutor owned by the application, because the application is then just shutting down its own instance. However, when backed by our global thread pool as the default executor, we will certainly need to include a layer in between here, because shutting that down would be catastrophic and not something that applications ought to be able to do. |
In our case, we pass an As for |
So, in smallrye/smallrye-context-propagation#183 I've made an implementation of this, with the methods you mentioned, minus one:
I did not add this one because I'm not sure it brings value, I think we can wait to see if it's useful:
I had to add the notion that So I rephrased the javadoc for I also mention in In practice, I did notice a weird detail wrt the I remember a discussion about this discrepency a long time ago, but I don't remember why they differed. |
Hah, what's funny is that we already have this method as |
That's great to hear you have it prototyped!
That's fine with me. I'm not aware of any request for it either, so it's best not to add it.
ManagedExecutor lacks configuration for
Now that you can create a ThreadContext from a ManagedExecutor, I think it would make sense for us to now add the Is there a pull for these spec updates anywhere? For some reason I was thinking we had created one, but maybe that was just me thinking of the JavaDoc/method signature examples that we've been posting into this issue. |
I don't think there's a PR yet. |
Are you planning to create a PR (or already working on one)? Or would you rather have me create it? I'm fine either way, just looking to avoid duplication. It should be easy enough given that we have a bunch of draft method signatures and even some draft JavaDoc for it in the discussion above. |
I can make a PR. |
It's at #196. |
Initial proposal for #173: Adding context to existing CS/CF instances
And TCK at #197 |
@FroMage I can't find ManagedExecutor.allOf . May be it is unnecessary or it is a gap. Could you please give some comments? |
We didn't add managedExecutor.allOf because it seemed unnecessary, just a shortcut for doing:
|
@njr-11 thank you. But actually I use quarkus and it seems it does not provide microprofile-context-propagation-api 1.1 by some reason. But as I understand that managedExecutor.copy is the same thing as threadContext.withContextCapture. That is enough. |
@njr-11 I counted how often |
It would be fine with me to add it if it makes the programming model easier to use for applications. I expect the ManagedExecutor variant of allOf wouldn't be static like CompletableFuture.allOf is, because the resulting completion stage ought to be backed by a specific ManagedExecutor for the sake of any dependent stages that are added on to it. Go ahead and open an issue for it (this current issue where we are discussing this is already closed out) and we can discuss it on the MicroProfile Context Propagation call on June 10 as a possible enhancement for the next release of the spec. |
ATM we have two APIs for adding context to
CompletionStage
andCompletableFuture
:ManagedExecutor
: you can create contextualisedCompletableFuture
instances that are completed or incomplete, but you can't wrap existing instances.ThreadContext
: you can only wrap contextualisedCompletableFuture
andCompletionStage
instances, but those can't have anExecutor
defined, and will throw when callingAsync
methods.While working around a bug, I found myself having to call the
Async
methods of a CS I had wrapped usingThreadContext
, and it threw at me.Then I found myself having to switch to using
ManagedExecutor
to wrap my CS stuff, but although I could replace some calls totc.withContextPropagation(CompletableFuture.completedValue(...))
I found I could not wrap existing CS instances with that API. The bext thing I found was to use:Which is not great, but also hard to guess to people not familiar with CS and composition. I couldn't use existing
ManagedExecutor
methods to wrap a CS I did not create myself.This leads me to believe there's something missing in the spec.
Now, additionally, for SmallRye-CP we had to add a method to our impl of
ContextManager.Builder
:To be able to specify a default executor service for all built
ManagedExecutor
(unless overridden by a similar method in our impl ofManagedExecutor.Builder
).Which leads me to think that for deployments where a (single) default executor service can be specified, it shouldn't be an issue to call
Async
methods of contextualised CS/CF byThreadContext
. But the current API forbids this.Let me know how it's implemented in OpenLiberty, but if you have the same builder extensions to be able to specify a default executor service, we could add those to the spec to the three builders (
ContextManager
,ThreadContext
andManagedExecutor
) and soften the API for wrapping CS/CF fromThreadContext
wrt having a default executor?I'd also favour add a method to be able to wrap existing CS/CF to
ManagedExecutor
and adding variants inThreadContext
to be able to specify anExecutorService
when wrapping CS/CF.This way, no matter which of the two APIs you're using you should be able to wrap existing CS/CF and even override the
ExecutorService
if it turns out your platform has no default.WDYT?
I can work out a PR if you agree with the general direction. Or even do a PR just to help make a decision and discuss.
The text was updated successfully, but these errors were encountered: