-
Notifications
You must be signed in to change notification settings - Fork 183
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
Untangling GrpcServerBuilder
from HttpServerBuilder
#1861
Conversation
Motivation: The methods in `GrpcServerBuilder` are often only delegating to the underlying HTTP transport builder. It will be beneficial if the API can be simplified and have only gRPC specific settings. The first step is to deprecate the methods which can be called directly on the underlying `HttpServerBuilder` and to introduce a method for configuring that builder. Modifications: - Introduce a `GrpcServerBuilder.HttpInitializer` interface and a corresponding `GrpcServerBuilder#initialize` method which accepts the initializer for the underlying `HttpServerBuilder` instance, - Deprecate methods which have only served the purpose of delegating to the underlying HTTP transport builder, - Refactor tests to use the new approach to showcase it works. Result: The API of `GrpcServerBuilder` is prepared for removal of the deprecated methods in 0.42 release and the API is more specific, while maintaining the same level of configurability.
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 deprecations will be removed for 0.42 correct?
private boolean appendedCatchAllFilter; | ||
|
||
public abstract GrpcServerBuilder initializer(HttpInitializer initializer); |
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.
Does this affect the order of applied configurations? In other words, when we are in this transient state with the deprecations, if users call appendHttpServiceFilter
directly (deprecated methods) and they also start using the initializer
where they also might append filters, is the order of the filters consistent to what it would have been if that new API wasn't there? If thats the case, can we prevent bad configuration, e.g. allowing exclusively one way or the other.
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.
Great observation! To answer – the order would not be preserved as the initializer
is applied at build time, while the deprecated methods have an immediate effect on the underlying builder. We could add documentation, but that would not prevent users from possible issues. I will try to implement a mutually exclusive mechanism, bear with me.
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.
Ok, I found where this comes from :)
We should not be extra caution in this scenario. Users either migrate all appendHttpServiceFilter
methods or nothing. If they use a mixed approach - this is their problem, because we recommend migration, not mixing. We can clarify it in javadoc, but no need to add extra guards in the code. Neither multi-address nor partitioned client builders have similar guards.
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 one way of looking at it. It is not always the case that users can migrate everything at the same time - say they receive a preconfigured builder from their own library and append their own configurations. In this case it's probably better to actually fail instead of being forced to debug production issues which are not straightforward to understand. I was happy with @tkountis suggestion so I implemented the validation. But I agree, a consistent approach would be to not validate the use as the other builders didn't check the state. Also, an exception is perhaps too aggressive as it might happen at runtime in a situation that is not dramatic for the user and can go past automated tests where the logic is not validated. So I decided to remove the logic. But I believe it's a matter of opinion that ServiceTalk takes -> we could as well transition into a more safe-to-use/prevent-users-from-shooting-themselves-in-the-foot approach.
Yes, that is the intention to remove the deprecated methods. |
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.
LGTM 🚢
// been used to build a client. | ||
if (initializer != null) { | ||
if (underlyingBuilderCalledDirectly) { | ||
throw new IllegalStateException("Builder configured with " + HttpInitializer.class.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.
Why this is a problem to mix approaches? Top level methods delegate to httpServerBuilder
, initializer also invokes methods on the same httpServerBuilder
. Order should not matter for most of the settings except "appendFilter", which is fine.
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 replied in the other thread as a general comment. Regarding order of operations -> it's not just appending filters that can be a problem.
Configuring anything else at the same time can be a surprise as the actual implementation controls the order of initializers. Consider the following code:
GrpcServers.forAddress(localAddress(0))
.initializeHttp(builder -> builder.sslConfig(trustedServerConfig()))
.sslConfig(untrustedServerConfig())
.listenAndAwait(serviceFactory());
The actual SSL config will be trustedServerConfig()
now and would also have been before my recent change. However the user might as well expect that the order of calls should determine the actual outcome and expect untrustedServerConfig()
to be actually applied.
servicetalk-grpc-api/src/main/java/io/servicetalk/grpc/api/GrpcServerBuilder.java
Outdated
Show resolved
Hide resolved
@bondolo this is not a breaking change, we expect to cherry-pick this into 0.41 |
…enamed initializer to initializeHttp
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.
LGTM after the last comments addressed.
Nice change! Thanks @tkountis for a proposal ❤️
servicetalk-grpc-api/src/main/java/io/servicetalk/grpc/api/GrpcServerBuilder.java
Outdated
Show resolved
Hide resolved
servicetalk-grpc-netty/src/main/java/io/servicetalk/grpc/netty/DefaultGrpcServerBuilder.java
Outdated
Show resolved
Hide resolved
servicetalk-grpc-netty/src/main/java/io/servicetalk/grpc/netty/DefaultGrpcServerBuilder.java
Outdated
Show resolved
Hide resolved
servicetalk-grpc-netty/src/main/java/io/servicetalk/grpc/netty/DefaultGrpcServerBuilder.java
Outdated
Show resolved
Hide resolved
servicetalk-grpc-api/src/main/java/io/servicetalk/grpc/api/GrpcServerBuilder.java
Outdated
Show resolved
Hide resolved
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.
Discovered when I reviewed the client-side:
servicetalk-grpc-netty/src/main/java/io/servicetalk/grpc/netty/DefaultGrpcServerBuilder.java
Outdated
Show resolved
Hide resolved
Motivation: The methods in `GrpcServerBuilder` are often only delegating to the underlying HTTP transport builder. It will be beneficial if the API can be simplified and have only gRPC specific settings. The first step is to deprecate the methods which can be called directly on the underlying `HttpServerBuilder` and to introduce a method for configuring that builder. Modifications: - Introduce a `GrpcServerBuilder.HttpInitializer` interface and a corresponding `GrpcServerBuilder#initialize` method which accepts the initializer for the underlying `HttpServerBuilder` instance, - Deprecate methods which have only served the purpose of delegating to the underlying HTTP transport builder, - Added default implementations for deprecated methods, - Made the builder reconfigurable after first build, - Clarified javadoc for lifecycleObserver overriding by initializer, - Refactor tests to use the new approach to showcase it works. Result: The API of `GrpcServerBuilder` is prepared for removal of the deprecated methods in 0.42 release and the API is more specific, while maintaining the same level of configurability.
Cherry-picked for 0.41: f8aaa8d |
Motivation:
The methods in
GrpcServerBuilder
are often only delegating to theunderlying HTTP transport builder. It will be beneficial if the API can
be simplified and have only gRPC specific settings. The first step is to
deprecate the methods which can be called directly on the underlying
HttpServerBuilder
and to introduce a method for configuring thatbuilder.
Modifications:
GrpcServerBuilder.HttpInitializer
interface and acorresponding
GrpcServerBuilder#initialize
method which accepts theinitializer for the underlying
HttpServerBuilder
instance,the underlying HTTP transport builder,
Result:
The API of
GrpcServerBuilder
is prepared for removal of the deprecatedmethods in 0.42 release and the API is more specific, while maintaining
the same level of configurability.