Skip to content

Commit 2eaf174

Browse files
jxblummp911de
authored andcommitted
Polishing.
Organize source code and cleanup compiler warnings. See #2594 Original pull request: #2669
1 parent 76c1830 commit 2eaf174

File tree

8 files changed

+978
-824
lines changed

8 files changed

+978
-824
lines changed

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

+57-37
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
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;
3536
import org.springframework.lang.Nullable;
3637
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
3738
import org.springframework.util.Assert;
@@ -48,11 +49,17 @@
4849
*/
4950
public class ClusterCommandExecutor implements DisposableBean {
5051

51-
private AsyncTaskExecutor executor;
52-
private final ClusterTopologyProvider topologyProvider;
52+
protected static final AsyncTaskExecutor DEFAULT_TASK_EXECUTOR = new SimpleAsyncTaskExecutor();
53+
54+
private int maxRedirects = 5;
55+
56+
private final AsyncTaskExecutor executor;
57+
5358
private final ClusterNodeResourceProvider resourceProvider;
59+
60+
private final ClusterTopologyProvider topologyProvider;
61+
5462
private final ExceptionTranslationStrategy exceptionTranslationStrategy;
55-
private int maxRedirects = 5;
5663

5764
/**
5865
* Create a new instance of {@link ClusterCommandExecutor}.
@@ -64,13 +71,7 @@ public class ClusterCommandExecutor implements DisposableBean {
6471
public ClusterCommandExecutor(ClusterTopologyProvider topologyProvider, ClusterNodeResourceProvider resourceProvider,
6572
ExceptionTranslationStrategy exceptionTranslation) {
6673

67-
Assert.notNull(topologyProvider, "ClusterTopologyProvider must not be null");
68-
Assert.notNull(resourceProvider, "ClusterNodeResourceProvider must not be null");
69-
Assert.notNull(exceptionTranslation, "ExceptionTranslationStrategy must not be null");
70-
71-
this.topologyProvider = topologyProvider;
72-
this.resourceProvider = resourceProvider;
73-
this.exceptionTranslationStrategy = exceptionTranslation;
74+
this(topologyProvider, resourceProvider, exceptionTranslation, DEFAULT_TASK_EXECUTOR);
7475
}
7576

7677
/**
@@ -82,36 +83,42 @@ public ClusterCommandExecutor(ClusterTopologyProvider topologyProvider, ClusterN
8283
public ClusterCommandExecutor(ClusterTopologyProvider topologyProvider, ClusterNodeResourceProvider resourceProvider,
8384
ExceptionTranslationStrategy exceptionTranslation, @Nullable AsyncTaskExecutor executor) {
8485

85-
this(topologyProvider, resourceProvider, exceptionTranslation);
86-
this.executor = executor;
86+
Assert.notNull(topologyProvider, "ClusterTopologyProvider must not be null");
87+
Assert.notNull(resourceProvider, "ClusterNodeResourceProvider must not be null");
88+
Assert.notNull(exceptionTranslation, "ExceptionTranslationStrategy must not be null");
89+
90+
this.topologyProvider = topologyProvider;
91+
this.resourceProvider = resourceProvider;
92+
this.exceptionTranslationStrategy = exceptionTranslation;
93+
this.executor = resolveTaskExecutor(executor);
8794
}
8895

89-
{
90-
if (executor == null) {
91-
this.executor = new SimpleAsyncTaskExecutor();
92-
}
96+
private @NonNull AsyncTaskExecutor resolveTaskExecutor(@Nullable AsyncTaskExecutor taskExecutor) {
97+
return taskExecutor != null ? taskExecutor : DEFAULT_TASK_EXECUTOR;
9398
}
9499

95100
/**
96101
* Run {@link ClusterCommandCallback} on a random node.
97102
*
98-
* @param cmd must not be {@literal null}.
103+
* @param commandCallback must not be {@literal null}.
99104
* @return never {@literal null}.
100105
*/
101-
public <T> NodeResult<T> executeCommandOnArbitraryNode(ClusterCommandCallback<?, T> cmd) {
106+
public <T> NodeResult<T> executeCommandOnArbitraryNode(ClusterCommandCallback<?, T> commandCallback) {
107+
108+
Assert.notNull(commandCallback, "ClusterCommandCallback must not be null");
102109

103-
Assert.notNull(cmd, "ClusterCommandCallback must not be null");
104110
List<RedisClusterNode> nodes = new ArrayList<>(getClusterTopology().getActiveNodes());
105-
return executeCommandOnSingleNode(cmd, nodes.get(new Random().nextInt(nodes.size())));
111+
112+
return executeCommandOnSingleNode(commandCallback, nodes.get(new Random().nextInt(nodes.size())));
106113
}
107114

108115
/**
109116
* Run {@link ClusterCommandCallback} on given {@link RedisClusterNode}.
110117
*
111118
* @param cmd must not be {@literal null}.
112119
* @param node must not be {@literal null}.
120+
* @return the {@link NodeResult} from the single, targeted {@link RedisClusterNode}.
113121
* @throws IllegalArgumentException in case no resource can be acquired for given node.
114-
* @return
115122
*/
116123
public <S, T> NodeResult<T> executeCommandOnSingleNode(ClusterCommandCallback<S, T> cmd, RedisClusterNode node) {
117124
return executeCommandOnSingleNode(cmd, node, 0);
@@ -132,19 +139,21 @@ private <S, T> NodeResult<T> executeCommandOnSingleNode(ClusterCommandCallback<S
132139
RedisClusterNode nodeToUse = lookupNode(node);
133140

134141
S client = this.resourceProvider.getResourceForSpecificNode(nodeToUse);
142+
135143
Assert.notNull(client, "Could not acquire resource for node; Is your cluster info up to date");
136144

137145
try {
138146
return new NodeResult<>(node, cmd.doInCluster(client));
139-
} catch (RuntimeException ex) {
147+
} catch (RuntimeException cause) {
140148

141-
RuntimeException translatedException = convertToDataAccessException(ex);
142-
if (translatedException instanceof ClusterRedirectException) {
143-
ClusterRedirectException cre = (ClusterRedirectException) translatedException;
144-
return executeCommandOnSingleNode(cmd,
145-
topologyProvider.getTopology().lookup(cre.getTargetHost(), cre.getTargetPort()), redirectCount + 1);
149+
RuntimeException translatedException = convertToDataAccessException(cause);
150+
151+
if (translatedException instanceof ClusterRedirectException clusterRedirectException) {
152+
return executeCommandOnSingleNode(cmd, topologyProvider.getTopology()
153+
.lookup(clusterRedirectException.getTargetHost(), clusterRedirectException.getTargetPort()),
154+
redirectCount + 1);
146155
} else {
147-
throw translatedException != null ? translatedException : ex;
156+
throw translatedException != null ? translatedException : cause;
148157
}
149158
} finally {
150159
this.resourceProvider.returnResourceForSpecificNode(nodeToUse, client);
@@ -159,10 +168,11 @@ private <S, T> NodeResult<T> executeCommandOnSingleNode(ClusterCommandCallback<S
159168
* @throws IllegalArgumentException in case the node could not be resolved to a topology-known node
160169
*/
161170
private RedisClusterNode lookupNode(RedisClusterNode node) {
171+
162172
try {
163173
return topologyProvider.getTopology().lookup(node);
164-
} catch (ClusterStateFailureException e) {
165-
throw new IllegalArgumentException(String.format("Node %s is unknown to cluster", node), e);
174+
} catch (ClusterStateFailureException cause) {
175+
throw new IllegalArgumentException(String.format("Node %s is unknown to cluster", node), cause);
166176
}
167177
}
168178

@@ -171,7 +181,8 @@ private RedisClusterNode lookupNode(RedisClusterNode node) {
171181
*
172182
* @param cmd must not be {@literal null}.
173183
* @return never {@literal null}.
174-
* @throws ClusterCommandExecutionFailureException
184+
* @throws ClusterCommandExecutionFailureException if a failure occurs while executing the given
185+
* {@link ClusterCommandCallback command} on any given {@link RedisClusterNode node}.
175186
*/
176187
public <S, T> MultiNodeResult<T> executeCommandOnAllNodes(final ClusterCommandCallback<S, T> cmd) {
177188
return executeCommandAsyncOnNodes(cmd, getClusterTopology().getActiveMasterNodes());
@@ -181,7 +192,8 @@ public <S, T> MultiNodeResult<T> executeCommandOnAllNodes(final ClusterCommandCa
181192
* @param callback must not be {@literal null}.
182193
* @param nodes must not be {@literal null}.
183194
* @return never {@literal null}.
184-
* @throws ClusterCommandExecutionFailureException
195+
* @throws ClusterCommandExecutionFailureException if a failure occurs while executing the given
196+
* {@link ClusterCommandCallback command} on any given {@link RedisClusterNode node}.
185197
* @throws IllegalArgumentException in case the node could not be resolved to a topology-known node
186198
*/
187199
public <S, T> MultiNodeResult<T> executeCommandAsyncOnNodes(ClusterCommandCallback<S, T> callback,
@@ -202,6 +214,7 @@ public <S, T> MultiNodeResult<T> executeCommandAsyncOnNodes(ClusterCommandCallba
202214
}
203215

204216
Map<NodeExecution, Future<NodeResult<T>>> futures = new LinkedHashMap<>();
217+
205218
for (RedisClusterNode node : resolvedRedisClusterNodes) {
206219
futures.put(new NodeExecution(node), executor.submit(() -> executeCommandOnSingleNode(callback, node)));
207220
}
@@ -213,10 +226,10 @@ private <T> MultiNodeResult<T> collectResults(Map<NodeExecution, Future<NodeResu
213226

214227
boolean done = false;
215228

216-
MultiNodeResult<T> result = new MultiNodeResult<>();
217229
Map<RedisClusterNode, Throwable> exceptions = new HashMap<>();
218-
230+
MultiNodeResult<T> result = new MultiNodeResult<>();
219231
Set<String> saveGuard = new HashSet<>();
232+
220233
while (!done) {
221234

222235
done = true;
@@ -242,6 +255,7 @@ private <T> MultiNodeResult<T> collectResults(Map<NodeExecution, Future<NodeResu
242255
} catch (ExecutionException e) {
243256

244257
RuntimeException ex = convertToDataAccessException((Exception) e.getCause());
258+
245259
exceptions.put(execution.getNode(), ex != null ? ex : e.getCause());
246260
} catch (InterruptedException e) {
247261

@@ -253,6 +267,7 @@ private <T> MultiNodeResult<T> collectResults(Map<NodeExecution, Future<NodeResu
253267
}
254268
}
255269
}
270+
256271
try {
257272
Thread.sleep(10);
258273
} catch (InterruptedException e) {
@@ -273,21 +288,23 @@ private <T> MultiNodeResult<T> collectResults(Map<NodeExecution, Future<NodeResu
273288
*
274289
* @param cmd must not be {@literal null}.
275290
* @return never {@literal null}.
276-
* @throws ClusterCommandExecutionFailureException
291+
* @throws ClusterCommandExecutionFailureException if a failure occurs while executing the given
292+
* {@link MultiKeyClusterCommandCallback command}.
277293
*/
278294
public <S, T> MultiNodeResult<T> executeMultiKeyCommand(MultiKeyClusterCommandCallback<S, T> cmd,
279295
Iterable<byte[]> keys) {
280296

281297
Map<RedisClusterNode, PositionalKeys> nodeKeyMap = new HashMap<>();
282-
283298
int index = 0;
299+
284300
for (byte[] key : keys) {
285301
for (RedisClusterNode node : getClusterTopology().getKeyServingNodes(key)) {
286302
nodeKeyMap.computeIfAbsent(node, val -> PositionalKeys.empty()).append(PositionalKey.of(key, index++));
287303
}
288304
}
289305

290306
Map<NodeExecution, Future<NodeResult<T>>> futures = new LinkedHashMap<>();
307+
291308
for (Entry<RedisClusterNode, PositionalKeys> entry : nodeKeyMap.entrySet()) {
292309

293310
if (entry.getKey().isMaster()) {
@@ -309,6 +326,7 @@ private <S, T> NodeResult<T> executeMultiKeyCommandOnSingleNode(MultiKeyClusterC
309326
Assert.notNull(key, "Keys for execution must not be null");
310327

311328
S client = this.resourceProvider.getResourceForSpecificNode(node);
329+
312330
Assert.notNull(client, "Could not acquire resource for node; Is your cluster info up to date");
313331

314332
try {
@@ -479,7 +497,9 @@ public RedisClusterNode getNode() {
479497
}
480498

481499
/**
482-
* @return
500+
* Returns the key as an array of bytes.
501+
*
502+
* @return the key as an array of bytes.
483503
*/
484504
public byte[] getKey() {
485505
return key.getArray();

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

+12-12
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,18 @@
2626
*/
2727
public interface RedisConnectionFactory extends PersistenceExceptionTranslator {
2828

29+
/**
30+
* Specifies if pipelined results should be converted to the expected data type.
31+
* <p>
32+
* If {@literal false}, results of {@link RedisConnection#closePipeline()} and {@link RedisConnection#exec()} will be
33+
* of the type returned by the underlying driver. This method is mostly for backwards compatibility with
34+
* {@literal 1.0}. It is generally always a good idea to allow results to be converted and deserialized. In fact, this
35+
* is now the default behavior.
36+
*
37+
* @return {@code true} to convert pipeline and transaction results; {@code false} otherwise.
38+
*/
39+
boolean getConvertPipelineAndTxResults();
40+
2941
/**
3042
* Returns a suitable {@link RedisConnection connection} for interacting with Redis.
3143
*
@@ -45,18 +57,6 @@ public interface RedisConnectionFactory extends PersistenceExceptionTranslator {
4557
*/
4658
RedisClusterConnection getClusterConnection();
4759

48-
/**
49-
* Specifies if pipelined results should be converted to the expected data type.
50-
* <p>
51-
* If {@literal false}, results of {@link RedisConnection#closePipeline()} and {@link RedisConnection#exec()} will be
52-
* of the type returned by the underlying driver. This method is mostly for backwards compatibility with
53-
* {@literal 1.0}. It is generally always a good idea to allow results to be converted and deserialized. In fact, this
54-
* is now the default behavior.
55-
*
56-
* @return {@code true} to convert pipeline and transaction results; {@code false} otherwise.
57-
*/
58-
boolean getConvertPipelineAndTxResults();
59-
6060
/**
6161
* Returns a suitable {@link RedisSentinelConnection connection} for interacting with Redis Sentinel.
6262
*

0 commit comments

Comments
 (0)