Skip to content

Commit 771dd57

Browse files
sschepenssnowp
authored andcommitted
cache: respond to watches in parallel v2 (envoyproxy#85)
Add ExecutorGroup to allow to respond watches in parallel Signed-off-by: Sebastian Schepens <sebastian.schepens@mercadolibre.com>
1 parent c56c848 commit 771dd57

File tree

3 files changed

+60
-4
lines changed

3 files changed

+60
-4
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package io.envoyproxy.controlplane.server;
2+
3+
import com.google.common.util.concurrent.MoreExecutors;
4+
5+
import java.util.concurrent.Executor;
6+
7+
/**
8+
* Default implementation of {@link ExecutorGroup} which
9+
* always returns {@link MoreExecutors#directExecutor}.
10+
*/
11+
public class DefaultExecutorGroup implements ExecutorGroup {
12+
/**
13+
* Returns the next {@link Executor} to use, which in this case is
14+
* always {@link MoreExecutors#directExecutor}.
15+
*/
16+
@Override
17+
public Executor next() {
18+
return MoreExecutors.directExecutor();
19+
}
20+
}

server/src/main/java/io/envoyproxy/controlplane/server/DiscoveryServer.java

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.util.Map;
2626
import java.util.Set;
2727
import java.util.concurrent.ConcurrentHashMap;
28+
import java.util.concurrent.Executor;
2829
import java.util.concurrent.atomic.AtomicLong;
2930
import java.util.stream.Collectors;
3031
import org.slf4j.Logger;
@@ -38,6 +39,7 @@ public class DiscoveryServer {
3839

3940
private final List<DiscoveryServerCallbacks> callbacks;
4041
private final ConfigWatcher configWatcher;
42+
private final ExecutorGroup executorGroup;
4143
private final AtomicLong streamCount = new AtomicLong();
4244

4345
public DiscoveryServer(ConfigWatcher configWatcher) {
@@ -54,11 +56,25 @@ public DiscoveryServer(DiscoveryServerCallbacks callbacks, ConfigWatcher configW
5456
* @param configWatcher source of configuration updates
5557
*/
5658
public DiscoveryServer(List<DiscoveryServerCallbacks> callbacks, ConfigWatcher configWatcher) {
59+
this(callbacks, configWatcher, new DefaultExecutorGroup());
60+
}
61+
62+
/**
63+
* Creates the server.
64+
* @param callbacks server callbacks
65+
* @param configWatcher source of configuration updates
66+
* @param executorGroup executor group to use for responding stream requests
67+
*/
68+
public DiscoveryServer(List<DiscoveryServerCallbacks> callbacks,
69+
ConfigWatcher configWatcher,
70+
ExecutorGroup executorGroup) {
5771
Preconditions.checkNotNull(callbacks, "callbacks cannot be null");
5872
Preconditions.checkNotNull(configWatcher, "configWatcher cannot be null");
73+
Preconditions.checkNotNull(executorGroup, "executorGroup cannot be null");
5974

6075
this.callbacks = callbacks;
6176
this.configWatcher = configWatcher;
77+
this.executorGroup = executorGroup;
6278
}
6379

6480
/**
@@ -149,13 +165,14 @@ private StreamObserver<DiscoveryRequest> createRequestHandler(
149165
String defaultTypeUrl) {
150166

151167
long streamId = streamCount.getAndIncrement();
168+
Executor executor = executorGroup.next();
152169

153170
LOGGER.info("[{}] open stream from {}", streamId, defaultTypeUrl);
154171

155172
callbacks.forEach(cb -> cb.onStreamOpen(streamId, defaultTypeUrl));
156173

157174
final DiscoveryRequestStreamObserver requestStreamObserver =
158-
new DiscoveryRequestStreamObserver(defaultTypeUrl, responseObserver, streamId, ads);
175+
new DiscoveryRequestStreamObserver(defaultTypeUrl, responseObserver, streamId, ads, executor);
159176

160177
if (responseObserver instanceof ServerCallStreamObserver) {
161178
((ServerCallStreamObserver) responseObserver).setOnCancelHandler(requestStreamObserver::onCancelled);
@@ -173,11 +190,15 @@ private class DiscoveryRequestStreamObserver implements StreamObserver<Discovery
173190
private final StreamObserver<DiscoveryResponse> responseObserver;
174191
private final long streamId;
175192
private final boolean ads;
193+
private final Executor executor;
176194

177195
private AtomicLong streamNonce;
178196

179-
public DiscoveryRequestStreamObserver(String defaultTypeUrl, StreamObserver<DiscoveryResponse> responseObserver,
180-
long streamId, boolean ads) {
197+
public DiscoveryRequestStreamObserver(String defaultTypeUrl,
198+
StreamObserver<DiscoveryResponse> responseObserver,
199+
long streamId,
200+
boolean ads,
201+
Executor executor) {
181202
this.defaultTypeUrl = defaultTypeUrl;
182203
this.responseObserver = responseObserver;
183204
this.streamId = streamId;
@@ -186,6 +207,7 @@ public DiscoveryRequestStreamObserver(String defaultTypeUrl, StreamObserver<Disc
186207
latestResponse = new ConcurrentHashMap<>(Resources.TYPE_URLS.size());
187208
ackedResources = new ConcurrentHashMap<>(Resources.TYPE_URLS.size());
188209
streamNonce = new AtomicLong();
210+
this.executor = executor;
189211
}
190212

191213
@Override
@@ -238,7 +260,7 @@ public void onNext(DiscoveryRequest request) {
238260
ads,
239261
request,
240262
ackedResources.getOrDefault(typeUrl, Collections.emptySet()),
241-
r -> send(r, typeUrl));
263+
r -> executor.execute(() -> send(r, typeUrl)));
242264
});
243265

244266
return;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package io.envoyproxy.controlplane.server;
2+
3+
import java.util.concurrent.Executor;
4+
5+
/**
6+
* The {@link ExecutorGroup} is responsible for providing the {@link Executor}'s to use
7+
* via its {@link #next()} method.
8+
*/
9+
public interface ExecutorGroup {
10+
/**
11+
* Returns the next {@link Executor} to use.
12+
*/
13+
Executor next();
14+
}

0 commit comments

Comments
 (0)