-
Notifications
You must be signed in to change notification settings - Fork 181
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
Introduce HttpProviders
and GrpcProviders
#2137
Changes from all commits
957a6cb
e1082b3
ac1530d
f2c11b4
fa38404
74c9a81
e24d583
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
/* | ||
* Copyright © 2022 Apple Inc. and the ServiceTalk project authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.servicetalk.grpc.api; | ||
|
||
import java.time.Duration; | ||
|
||
import static java.util.Objects.requireNonNull; | ||
|
||
/** | ||
* A {@link GrpcClientBuilder} that delegates all methods to another {@link GrpcClientBuilder}. | ||
* | ||
* @param <U> the type of address before resolution (unresolved address) | ||
* @param <R> the type of address after resolution (resolved address) | ||
*/ | ||
public class DelegatingGrpcClientBuilder<U, R> implements GrpcClientBuilder<U, R> { | ||
|
||
private GrpcClientBuilder<U, R> delegate; | ||
|
||
public DelegatingGrpcClientBuilder(final GrpcClientBuilder<U, R> delegate) { | ||
this.delegate = requireNonNull(delegate); | ||
} | ||
|
||
/** | ||
* Returns the {@link GrpcClientBuilder} delegate. | ||
* | ||
* @return Delegate {@link GrpcClientBuilder}. | ||
*/ | ||
protected final GrpcClientBuilder<U, R> delegate() { | ||
return delegate; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return this.getClass().getSimpleName() + "{delegate=" + delegate() + '}'; | ||
} | ||
|
||
@Override | ||
public GrpcClientBuilder<U, R> initializeHttp(final HttpInitializer<U, R> initializer) { | ||
delegate = delegate.initializeHttp(initializer); | ||
return this; | ||
} | ||
|
||
@Override | ||
public GrpcClientBuilder<U, R> defaultTimeout(final Duration defaultTimeout) { | ||
delegate = delegate.defaultTimeout(defaultTimeout); | ||
return this; | ||
} | ||
|
||
@Override | ||
public <Client extends GrpcClient<?>> Client build(final GrpcClientFactory<Client, ?> clientFactory) { | ||
return delegate.build(clientFactory); | ||
} | ||
|
||
@Override | ||
public <BlockingClient extends BlockingGrpcClient<?>> BlockingClient buildBlocking( | ||
final GrpcClientFactory<?, BlockingClient> clientFactory) { | ||
return delegate.buildBlocking(clientFactory); | ||
} | ||
|
||
@Override | ||
public MultiClientBuilder buildMulti() { | ||
return delegate.buildMulti(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
/* | ||
* Copyright © 2022 Apple Inc. and the ServiceTalk project authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.servicetalk.grpc.api; | ||
|
||
import io.servicetalk.concurrent.api.Single; | ||
|
||
import java.time.Duration; | ||
|
||
import static java.util.Objects.requireNonNull; | ||
|
||
/** | ||
* A {@link GrpcServerBuilder} that delegates all methods to another {@link GrpcServerBuilder}. | ||
*/ | ||
public class DelegatingGrpcServerBuilder implements GrpcServerBuilder { | ||
|
||
private GrpcServerBuilder delegate; | ||
|
||
public DelegatingGrpcServerBuilder(final GrpcServerBuilder delegate) { | ||
this.delegate = requireNonNull(delegate); | ||
} | ||
|
||
/** | ||
* Returns the {@link GrpcServerBuilder} delegate. | ||
* | ||
* @return Delegate {@link GrpcServerBuilder}. | ||
*/ | ||
protected final GrpcServerBuilder delegate() { | ||
return delegate; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return this.getClass().getSimpleName() + "{delegate=" + delegate() + '}'; | ||
} | ||
|
||
@Override | ||
public GrpcServerBuilder initializeHttp(final HttpInitializer initializer) { | ||
delegate = delegate.initializeHttp(initializer); | ||
return this; | ||
} | ||
|
||
@Override | ||
public GrpcServerBuilder defaultTimeout(final Duration defaultTimeout) { | ||
delegate = delegate.defaultTimeout(defaultTimeout); | ||
return this; | ||
} | ||
|
||
@Override | ||
public GrpcServerBuilder lifecycleObserver(final GrpcLifecycleObserver lifecycleObserver) { | ||
delegate = delegate.lifecycleObserver(lifecycleObserver); | ||
return this; | ||
} | ||
|
||
@Override | ||
public Single<GrpcServerContext> listen(final GrpcBindableService<?>... services) { | ||
return delegate.listen(services); | ||
} | ||
|
||
@Override | ||
public Single<GrpcServerContext> listen(final GrpcServiceFactory<?>... serviceFactories) { | ||
return delegate.listen(serviceFactories); | ||
} | ||
|
||
@Override | ||
public GrpcServerContext listenAndAwait(final GrpcServiceFactory<?>... serviceFactories) throws Exception { | ||
return delegate.listenAndAwait(serviceFactories); | ||
} | ||
|
||
@Override | ||
public GrpcServerContext listenAndAwait(final GrpcBindableService<?>... services) throws Exception { | ||
return delegate.listenAndAwait(services); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
/* | ||
* Copyright © 2022 Apple Inc. and the ServiceTalk project authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.servicetalk.grpc.api; | ||
|
||
import io.servicetalk.http.api.HttpProviders; | ||
import io.servicetalk.http.api.HttpProviders.HttpServerBuilderProvider; | ||
import io.servicetalk.http.api.HttpProviders.SingleAddressHttpClientBuilderProvider; | ||
|
||
import java.net.SocketAddress; | ||
import java.util.ServiceLoader; | ||
|
||
/** | ||
* A holder for all gRPC-specific providers that can be registered using {@link ServiceLoader}. | ||
bondolo marked this conversation as resolved.
Show resolved
Hide resolved
bondolo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* | ||
* @see HttpProviders | ||
*/ | ||
public final class GrpcProviders { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When I think of the name There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "provider" is a term defined by |
||
|
||
private GrpcProviders() { | ||
// No instances. | ||
} | ||
|
||
/** | ||
* Provider for {@link GrpcClientBuilder}. | ||
* <p> | ||
* An HTTP layer should use {@link SingleAddressHttpClientBuilderProvider}. | ||
*/ | ||
@FunctionalInterface | ||
public interface GrpcClientBuilderProvider { | ||
|
||
/** | ||
* Returns a {@link GrpcClientBuilder} based on the address and pre-initialized {@link GrpcClientBuilder}. | ||
* <p> | ||
* This method may return the pre-initialized {@code builder} as-is, or apply custom builder settings before | ||
* returning it, or wrap it ({@link DelegatingGrpcClientBuilder} may be helpful). | ||
* | ||
* @param address a remote address used to create a {@link GrpcClientBuilder}, it can be resolved or unresolved | ||
* based on the factory used | ||
* @param builder pre-initialized {@link GrpcClientBuilder} | ||
* @param <U> the type of address before resolution (unresolved address) | ||
* @param <R> the type of address after resolution (resolved address) | ||
* @return a {@link GrpcClientBuilder} based on the address and pre-initialized {@link GrpcClientBuilder}. | ||
* @see DelegatingGrpcClientBuilder | ||
*/ | ||
<U, R> GrpcClientBuilder<U, R> newBuilder(U address, GrpcClientBuilder<U, R> builder); | ||
} | ||
|
||
/** | ||
* Provider for {@link GrpcServerBuilder}. | ||
* <p> | ||
* An HTTP layer should use {@link HttpServerBuilderProvider}. | ||
*/ | ||
@FunctionalInterface | ||
public interface GrpcServerBuilderProvider { | ||
|
||
/** | ||
* Returns a {@link GrpcServerBuilder} based on the address and pre-initialized {@link GrpcServerBuilder}. | ||
* <p> | ||
* This method may return the pre-initialized {@code builder} as-is, or apply custom builder settings before | ||
* returning it, or wrap it ({@link DelegatingGrpcServerBuilder} may be helpful). | ||
* | ||
* @param address a server address used to create a {@link GrpcServerBuilder} | ||
* @param builder pre-initialized {@link GrpcServerBuilder} | ||
* @return a {@link GrpcServerBuilder} based on the address and pre-initialized{@link GrpcServerBuilder}. | ||
idelpivnitskiy marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* @see DelegatingGrpcServerBuilder | ||
*/ | ||
GrpcServerBuilder newBuilder(SocketAddress address, GrpcServerBuilder builder); | ||
} | ||
} |
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.
When I had all builder methods as
Spotbugs complained that the return value is discarded. I though to suppress it because all our builder implementations always return
this
. But then considered a use-case when users may have an immutable provider or builder impl that always return a new instance. LMK what you think. Should we support that and reassign thedelegate
or is it better to keepdelegate
asfinal
?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 don't see any alternative to assigning
delegate
with each delegate invocation. Eventually someone will get clever and implement a builder which doesn't returnthis
and we will have to fix it anyway. I've had to fix very non-obvious problems more than once where failing to reassign the builder at the end of the chain meant that the operations in the chain were lost. It is always a frustrating bug to locate.