Skip to content

Commit f5f0c3b

Browse files
committed
Polishing.
Move executor from ClusterConfiguration to connection factories as the executor is a Spring concept that isn't tied to endpoint details or the client config. Reorder static factory methods after constructors and property accessors after static factory methods. Inline single-line single-use methods that aren't intended as extension hooks for easier readability. Disable TaskExecutor disposal on ClusterCommandExecutor.destroy(). Remove NonNull annotations as default non-nullability is defined on the package level. Simplify tests to use integration tests to avoid excessive mocking. See #2594 Original pull request: #2669
1 parent 8d6ebb4 commit f5f0c3b

File tree

9 files changed

+1201
-1309
lines changed

9 files changed

+1201
-1309
lines changed

src/main/java/org/springframework/data/redis/connection/ClusterCommandExecutor.java

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -32,25 +32,21 @@
3232
import org.springframework.data.redis.TooManyClusterRedirectionsException;
3333
import org.springframework.data.redis.connection.util.ByteArraySet;
3434
import org.springframework.data.redis.connection.util.ByteArrayWrapper;
35-
import org.springframework.lang.NonNull;
3635
import org.springframework.lang.Nullable;
37-
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
3836
import org.springframework.util.Assert;
3937
import org.springframework.util.CollectionUtils;
4038
import org.springframework.util.ObjectUtils;
4139

