-
Notifications
You must be signed in to change notification settings - Fork 62
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
Revamp API and SPI #32
Conversation
heiko-braun
commented
Jul 7, 2017
- Refactor builder builder pattern
- Introduce SPI delegation (using service loader)
- Change API terms
- Introduce SPI delegation (using service loader) - Change API terms
The PR introduces a revamped API and that I would like to use as a baseline moving forward. It uses more descriptive API terms and introduces a contract between the implementing runtime and health API using the Implementors are expected to provide an implementation of Let me know what you think. |
|
||
public abstract Optional<Map<String, Object>> getAttributes(); | ||
|
||
private static <T> T find(Class<T> service) { |
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.
implementation detail but the SPIFactory should be cached instead of loading it from the ServiceLoader every time a ResponseBuilder is invoked.
It's reasonable to use the same SPIFactory for the whole lifetime of the application
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.
agreed, we will improve this when moving forward with this PR
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.
@jmesnil done
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 name SPIFactory is not good. ResponseResolver is a better name for it and it follows the similar name convention as config.
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.
You need one more method setInstance so that it works in the OSGi environment. See ConfigProviderResolver.java.
try { | ||
Iterator<T> iterator = ServiceLoader.load(service, Response.class.getClassLoader()).iterator(); | ||
|
||
if (iterator.hasNext()) { |
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.
Assuming that a correct configured application has a single SPIFactory, we should check for multiple instances instead of letting the latest one that is loaded win.
(Have a look at https://github.com/eclipse/microprofile-config/blob/master/api/src/main/java/org/eclipse/microprofile/config/spi/ConfigProviderResolver.java#L134 for a similar use case)
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.
@jmesnil Done
* The ResponseBuilder class is reserved for an extension by implementation providers. | ||
* </p> | ||
*/ | ||
public abstract class ResponseBuilder { |
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'd be good to have a Response state(boolean up)
method too (as proposed in #23 for the previous API).
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.
yes, once this is accepted (merged) we should add the changes
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.
@jmesnil done
*/ | ||
public interface HealthStatus { | ||
public interface SPIFactory { |
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.
Name is generic and non-descriptive. Maybe something like ResponseBuilderFactory
instead?
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 intended to capture all possible SPI contracts. ResponseBuilder
is currently the only one we have, but who knows?
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.
If there is differents SPI contracts, I'd expect to load each through the ServiceLoader with their respective contract interface (instead of grouping them in a single SPIFactory class).
Especially is some contracts are optional and other mandatory
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.
yes, that would work also.
|
||
public enum State { UP, DOWN } | ||
|
||
public abstract String getName(); |
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 do not think that the name of the health check belongs to the Response
.
I don't see an use case where a health check would return different names when it is called.
This may require a separate issue to discuss this but I think the name
of the health check should be set on the HealthCheck
. In the design document, I proposed to introduce a @Health(name)
annotation to name a HealthCheck
(and remove the info from the Response
).
Please note that it's not clear to me what a name of a health check implies.
As far as I can tell, nothing in the spec or the API mandates uniqueness of names.
But the HTTP protocol document implies otherwise:
The JSON response MUST contain the
id
entry specifying the name of the check, to support protocols that support external identifier (i.e. URI)
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.
well, it is part of the Response
payload. How it's get's there is a different question. I like your proposal for @Health(name)
annotations
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.
following my above response: i think name
needs to stay in Response
, but can be removed from ResponseBuilder
, no?
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.
After having written #34, I'm almost making my mind that is is up to the API provider to "name" the procedures when it is returning its payload.
I'm not sure we need to add the name
to the Response
though.
The provide MUST name the health check in the HTTP payload but it is its responsibility to give it an unique name (base on my proposed @Health
annotation and/or using unique generated IDs to take into account multiple deployments).
Implementation-wise it seems to be trickier to add the name to the Response from the ResponseBuilder instead of waiting to create the HTTP payload to do that.
At that point, I have access to all health check procedures and I can ensure uniqueness among their names.
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 suggest we move this to a separate thread (issue), wdyt? I'd prefer to consolidate the API first and then enhance it, a piece meal approach.
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.
+1 to move it to another issue (#34 can be used for this)
@jmesnil Do you see anything else that would hold back merging this PR? @Emily-Jiang Any thoughts on this? |
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.
looks good to me
|
||
public abstract Optional<Map<String, Object>> getAttributes(); | ||
|
||
private static <T> T find(Class<T> service) { |
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 name SPIFactory is not good. ResponseResolver is a better name for it and it follows the similar name convention as config.
|
||
public abstract Optional<Map<String, Object>> getAttributes(); | ||
|
||
private static <T> T find(Class<T> service) { |
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.
You need one more method setInstance so that it works in the OSGi environment. See ConfigProviderResolver.java.
|
||
public abstract Response state(boolean up); | ||
|
||
|
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.
You need a build() method to create a response object. Delete all the up, down and state, which should belong to Response.java.
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.
@Emily-Jiang let's address this in a separate PR
public interface SPIFactory { | ||
|
||
ResponseBuilder createResponseBuilder(); | ||
|
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 think the structure is confusing. You need Response, Response Builder and ResponseResolver. ResponseResolver is to use service loader pattern to load an implementation of ResponseResolver. Response should just be a clean object to contain name, attributes, up, down, state etc.
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.
@Emily-Jiang let's address this in a separate PR
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.
@heiko-braun This whole PR is misleading. The structure is incorrect in my view. I would rather redo this PR instead of moving to a different PR. You can close this PR but not commit it and start a new one if you like.
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.
That's your point of view @Emily-Jiang. However @jmesnil and I think differently and hence I've decided to merge this PR. Feel free to submit proposals based on the the new API and we take it from there.