Skip to content

Commit ff6bd12

Browse files
loadbalancer-experimental: Make some of the types public
Motivation: We want to be able to use the experimental load balancer from other packages but we can't because the types are all private. Modifications: - Make a bunch of helpful interfaces public - Add `DelegatingLoadBalancerBuilder` for symmetry with round robin
1 parent 840aca3 commit ff6bd12

9 files changed

+148
-17
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
* Copyright © 2024 Apple Inc. and the ServiceTalk project authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.servicetalk.loadbalancer;
17+
18+
import io.servicetalk.client.api.LoadBalancedConnection;
19+
import io.servicetalk.client.api.LoadBalancerFactory;
20+
import io.servicetalk.concurrent.api.Executor;
21+
22+
import java.time.Duration;
23+
import javax.annotation.Nullable;
24+
25+
import static java.util.Objects.requireNonNull;
26+
27+
/**
28+
* A {@link LoadBalancerBuilder} that delegates all methods to another {@link LoadBalancerBuilder}.
29+
*
30+
* @param <ResolvedAddress> The resolved address type.
31+
* @param <C> The type of connection.
32+
*/
33+
public class DelegatingLoadBalancerBuilder<ResolvedAddress, C extends LoadBalancedConnection>
34+
implements LoadBalancerBuilder<ResolvedAddress, C> {
35+
36+
private LoadBalancerBuilder<ResolvedAddress, C> delegate;
37+
38+
/**
39+
* Creates a new builder which delegates to the provided {@link LoadBalancerBuilder}.
40+
*
41+
* @param delegate the delegate builder.
42+
*/
43+
public DelegatingLoadBalancerBuilder(final LoadBalancerBuilder<ResolvedAddress, C> delegate) {
44+
this.delegate = requireNonNull(delegate, "delegate");
45+
}
46+
47+
/**
48+
* Returns the {@link DelegatingLoadBalancerBuilder} delegate.
49+
*
50+
* @return Delegate {@link DelegatingLoadBalancerBuilder}.
51+
*/
52+
protected final LoadBalancerBuilder<ResolvedAddress, C> delegate() {
53+
return delegate;
54+
}
55+
56+
@Override
57+
public LoadBalancerBuilder<ResolvedAddress, C> loadBalancingPolicy(
58+
LoadBalancingPolicy<ResolvedAddress, C> loadBalancingPolicy) {
59+
delegate = delegate.loadBalancingPolicy(loadBalancingPolicy);
60+
return this;
61+
}
62+
63+
@Override
64+
public LoadBalancerBuilder<ResolvedAddress, C> loadBalancerObserver(
65+
@Nullable LoadBalancerObserver<ResolvedAddress> loadBalancerObserver) {
66+
delegate = delegate.loadBalancerObserver(loadBalancerObserver);
67+
return this;
68+
}
69+
70+
@Override
71+
public LoadBalancerBuilder<ResolvedAddress, C> healthCheckerFactory(
72+
HealthCheckerFactory<ResolvedAddress> healthCheckerFactory) {
73+
delegate = delegate.healthCheckerFactory(healthCheckerFactory);
74+
return this;
75+
}
76+
77+
@Override
78+
public LoadBalancerBuilder<ResolvedAddress, C> backgroundExecutor(Executor backgroundExecutor) {
79+
delegate = delegate.backgroundExecutor(backgroundExecutor);
80+
return this;
81+
}
82+
83+
@Override
84+
public LoadBalancerBuilder<ResolvedAddress, C> linearSearchSpace(int linearSearchSpace) {
85+
delegate = delegate.linearSearchSpace(linearSearchSpace);
86+
return this;
87+
}
88+
89+
@Override
90+
public LoadBalancerBuilder<ResolvedAddress, C> healthCheckInterval(Duration interval, Duration jitter) {
91+
delegate = delegate.healthCheckInterval(interval, jitter);
92+
return this;
93+
}
94+
95+
@Override
96+
public LoadBalancerBuilder<ResolvedAddress, C> healthCheckResubscribeInterval(Duration interval, Duration jitter) {
97+
delegate = delegate.healthCheckResubscribeInterval(interval, jitter);
98+
return this;
99+
}
100+
101+
@Override
102+
public LoadBalancerBuilder<ResolvedAddress, C> healthCheckFailedConnectionsThreshold(int threshold) {
103+
delegate = delegate.healthCheckFailedConnectionsThreshold(threshold);
104+
return this;
105+
}
106+
107+
@Override
108+
public LoadBalancerFactory<ResolvedAddress, C> build() {
109+
return delegate.build();
110+
}
111+
}

