|
21 | 21 | import io.lettuce.core.ClientOptions;
|
22 | 22 | import io.lettuce.core.ReadFrom;
|
23 | 23 | import io.lettuce.core.RedisClient;
|
24 |
| -import io.lettuce.core.RedisException; |
| 24 | +import io.lettuce.core.RedisConnectionException; |
25 | 25 | import io.lettuce.core.RedisURI;
|
26 | 26 | import io.lettuce.core.api.StatefulConnection;
|
27 | 27 | import io.lettuce.core.api.StatefulRedisConnection;
|
|
37 | 37 | import java.util.ArrayList;
|
38 | 38 | import java.util.List;
|
39 | 39 | import java.util.Optional;
|
| 40 | +import java.util.concurrent.CompletableFuture; |
| 41 | +import java.util.concurrent.CompletionStage; |
40 | 42 | import java.util.concurrent.TimeUnit;
|
41 | 43 | import java.util.function.Consumer;
|
42 | 44 | import java.util.stream.Collectors;
|
43 | 45 |
|
44 | 46 | import org.apache.commons.logging.Log;
|
45 | 47 | import org.apache.commons.logging.LogFactory;
|
| 48 | + |
46 | 49 | import org.springframework.beans.factory.DisposableBean;
|
47 | 50 | import org.springframework.beans.factory.InitializingBean;
|
48 | 51 | import org.springframework.dao.DataAccessException;
|
|
55 | 58 | import org.springframework.data.redis.connection.RedisConfiguration.DomainSocketConfiguration;
|
56 | 59 | import org.springframework.data.redis.connection.RedisConfiguration.WithDatabaseIndex;
|
57 | 60 | import org.springframework.data.redis.connection.RedisConfiguration.WithPassword;
|
| 61 | +import org.springframework.data.redis.connection.lettuce.LettuceConnection.*; |
58 | 62 | import org.springframework.data.util.Optionals;
|
59 | 63 | import org.springframework.lang.Nullable;
|
60 | 64 | import org.springframework.util.Assert;
|
@@ -277,8 +281,9 @@ public void afterPropertiesSet() {
|
277 | 281 |
|
278 | 282 | this.client = createClient();
|
279 | 283 |
|
280 |
| - this.connectionProvider = createConnectionProvider(client, CODEC); |
281 |
| - this.reactiveConnectionProvider = createConnectionProvider(client, LettuceReactiveRedisConnection.CODEC); |
| 284 | + this.connectionProvider = new ExceptionTranslatingConnectionProvider(createConnectionProvider(client, CODEC)); |
| 285 | + this.reactiveConnectionProvider = new ExceptionTranslatingConnectionProvider( |
| 286 | + createConnectionProvider(client, LettuceReactiveRedisConnection.CODEC)); |
282 | 287 |
|
283 | 288 | if (isClusterAware()) {
|
284 | 289 |
|
@@ -1197,12 +1202,7 @@ StatefulConnection<E, E> getConnection() {
|
1197 | 1202 | * @return the connection.
|
1198 | 1203 | */
|
1199 | 1204 | private StatefulConnection<E, E> getNativeConnection() {
|
1200 |
| - |
1201 |
| - try { |
1202 |
| - return connectionProvider.getConnection(StatefulConnection.class); |
1203 |
| - } catch (RedisException e) { |
1204 |
| - throw new RedisConnectionFailureException("Unable to connect to Redis", e); |
1205 |
| - } |
| 1205 | + return connectionProvider.getConnection(StatefulConnection.class); |
1206 | 1206 | }
|
1207 | 1207 |
|
1208 | 1208 | /**
|
@@ -1393,4 +1393,124 @@ public Duration getShutdownQuietPeriod() {
|
1393 | 1393 | return shutdownTimeout;
|
1394 | 1394 | }
|
1395 | 1395 | }
|
| 1396 | + |
| 1397 | + /** |
| 1398 | + * {@link LettuceConnectionProvider} that translates connection exceptions into {@link RedisConnectionException}. |
| 1399 | + */ |
| 1400 | + private static class ExceptionTranslatingConnectionProvider |
| 1401 | + implements LettuceConnectionProvider, LettuceConnectionProvider.TargetAware, DisposableBean { |
| 1402 | + |
| 1403 | + private final LettuceConnectionProvider delegate; |
| 1404 | + |
| 1405 | + public ExceptionTranslatingConnectionProvider(LettuceConnectionProvider delegate) { |
| 1406 | + this.delegate = delegate; |
| 1407 | + } |
| 1408 | + |
| 1409 | + /* |
| 1410 | + * (non-Javadoc) |
| 1411 | + * @see org.springframework.data.redis.connection.lettuce.LettuceConnectionProvider#getConnection(java.lang.Class) |
| 1412 | + */ |
| 1413 | + @Override |
| 1414 | + public <T extends StatefulConnection<?, ?>> T getConnection(Class<T> connectionType) { |
| 1415 | + |
| 1416 | + try { |
| 1417 | + return delegate.getConnection(connectionType); |
| 1418 | + } catch (RuntimeException e) { |
| 1419 | + throw translateException(e); |
| 1420 | + } |
| 1421 | + } |
| 1422 | + |
| 1423 | + /* |
| 1424 | + * (non-Javadoc) |
| 1425 | + * @see org.springframework.data.redis.connection.lettuce.LettuceConnectionProvider#getConnection(java.lang.Class, RedisURI) |
| 1426 | + */ |
| 1427 | + @Override |
| 1428 | + public <T extends StatefulConnection<?, ?>> T getConnection(Class<T> connectionType, RedisURI redisURI) { |
| 1429 | + |
| 1430 | + try { |
| 1431 | + return ((TargetAware) delegate).getConnection(connectionType, redisURI); |
| 1432 | + } catch (RuntimeException e) { |
| 1433 | + throw translateException(e); |
| 1434 | + } |
| 1435 | + } |
| 1436 | + |
| 1437 | + /* |
| 1438 | + * (non-Javadoc) |
| 1439 | + * @see org.springframework.data.redis.connection.lettuce.LettuceConnectionProvider#getConnectionAsync(java.lang.Class) |
| 1440 | + */ |
| 1441 | + @Override |
| 1442 | + public <T extends StatefulConnection<?, ?>> CompletionStage<T> getConnectionAsync(Class<T> connectionType) { |
| 1443 | + |
| 1444 | + CompletableFuture<T> future = new CompletableFuture<>(); |
| 1445 | + |
| 1446 | + delegate.getConnectionAsync(connectionType).whenComplete((t, throwable) -> { |
| 1447 | + |
| 1448 | + if (throwable != null) { |
| 1449 | + future.completeExceptionally(translateException(throwable)); |
| 1450 | + } else { |
| 1451 | + future.complete(t); |
| 1452 | + } |
| 1453 | + }); |
| 1454 | + |
| 1455 | + return future; |
| 1456 | + } |
| 1457 | + |
| 1458 | + /* |
| 1459 | + * (non-Javadoc) |
| 1460 | + * @see org.springframework.data.redis.connection.lettuce.LettuceConnectionProvider#getConnectionAsync(java.lang.Class, RedisURI) |
| 1461 | + */ |
| 1462 | + @Override |
| 1463 | + public <T extends StatefulConnection<?, ?>> CompletionStage<T> getConnectionAsync(Class<T> connectionType, |
| 1464 | + RedisURI redisURI) { |
| 1465 | + |
| 1466 | + CompletableFuture<T> future = new CompletableFuture<>(); |
| 1467 | + |
| 1468 | + ((TargetAware) delegate).getConnectionAsync(connectionType, redisURI).whenComplete((t, throwable) -> { |
| 1469 | + |
| 1470 | + if (throwable != null) { |
| 1471 | + future.completeExceptionally(translateException(throwable)); |
| 1472 | + } else { |
| 1473 | + future.complete(t); |
| 1474 | + } |
| 1475 | + }); |
| 1476 | + |
| 1477 | + return future; |
| 1478 | + } |
| 1479 | + |
| 1480 | + /* |
| 1481 | + * (non-Javadoc) |
| 1482 | + * @see org.springframework.data.redis.connection.lettuce.LettuceConnectionProvider#release(io.lettuce.core.api.StatefulConnection) |
| 1483 | + */ |
| 1484 | + @Override |
| 1485 | + public void release(StatefulConnection<?, ?> connection) { |
| 1486 | + delegate.release(connection); |
| 1487 | + } |
| 1488 | + |
| 1489 | + /* |
| 1490 | + * (non-Javadoc) |
| 1491 | + * @see org.springframework.data.redis.connection.lettuce.LettuceConnectionProvider#releaseAsync(io.lettuce.core.api.StatefulConnection) |
| 1492 | + */ |
| 1493 | + @Override |
| 1494 | + public CompletableFuture<Void> releaseAsync(StatefulConnection<?, ?> connection) { |
| 1495 | + return delegate.releaseAsync(connection); |
| 1496 | + } |
| 1497 | + |
| 1498 | + /* |
| 1499 | + * (non-Javadoc) |
| 1500 | + * @see org.springframework.beans.factory.DisposableBean#destroy() |
| 1501 | + */ |
| 1502 | + @Override |
| 1503 | + public void destroy() throws Exception { |
| 1504 | + |
| 1505 | + if (delegate instanceof DisposableBean) { |
| 1506 | + ((DisposableBean) delegate).destroy(); |
| 1507 | + } |
| 1508 | + } |
| 1509 | + |
| 1510 | + private RuntimeException translateException(Throwable e) { |
| 1511 | + return e instanceof RedisConnectionFailureException ? (RedisConnectionFailureException) e |
| 1512 | + : new RedisConnectionFailureException("Unable to connect to Redis", e); |
| 1513 | + } |
| 1514 | + |
| 1515 | + } |
1396 | 1516 | }
|
0 commit comments