- 
                Notifications
    
You must be signed in to change notification settings  - Fork 23
 
copy initial proposed API and readme from sandbox #4
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
Conversation
Signed-off-by: Nathan Rauh <nathan.rauh@us.ibm.com>
| 
           LGTM: we can start with that and work through remaining issues afterwards.  | 
    
| * are removed from the thread of execution for the duration of the | ||
| * action or task.</p> | ||
| */ | ||
| String[] context() default { ThreadContext.APPLICATION, ThreadContext.CDI, ThreadContext.SECURITY }; | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should ALL be the default?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The prior default was chosen to match the EE Concurrency requirement for only a specific set of context types to be propagated by default, where
 @Inject @ManagedExecutorConfig ManagedExecutor executor1;
would create an instance with the same context propagation as
 @Inject ManagedExecutor executor2;
which would also have the same context propagation as EE Concurrency's default instance,
 @Resource ManagedExecutorService executor3;
The idea was to allow a container that is both MP Concurrency and EE Concurrency to return the same instance from all of these.
That said, it would be possible to instead default to ALL and require the use of different instance than the EE Concurrency default instance if that would be more useful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking about this some more, defaulting to ThreadContext.ALL would mean that if someone implemented a provider for transaction context that was capable of propagating transactions, then those would also propagate by default. I don't think we want to go that far. It seems better for performance and predictability that we default to the more limited set of core contexts. The user can always specify ALL if they want it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking about this some more, defaulting to ThreadContext.ALL would mean that if someone implemented a provider for transaction context that was capable of propagating transactions, then those would also propagate by default.
If an user provide a transaction context, surely the default one will be overriden. You won't need two of them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 'someone' that I was referring wasn't intended to mean the end user. I was referring to a container implementation of transactions (the transaction manager). In the event that an end user did provide a conflicting implementation of one of already-provided context types, I think we discussed that would be considered an error path for now. Allowing an override of context provided by someone else seems outright dangerous, and in the case of transactions would probably lead to data integrity issues.
| * <code>ManagedExecutor</code> or <code>ThreadContext</code> must invoke the | ||
| * <code>end</code> method.</p> | ||
| */ | ||
| public interface ActiveThreadContext { | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would say this is a controller. How about ThreadContextController?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like how the name ThreadContextController starts with ThreadContext in the same way that ThreadContextProvider and ThreadContextSnapshot do, which will cause them to naturally be listed together when interfaces are shown alphabetically. ActiveThreadContext seems more descriptive/clear, except could be confusing after it is ended, so I'm willing to change it as you suggest.
| * </code></pre> | ||
| * | ||
| * @throws IllegalStateException if invoked more than once on the same instance. | ||
| */ | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should a method e.g. getState() to return whether it is active or not. end() can check whether it is active or not. If it is, end it. If not, ignore it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, we can add this, maybe as a boolean isEnded() given that there are only 2 states.
| * does not support capturing context from the current thread and | ||
| * propagating it to other threads. | ||
| */ | ||
| ThreadContextSnapshot currentContext(Map<String, String> props); | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be String, String? Maybe String, Object has more coverage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is Map<String, String> for compatibility with EE Concurrency execution properties. Switching to Object would force code to deal with unwanted casting.
| * either captured from a thread or otherwise representing an | ||
| * empty/default context. | ||
| */ | ||
| ActiveThreadContext begin(); | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you put this method to ThreadContextController?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leaving it here enforces the contract that each ActiveThreadContext/ThreadContextController represents exactly one contextualized execution. If we move it, then the implementer must deal with the possibility that the user tries to invoke begin multiple times on the same instance, or tries to re-begin one that has already ended. I can't see a reason to place this additional burden/lack of clarity upon the provider of thread context without any clear benefit that would be achieved by doing so.
| 
           @njr-11 please take a look at my comments.  | 
    
Signed-off-by: Nathan Rauh <nathan.rauh@us.ibm.com>
| 
           @Emily-Jiang thanks for the review. I have added a pull with several code review fixes (per comments above) as well as a couple of spelling and punctuation fixes that Nathan M and myself spotted while proofreading.  | 
    
| * | ||
| * <code>META-INF/services/org.eclipse.microprofile.concurrent.spi.ThreadContextProvider</code> | ||
| * | ||
| * <p>The content of the aforementioned file must be a single line that specifies the | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually it may be more than one line, each with a different implementation of the interface.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks - good catch. We definitely want to allow for multiple. I have added a commit correcting the language here to indicate at least one instead of single.
Signed-off-by: Nathan Rauh <nathan.rauh@us.ibm.com>
| 
           Can we please merge these two PRs ASAP and fix whatever remaining issue afterwards? It really doesn't help implementation to keep these in PRs.  | 
    
| * fully qualified name of the <code>ThreadContextProvider</code> implementation.</p> | ||
| * <p>The content of the aforementioned file must be one or more lines, each specifying | ||
| * the fully qualified name of a <code>ThreadContextProvider</code> implementation | ||
| * that is provided within the JAR file.</p> | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
| * @return true if <code>endContext</code> was invoked on this controller, | ||
| * otherwise false. | ||
| */ | ||
| boolean isEnded(); | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that this prevents implementing this interface as a @FunctionalInterface as I had before:
	public ThreadContextSnapshot currentContext(Map<String, String> props) {
		MyContext capturedContext = MyContext.get();
		return () -> {
			MyContext movedContext = MyContext.get();
			MyContext.set(capturedContext);
			return () -> {
				MyContext.set(movedContext);
			};
		};
	}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for spotting this as well. I was previously willing to accommodate the request to have an isEnded method when I saw no benefit either way for including or not including it. However, as you have pointed out, this makes it no longer be a functional interface. I have added a commit to remove the isEnded method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I noticed it by accident, but I thought it made a good argument in favour of not having that extra method. I suppose we should also add @FunctionalInterface to the interfaces (at least if/until we decide to add methods to it) to make sure that we don't add any new method without just cause.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea. @FunctionalInterface is added to both ThreadContextController and ThreadContextSnapshot.  I think as long as they are able to remain functional interfaces for the initial release, they should hopefully remain that way.  We won't want to cause a lot of churn in the SPI once implementations of it start to be provided.
Signed-off-by: Nathan Rauh <nathan.rauh@us.ibm.com>
e54b29d    to
    08afbbd      
    Compare
  
    
pull fixes #3
Signed-off-by: Nathan Rauh nathan.rauh@us.ibm.com