Rename client configurer to customizer

This commit renames the GrpcChannelConfigurer to GrpcChannelBuilderCustomizer
to more accurately represent its purpose and for consistency with the
server-side terminology.

Additionally, a new `What's new?` doc is added to list breaking changes between
versions.

See #52

Signed-off-by: Chris Bono <chris.bono@gmail.com>
This commit is contained in:
Chris Bono
2024-12-01 10:41:27 -06:00
committed by Dave Syer
parent 17b8e9204c
commit 62499c8be2
7 changed files with 61 additions and 44 deletions

View File

@@ -22,6 +22,7 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.util.Assert;
import io.grpc.ChannelCredentials;
import io.grpc.ForwardingChannelBuilder2;
@@ -44,7 +45,7 @@ public class DefaultGrpcChannelFactory implements GrpcChannelFactory, Disposable
private final Map<String, ManagedChannel> channels = new ConcurrentHashMap<>();
private final List<GrpcChannelConfigurer> configurers = new ArrayList<>();
private final List<GrpcChannelBuilderCustomizer> customizers = new ArrayList<>();
private ChannelCredentialsProvider credentials = ChannelCredentialsProvider.INSECURE;
@@ -54,8 +55,9 @@ public class DefaultGrpcChannelFactory implements GrpcChannelFactory, Disposable
this(List.of());
}
public DefaultGrpcChannelFactory(List<GrpcChannelConfigurer> configurers) {
this.configurers.addAll(configurers);
public DefaultGrpcChannelFactory(List<GrpcChannelBuilderCustomizer> customizers) {
Assert.notNull(customizers, () -> "customizers must not be null");
this.customizers.addAll(customizers);
}
public void setVirtualTargets(VirtualTargets targets) {
@@ -71,13 +73,10 @@ public class DefaultGrpcChannelFactory implements GrpcChannelFactory, Disposable
ManagedChannelBuilder<?> target = this.builders.computeIfAbsent(authority, path -> {
ManagedChannelBuilder<?> builder = newChannel(this.targets.getTarget(path),
this.credentials.getChannelCredentials(path));
for (GrpcChannelConfigurer configurer : this.configurers) {
configurer.configure(path, builder);
}
this.customizers.forEach((c) -> c.customize(path, builder));
return builder;
});
return new DisposableChannelBuilder(authority, target);
}
/**
@@ -120,9 +119,7 @@ public class DefaultGrpcChannelFactory implements GrpcChannelFactory, Disposable
@Override
public ManagedChannel build() {
ManagedChannel channel = DefaultGrpcChannelFactory.this.channels.computeIfAbsent(this.authority,
name -> super.build());
return channel;
return DefaultGrpcChannelFactory.this.channels.computeIfAbsent(this.authority, name -> super.build());
}
}

View File

@@ -19,21 +19,21 @@ package org.springframework.grpc.client;
import io.grpc.ManagedChannelBuilder;
/**
* A functional interface for configuring a {@link ManagedChannelBuilder} for a specific
* authority.
* Callback interface that can be used to customize a {@link ManagedChannelBuilder} for a
* specific authority.
*
* @author Dave Syer
* @author Chris Bono
* @see ManagedChannelBuilder
*/
@FunctionalInterface
public interface GrpcChannelConfigurer {
public interface GrpcChannelBuilderCustomizer {
/**
* Configures the given {@link ManagedChannelBuilder} for the specified authority.
* Callback to customize a {@link ManagedChannelBuilder} instance for a specified
* authority.
* @param authority the target authority for the channel
* @param builder the builder to configure
* @param builder the builder to customize
*/
void configure(String authority, ManagedChannelBuilder<?> builder);
void customize(String authority, ManagedChannelBuilder<?> builder);
}

View File

@@ -1,4 +1,5 @@
* xref:index.adoc[Overview]
* xref:whats-new.adoc[What's new?]
* xref:getting-started.adoc[Getting Started]
* xref:server.adoc[GRPC Server]
* xref:client.adoc[GRPC Clients]

View File

@@ -82,7 +82,7 @@ spring.grpc.client.channels.local.address=0.0.0.0:9090
There is a default named channel (named "default") that you can configure in the same way, and then it will be used by default if there is no channel with the name specified in the channel creation.
Beans of type `GrpcChannelConfigurer` can be used to customize the `ChannelBuilder` before the channel is built.
Beans of type `GrpcChannelBuilderCustomizer` can be used to customize the `ChannelBuilder` before the channel is built.
This can be useful for setting up security, for example.
== The Local Server Port
@@ -99,4 +99,4 @@ The `@Bean` has to be marked as `@Lazy` to ensure that the port is available whe
SimpleGrpc.SimpleBlockingStub stub(GrpcChannelFactory channels, @LocalGrpcPort int port) {
return SimpleGrpc.newBlockingStub(channels.createChannel("0.0.0.0:" + port).build());
}
----
----

View File

@@ -0,0 +1,13 @@
= What's new?
[[what-s-new-in-0-3-0-since-0-2-0]]
== What's New in 0.3.0 Since 0.2.0
:page-section-summary-toc: 1
This section covers the changes made from version 0.2.0 to version 0.3.0.
=== Breaking Changes
==== GrpcChannelConfigurer renamed
The `GrpcChannelConfigurer` has been renamed to `GrpcChannelBuilderCustomizer` to more accurately represent its purpose and be consistent with the server-side terminology.

View File

@@ -30,7 +30,7 @@ import org.springframework.grpc.autoconfigure.client.GrpcClientProperties.NamedC
import org.springframework.grpc.autoconfigure.common.codec.GrpcCodecConfiguration;
import org.springframework.grpc.client.ChannelCredentialsProvider;
import org.springframework.grpc.client.DefaultGrpcChannelFactory;
import org.springframework.grpc.client.GrpcChannelConfigurer;
import org.springframework.grpc.client.GrpcChannelBuilderCustomizer;
import org.springframework.grpc.client.GrpcChannelFactory;
import org.springframework.grpc.client.VirtualTargets;
@@ -44,9 +44,9 @@ public class GrpcClientAutoConfiguration {
@Bean
@ConditionalOnMissingBean(GrpcChannelFactory.class)
public DefaultGrpcChannelFactory defaultGrpcChannelFactory(final List<GrpcChannelConfigurer> configurers,
public DefaultGrpcChannelFactory defaultGrpcChannelFactory(List<GrpcChannelBuilderCustomizer> customizers,
ChannelCredentialsProvider credentials, GrpcClientProperties channels, SslBundles ignored) {
DefaultGrpcChannelFactory factory = new DefaultGrpcChannelFactory(configurers);
DefaultGrpcChannelFactory factory = new DefaultGrpcChannelFactory(customizers);
factory.setCredentialsProvider(credentials);
factory.setVirtualTargets(new NamedChannelVirtualTargets(channels));
return factory;
@@ -60,7 +60,7 @@ public class GrpcClientAutoConfiguration {
}
@Bean
public GrpcChannelConfigurer baseGrpcChannelConfigurer(GrpcClientProperties channels) {
public GrpcChannelBuilderCustomizer baseGrpcChannelBuilderCustomizer(GrpcClientProperties channels) {
return (authority, builder) -> {
for (String name : channels.getChannels().keySet()) {
if (authority.equals(name)) {
@@ -101,13 +101,13 @@ public class GrpcClientAutoConfiguration {
@ConditionalOnBean(CompressorRegistry.class)
@Bean
GrpcChannelConfigurer compressionClientConfigurer(CompressorRegistry registry) {
GrpcChannelBuilderCustomizer compressionClientCustomizer(CompressorRegistry registry) {
return (name, builder) -> builder.compressorRegistry(registry);
}
@ConditionalOnBean(DecompressorRegistry.class)
@Bean
GrpcChannelConfigurer decompressionClientConfigurer(DecompressorRegistry registry) {
GrpcChannelBuilderCustomizer decompressionClientCustomizer(DecompressorRegistry registry) {
return (name, builder) -> builder.decompressorRegistry(registry);
}

View File

@@ -35,7 +35,7 @@ import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.grpc.autoconfigure.client.GrpcClientAutoConfiguration.NamedChannelVirtualTargets;
import org.springframework.grpc.client.ChannelCredentialsProvider;
import org.springframework.grpc.client.DefaultGrpcChannelFactory;
import org.springframework.grpc.client.GrpcChannelConfigurer;
import org.springframework.grpc.client.GrpcChannelBuilderCustomizer;
import org.springframework.grpc.client.GrpcChannelFactory;
import io.grpc.Codec;
@@ -91,27 +91,30 @@ class GrpcClientAutoConfigurationTests {
}
@Test
void baseChannelConfigurerAutoConfiguredWithHealthAsExpected() {
void baseChannelCustomizerAutoConfiguredWithHealthAsExpected() {
this.contextRunner()
.withPropertyValues("spring.grpc.client.channels.test.health.enabled=true",
"spring.grpc.client.channels.test.health.service-name=my-service")
.run((context) -> {
assertThat(context).getBean("baseGrpcChannelConfigurer", GrpcChannelConfigurer.class).isNotNull();
var configurer = context.getBean("baseGrpcChannelConfigurer", GrpcChannelConfigurer.class);
assertThat(context).getBean("baseGrpcChannelBuilderCustomizer", GrpcChannelBuilderCustomizer.class)
.isNotNull();
var customizer = context.getBean("baseGrpcChannelBuilderCustomizer",
GrpcChannelBuilderCustomizer.class);
ManagedChannelBuilder<?> builder = Mockito.mock();
configurer.configure("test", builder);
customizer.customize("test", builder);
Map<String, ?> healthCheckConfig = Map.of("healthCheckConfig", Map.of("serviceName", "my-service"));
verify(builder).defaultServiceConfig(healthCheckConfig);
});
}
@Test
void baseChannelConfigurerAutoConfiguredWithoutHealthAsExpected() {
void baseChannelCustomizerAutoConfiguredWithoutHealthAsExpected() {
this.contextRunner().run((context) -> {
assertThat(context).getBean("baseGrpcChannelConfigurer", GrpcChannelConfigurer.class).isNotNull();
var configurer = context.getBean("baseGrpcChannelConfigurer", GrpcChannelConfigurer.class);
assertThat(context).getBean("baseGrpcChannelBuilderCustomizer", GrpcChannelBuilderCustomizer.class)
.isNotNull();
var customizer = context.getBean("baseGrpcChannelBuilderCustomizer", GrpcChannelBuilderCustomizer.class);
ManagedChannelBuilder<?> builder = Mockito.mock();
configurer.configure("test", builder);
customizer.customize("test", builder);
verify(builder, never()).defaultServiceConfig(anyMap());
});
}
@@ -122,18 +125,19 @@ class GrpcClientAutoConfigurationTests {
// registry
this.contextRunner()
.withClassLoader(new FilteredClassLoader(Codec.class))
.run((context) -> assertThat(context).getBean("compressionClientConfigurer", GrpcChannelConfigurer.class)
.run((context) -> assertThat(context)
.getBean("compressionClientCustomizer", GrpcChannelBuilderCustomizer.class)
.isNull());
}
@Test
void compressionConfigurerAutoConfiguredAsExpected() {
void compressionCustomizerAutoConfiguredAsExpected() {
this.contextRunner().run((context) -> {
assertThat(context).getBean("compressionClientConfigurer", GrpcChannelConfigurer.class).isNotNull();
var configurer = context.getBean("compressionClientConfigurer", GrpcChannelConfigurer.class);
assertThat(context).getBean("compressionClientCustomizer", GrpcChannelBuilderCustomizer.class).isNotNull();
var customizer = context.getBean("compressionClientCustomizer", GrpcChannelBuilderCustomizer.class);
var compressorRegistry = context.getBean(CompressorRegistry.class);
ManagedChannelBuilder<?> builder = Mockito.mock();
configurer.configure("testChannel", builder);
customizer.customize("testChannel", builder);
verify(builder).compressorRegistry(compressorRegistry);
});
}
@@ -144,18 +148,20 @@ class GrpcClientAutoConfigurationTests {
// registry
this.contextRunner()
.withClassLoader(new FilteredClassLoader(Codec.class))
.run((context) -> assertThat(context).getBean("decompressionClientConfigurer", GrpcChannelConfigurer.class)
.run((context) -> assertThat(context)
.getBean("decompressionClientCustomizer", GrpcChannelBuilderCustomizer.class)
.isNull());
}
@Test
void decompressionConfigurerAutoConfiguredAsExpected() {
void decompressionCustomizerAutoConfiguredAsExpected() {
this.contextRunner().run((context) -> {
assertThat(context).getBean("decompressionClientConfigurer", GrpcChannelConfigurer.class).isNotNull();
var configurer = context.getBean("decompressionClientConfigurer", GrpcChannelConfigurer.class);
assertThat(context).getBean("decompressionClientCustomizer", GrpcChannelBuilderCustomizer.class)
.isNotNull();
var customizer = context.getBean("decompressionClientCustomizer", GrpcChannelBuilderCustomizer.class);
var decompressorRegistry = context.getBean(DecompressorRegistry.class);
ManagedChannelBuilder<?> builder = Mockito.mock();
configurer.configure("testChannel", builder);
customizer.customize("testChannel", builder);
verify(builder).decompressorRegistry(decompressorRegistry);
});
}