4240
/**
4341
* {@link ClusterCommandExecutor} takes care of running commands across the known cluster nodes. By providing an
44-
* {@link AsyncTaskExecutor} the execution behavior can be influenced.
42+
* {@link AsyncTaskExecutor} the execution behavior can be configured.
4543
*
4644
* @author Christoph Strobl
4745
* @author Mark Paluch
4846
* @since 1.7
4947
*/
5048
public class ClusterCommandExecutor implements DisposableBean {
5149

52-
protected static final AsyncTaskExecutor DEFAULT_TASK_EXECUTOR = new SimpleAsyncTaskExecutor();
53-
5450
private int maxRedirects = 5;
5551

5652
private final AsyncTaskExecutor executor;
@@ -71,14 +67,14 @@ public class ClusterCommandExecutor implements DisposableBean {
7167
public ClusterCommandExecutor(ClusterTopologyProvider topologyProvider, ClusterNodeResourceProvider resourceProvider,
7268
ExceptionTranslationStrategy exceptionTranslation) {
7369

74-
this(topologyProvider, resourceProvider, exceptionTranslation, DEFAULT_TASK_EXECUTOR);
70+
this(topologyProvider, resourceProvider, exceptionTranslation, new SimpleAsyncTaskExecutor());
7571
}
7672

7773
/**
7874
* @param topologyProvider must not be {@literal null}.
7975
* @param resourceProvider must not be {@literal null}.
8076
* @param exceptionTranslation must not be {@literal null}.
81-
* @param executor can be {@literal null}. Defaulted to {@link ThreadPoolTaskExecutor}.
77+
* @param executor the task executor to null, defaults to {@link SimpleAsyncTaskExecutor} if {@literal null}.
8278
*/
8379
public ClusterCommandExecutor(ClusterTopologyProvider topologyProvider, ClusterNodeResourceProvider resourceProvider,
8480
ExceptionTranslationStrategy exceptionTranslation, @Nullable AsyncTaskExecutor executor) {
@@ -90,11 +86,7 @@ public ClusterCommandExecutor(ClusterTopologyProvider topologyProvider, ClusterN
9086
this.topologyProvider = topologyProvider;
9187
this.resourceProvider = resourceProvider;
9288
this.exceptionTranslationStrategy = exceptionTranslation;
93-
this.executor = resolveTaskExecutor(executor);
94-
}
95-
96-
private @NonNull AsyncTaskExecutor resolveTaskExecutor(@Nullable AsyncTaskExecutor taskExecutor) {
97-
return taskExecutor != null ? taskExecutor : DEFAULT_TASK_EXECUTOR;
89+
this.executor = executor != null ? executor : new SimpleAsyncTaskExecutor();
9890
}
9991

10092
/**
@@ -149,9 +141,8 @@ private <S, T> NodeResult<T> executeCommandOnSingleNode(ClusterCommandCallback<S
149141
RuntimeException translatedException = convertToDataAccessException(cause);
150142

151143
if (translatedException instanceof ClusterRedirectException clusterRedirectException) {
152-
return executeCommandOnSingleNode(cmd, topologyProvider.getTopology()
153-
.lookup(clusterRedirectException.getTargetHost(), clusterRedirectException.getTargetPort()),
154-
redirectCount + 1);
144+
return executeCommandOnSingleNode(cmd, topologyProvider.getTopology().lookup(
145+
clusterRedirectException.getTargetHost(), clusterRedirectException.getTargetPort()), redirectCount + 1);
155146
} else {
156147
throw translatedException != null ? translatedException : cause;
157148
}
@@ -182,7 +173,7 @@ private RedisClusterNode lookupNode(RedisClusterNode node) {
182173
* @param cmd must not be {@literal null}.
183174
* @return never {@literal null}.
184175
* @throws ClusterCommandExecutionFailureException if a failure occurs while executing the given
185-
* {@link ClusterCommandCallback command} on any given {@link RedisClusterNode node}.
176+
* {@link ClusterCommandCallback command} on any given {@link RedisClusterNode node}.
186177
*/
187178
public <S, T> MultiNodeResult<T> executeCommandOnAllNodes(final ClusterCommandCallback<S, T> cmd) {
188179
return executeCommandAsyncOnNodes(cmd, getClusterTopology().getActiveMasterNodes());
@@ -193,7 +184,7 @@ public <S, T> MultiNodeResult<T> executeCommandOnAllNodes(final ClusterCommandCa
193184
* @param nodes must not be {@literal null}.
194185
* @return never {@literal null}.
195186
* @throws ClusterCommandExecutionFailureException if a failure occurs while executing the given
196-
* {@link ClusterCommandCallback command} on any given {@link RedisClusterNode node}.
187+
* {@link ClusterCommandCallback command} on any given {@link RedisClusterNode node}.
197188
* @throws IllegalArgumentException in case the node could not be resolved to a topology-known node
198189
*/
199190
public <S, T> MultiNodeResult<T> executeCommandAsyncOnNodes(ClusterCommandCallback<S, T> callback,
@@ -295,7 +286,7 @@ private <T> MultiNodeResult<T> collectResults(Map<NodeExecution, Future<NodeResu
295286
* @param commandCallback must not be {@literal null}.
296287
* @return never {@literal null}.
297288
* @throws ClusterCommandExecutionFailureException if a failure occurs while executing the given
298-
* {@link MultiKeyClusterCommandCallback command}.
289+
* {@link MultiKeyClusterCommandCallback command}.
299290
*/
300291
public <S, T> MultiNodeResult<T> executeMultiKeyCommand(MultiKeyClusterCommandCallback<S, T> commandCallback,
301292
Iterable<byte[]> keys) {
@@ -315,8 +306,8 @@ public <S, T> MultiNodeResult<T> executeMultiKeyCommand(MultiKeyClusterCommandCa
315306

316307
if (entry.getKey().isMaster()) {
317308
for (PositionalKey key : entry.getValue()) {
318-
futures.put(new NodeExecution(entry.getKey(), key), this.executor.submit(() ->
319-
executeMultiKeyCommandOnSingleNode(commandCallback, entry.getKey(), key.getBytes())));
309+
futures.put(new NodeExecution(entry.getKey(), key), this.executor
310+
.submit(() -> executeMultiKeyCommandOnSingleNode(commandCallback, entry.getKey(), key.getBytes())));
320311
}
321312
}
322313
}
@@ -367,10 +358,6 @@ public void setMaxRedirects(int maxRedirects) {
367358
@Override
368359
public void destroy() throws Exception {
369360

370-
if (this.executor instanceof DisposableBean disposableBean) {
371-
disposableBean.destroy();
372-
}
373-
374361
if (this.resourceProvider instanceof DisposableBean disposableBean) {
375362
disposableBean.destroy();
376363
}

src/main/java/org/springframework/data/redis/connection/RedisClusterConfiguration.java

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
*/
1616
package org.springframework.data.redis.connection;
1717

18-
import static org.springframework.util.StringUtils.commaDelimitedListToSet;
19-
2018
import java.util.Collection;
2119
import java.util.Collections;
2220
import java.util.HashMap;
@@ -26,7 +24,6 @@
2624

2725
import org.springframework.core.env.MapPropertySource;
2826
import org.springframework.core.env.PropertySource;
29-
import org.springframework.core.task.AsyncTaskExecutor;
3027
import org.springframework.data.redis.connection.RedisConfiguration.ClusterConfiguration;
3128
import org.springframework.data.redis.util.RedisAssertions;
3229
import org.springframework.lang.Nullable;
@@ -36,8 +33,8 @@
3633
import org.springframework.util.StringUtils;
3734

3835
/**
39-
* Configuration class used to set up a {@link RedisConnection} via {@link RedisConnectionFactory} for connecting
40-
* to <a href="https://redis.io/topics/cluster-spec">Redis Cluster</a>. Useful when setting up a highly available Redis
36+
* Configuration class used to set up a {@link RedisConnection} via {@link RedisConnectionFactory} for connecting to
37+
* <a href="https://redis.io/topics/cluster-spec">Redis Cluster</a>. Useful when setting up a highly available Redis
4138
* environment.
4239
*
4340
* @author Christoph Strobl
@@ -52,8 +49,6 @@ public class RedisClusterConfiguration implements RedisConfiguration, ClusterCon
5249

5350
private @Nullable Integer maxRedirects;
5451

55-
private @Nullable AsyncTaskExecutor executor;
56-
5752
private RedisPassword password = RedisPassword.none();
5853

5954
private final Set<RedisNode> clusterNodes;
@@ -103,10 +98,12 @@ public RedisClusterConfiguration(PropertySource<?> propertySource) {
10398
this.clusterNodes = new LinkedHashSet<>();
10499

105100
if (propertySource.containsProperty(REDIS_CLUSTER_NODES_CONFIG_PROPERTY)) {
101+
106102
Object redisClusterNodes = propertySource.getProperty(REDIS_CLUSTER_NODES_CONFIG_PROPERTY);
107-
appendClusterNodes(commaDelimitedListToSet(String.valueOf(redisClusterNodes)));
103+
appendClusterNodes(StringUtils.commaDelimitedListToSet(String.valueOf(redisClusterNodes)));
108104
}
109105
if (propertySource.containsProperty(REDIS_CLUSTER_MAX_REDIRECTS_CONFIG_PROPERTY)) {
106+
110107
Object clusterMaxRedirects = propertySource.getProperty(REDIS_CLUSTER_MAX_REDIRECTS_CONFIG_PROPERTY);
111108
this.maxRedirects = NumberUtils.parseNumber(String.valueOf(clusterMaxRedirects), Integer.class);
112109
}
@@ -204,16 +201,6 @@ public RedisPassword getPassword() {
204201
return password;
205202
}
206203

207-
@Override
208-
public void setAsyncTaskExecutor(@Nullable AsyncTaskExecutor executor) {
209-
this.executor = executor;
210-
}
211-
212-
@Nullable @Override
213-
public AsyncTaskExecutor getAsyncTaskExecutor() {
214-
return this.executor;
215-
}
216-
217204
@Override
218205
public boolean equals(@Nullable Object obj) {
219206

@@ -226,9 +213,9 @@ public boolean equals(@Nullable Object obj) {
226213
}
227214

228215
return ObjectUtils.nullSafeEquals(this.clusterNodes, that.clusterNodes)
229-
&& ObjectUtils.nullSafeEquals(this.maxRedirects, that.maxRedirects)
230-
&& ObjectUtils.nullSafeEquals(this.username, that.username)
231-
&& ObjectUtils.nullSafeEquals(this.password, that.password);
216+
&& ObjectUtils.nullSafeEquals(this.maxRedirects, that.maxRedirects)
217+
&& ObjectUtils.nullSafeEquals(this.username, that.username)
218+
&& ObjectUtils.nullSafeEquals(this.password, that.password);
232219
}
233220

234221
@Override

src/main/java/org/springframework/data/redis/connection/RedisConfiguration.java

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import java.util.function.IntSupplier;
2222
import java.util.function.Supplier;
2323

24-
import org.springframework.core.task.AsyncTaskExecutor;
2524
import org.springframework.lang.Nullable;
2625
import org.springframework.util.Assert;
2726

@@ -346,20 +345,6 @@ interface WithDomainSocket {
346345
*/
347346
interface ClusterConfiguration extends WithPassword {
348347

349-
/**
350-
* Configures the {@link AsyncTaskExecutor} used to execute commands asynchronously across the cluster.
351-
*
352-
* @param executor {@link AsyncTaskExecutor} used to execute commands asynchronously across the cluster.
353-
*/
354-
void setAsyncTaskExecutor(AsyncTaskExecutor executor);
355-
356-
/**
357-
* Returns the configured {@link AsyncTaskExecutor} used to execute commands asynchronously across the cluster.
358-
*
359-
* @return the configured {@link AsyncTaskExecutor} used to execute commands asynchronously across the cluster.
360-
*/
361-
AsyncTaskExecutor getAsyncTaskExecutor();
362-
363348
/**
364349
* Returns an {@link Collections#unmodifiableSet(Set) Set} of {@link RedisNode cluster nodes}.
365350
*

0 commit comments

Comments
 (0)