servicetalk-loadbalancer-experimental/src/main/java/io/servicetalk/loadbalancer/HealthCheckerFactory.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
* builders and may make more than one health checker per-load balancer.
2323
* @param <ResolvedAddress> the type of the resolved address.
2424
*/
25-
interface HealthCheckerFactory<ResolvedAddress> {
25+
public interface HealthCheckerFactory<ResolvedAddress> {
2626
/**
2727
* Create a new {@link HealthChecker}.
2828
* @param executor the {@link Executor} to use for scheduling tasks and obtaining the current time.

servicetalk-loadbalancer-experimental/src/main/java/io/servicetalk/loadbalancer/LoadBalancerBuilderProvider.java

+18-3
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,24 @@
1717

1818
import io.servicetalk.client.api.LoadBalancedConnection;
1919

20-
// TODO: this has to be public for the service loading to work. At that point we'll also likely want
21-
// to provide a DelegatingLoadBalancerBuilder.
22-
interface LoadBalancerBuilderProvider {
20+
/**
21+
* Provider for {@link LoadBalancerBuilder}.
22+
*/
23+
public interface LoadBalancerBuilderProvider {
24+
25+
/**
26+
* Returns a {@link LoadBalancerBuilder} based on the pre-initialized {@link LoadBalancerBuilder}.
27+
* <p>
28+
* This method may return the pre-initialized {@code builder} as-is, or apply custom builder settings before
29+
* returning it, or wrap it ({@link DelegatingLoadBalancerBuilder} may be helpful).
30+
*
31+
* @param id a (unique) identifier used to identify the underlying {@link io.servicetalk.client.api.LoadBalancer}.
32+
* @param builder pre-initialized {@link LoadBalancerBuilder}.
33+
* @return a {@link LoadBalancerBuilder} based on the pre-initialized
34+
* {@link LoadBalancerBuilder}.
35+
* @param <ResolvedAddress> The resolved address type.
36+
* @param <C> The type of connection.
37+
*/
2338
<ResolvedAddress, C extends LoadBalancedConnection> LoadBalancerBuilder<ResolvedAddress, C>
2439
newBuilder(String id, LoadBalancerBuilder<ResolvedAddress, C> builder);
2540
}

servicetalk-loadbalancer-experimental/src/main/java/io/servicetalk/loadbalancer/LoadBalancers.java

+9-4
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,24 @@
1717

1818
import io.servicetalk.client.api.LoadBalancedConnection;
1919

20-
import java.util.ArrayList;
20+
import org.slf4j.Logger;
21+
import org.slf4j.LoggerFactory;
22+
2123
import java.util.List;
2224

25+
import static io.servicetalk.utils.internal.ServiceLoaderUtils.loadProviders;
26+
2327
/**
2428
* A factory to create {@link DefaultLoadBalancer DefaultLoadBalancers}.
2529
*/
26-
final class LoadBalancers {
30+
public final class LoadBalancers {
2731

32+
private static final Logger LOGGER = LoggerFactory.getLogger(LoadBalancers.class);
2833
private static final List<LoadBalancerBuilderProvider> PROVIDERS;
2934

3035
static {
31-
// TODO: we can't service load the providers until we make the interface public.
32-
PROVIDERS = new ArrayList<>();
36+
final ClassLoader classLoader = LoadBalancers.class.getClassLoader();
37+
PROVIDERS = loadProviders(LoadBalancerBuilderProvider.class, classLoader, LOGGER);
3338
}
3439

3540
private LoadBalancers() {

servicetalk-loadbalancer-experimental/src/main/java/io/servicetalk/loadbalancer/LoadBalancingPolicy.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
/**
2323
* Definition of the selector mechanism used for load balancing.
2424
*/
25-
interface LoadBalancingPolicy<ResolvedAddress, C extends LoadBalancedConnection> {
25+
public interface LoadBalancingPolicy<ResolvedAddress, C extends LoadBalancedConnection> {
2626
/**
2727
* The name of the load balancing policy
2828
*

servicetalk-loadbalancer-experimental/src/main/java/io/servicetalk/loadbalancer/OutlierDetectorConfig.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@
2626
* XDS outlier detector configuration.
2727
* <p>
2828
* See the <a href="https://www.envoyproxy.io/docs/envoy/v1.29.0/api-v3/config/cluster/v3/
29-
* outlier_detection.proto#envoy-v3-api-msg-config-cluster-v3-outlierdetection"> Envoy docs</a> for the official
29+
outlier_detection.proto#envoy-v3-api-msg-config-cluster-v3-outlierdetection"> Envoy docs</a> for the official
3030
* OutlierDetector configuration definition.
3131
*/
32-
final class OutlierDetectorConfig {
32+
public final class OutlierDetectorConfig {
3333

3434
private final Duration ewmaHalfLife;
3535
private final int consecutive5xx;
@@ -311,7 +311,7 @@ public boolean successfulActiveHealthCheckUnejectHost() {
311311
/**
312312
* A builder for {@link OutlierDetectorConfig} instances.
313313
*/
314-
public static class Builder {
314+
public static final class Builder {
315315
private Duration ewmaHalfLife = Duration.ofSeconds(10);
316316
private int consecutive5xx = 5;
317317

servicetalk-loadbalancer-experimental/src/main/java/io/servicetalk/loadbalancer/P2CLoadBalancingPolicy.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
* - if neither host is healthy, repeat selection process until max-effort.
3838
* - pick the 'best' host of the two options.
3939
*/
40-
final class P2CLoadBalancingPolicy<ResolvedAddress, C extends LoadBalancedConnection>
40+
public final class P2CLoadBalancingPolicy<ResolvedAddress, C extends LoadBalancedConnection>
4141
implements LoadBalancingPolicy<ResolvedAddress, C> {
4242

4343
private final int maxEffort;
@@ -109,7 +109,7 @@ Builder random(Random random) {
109109
/**
110110
* Construct an immutable {@link P2CLoadBalancingPolicy}.
111111
* @param <ResolvedAddress> the type of the resolved address.
112-
* @param <C> the refined type of the {@LoadBalancedConnection}.
112+
* @param <C> the refined type of the {@link LoadBalancedConnection}.
113113
* @return the concrete {@link P2CLoadBalancingPolicy}.
114114
*/
115115
public <ResolvedAddress, C extends LoadBalancedConnection> P2CLoadBalancingPolicy<ResolvedAddress, C> build() {

servicetalk-loadbalancer-experimental/src/main/java/io/servicetalk/loadbalancer/RoundRobinLoadBalancingPolicy.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
* from an ordered set. If a host is considered unhealthy it is skipped the next host
2727
* is selected until a healthy host is found or the entire host set has been exhausted.
2828
*/
29-
final class RoundRobinLoadBalancingPolicy<ResolvedAddress, C extends LoadBalancedConnection>
29+
public final class RoundRobinLoadBalancingPolicy<ResolvedAddress, C extends LoadBalancedConnection>
3030
implements LoadBalancingPolicy<ResolvedAddress, C> {
3131

3232
private final boolean failOpen;
@@ -66,7 +66,7 @@ public RoundRobinLoadBalancingPolicy.Builder failOpen(final boolean failOpen) {
6666
/**
6767
* Construct the immutable {@link RoundRobinLoadBalancingPolicy}.
6868
* @param <ResolvedAddress> the type of the resolved address.
69-
* @param <C> the refined type of the {@LoadBalancedConnection}.
69+
* @param <C> the refined type of the {@link LoadBalancedConnection}.
7070
* @return the concrete {@link RoundRobinLoadBalancingPolicy}.
7171
*/
7272
public <ResolvedAddress, C extends LoadBalancedConnection> RoundRobinLoadBalancingPolicy<ResolvedAddress, C>

servicetalk-loadbalancer-experimental/src/main/java/io/servicetalk/loadbalancer/XdsHealthCheckerFactory.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
* See the {@link XdsHealthChecker} for a detailed description and history of the xDS protocol.
2525
* @param <ResolvedAddress> the type of the resolved address.
2626
*/
27-
final class XdsHealthCheckerFactory<ResolvedAddress> implements HealthCheckerFactory<ResolvedAddress> {
27+
public final class XdsHealthCheckerFactory<ResolvedAddress> implements HealthCheckerFactory<ResolvedAddress> {
2828

2929
private final OutlierDetectorConfig config;
3030

0 commit comments

Comments
 (0)