|
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;
|
|
36 | 36 | import java.util.ArrayList;
|
37 | 37 | import java.util.List;
|
38 | 38 | import java.util.Optional;
|
| 39 | +import java.util.concurrent.CompletableFuture; |
| 40 | +import java.util.concurrent.CompletionStage; |
39 | 41 | import java.util.concurrent.TimeUnit;
|
40 | 42 | import java.util.function.Consumer;
|
41 | 43 | import java.util.stream.Collectors;
|
42 | 44 |
|
43 | 45 | import org.apache.commons.logging.Log;
|
44 | 46 | import org.apache.commons.logging.LogFactory;
|
| 47 | + |
45 | 48 | import org.springframework.beans.factory.DisposableBean;
|
46 | 49 | import org.springframework.beans.factory.InitializingBean;
|
47 | 50 | import org.springframework.dao.DataAccessException;
|
|
54 | 57 | import org.springframework.data.redis.connection.RedisConfiguration.DomainSocketConfiguration;
|
55 | 58 | import org.springframework.data.redis.connection.RedisConfiguration.WithDatabaseIndex;
|
56 | 59 | import org.springframework.data.redis.connection.RedisConfiguration.WithPassword;
|
| 60 | +import org.springframework.data.redis.connection.lettuce.LettuceConnection.*; |
57 | 61 | import org.springframework.data.util.Optionals;
|
58 | 62 | import org.springframework.lang.Nullable;
|
59 | 63 | 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 |
|
@@ -1222,12 +1227,7 @@ StatefulConnection<E, E> getConnection() {
|
1222 | 1227 | * @return the connection.
|
1223 | 1228 | */
|
1224 | 1229 | private StatefulConnection<E, E> getNativeConnection() {
|
1225 |
| - |
1226 |
| -try { |
1227 |
| -return connectionProvider.getConnection(StatefulConnection.class); |
1228 |
| -} catch (RedisException e) { |
1229 |
| -throw new RedisConnectionFailureException("Unable to connect to Redis", e); |
1230 |
| -} |
| 1230 | +return connectionProvider.getConnection(StatefulConnection.class); |
1231 | 1231 | }
|
1232 | 1232 |
|
1233 | 1233 | /**
|
@@ -1418,4 +1418,124 @@ public Duration getShutdownQuietPeriod() {
|
1418 | 1418 | return shutdownTimeout;
|
1419 | 1419 | }
|
1420 | 1420 | }
|
| 1421 | + |
| 1422 | +/** |
| 1423 | + * {@link LettuceConnectionProvider} that translates connection exceptions into {@link RedisConnectionException}. |
| 1424 | + */ |
| 1425 | +private static class ExceptionTranslatingConnectionProvider |
| 1426 | +implements LettuceConnectionProvider, LettuceConnectionProvider.TargetAware, DisposableBean { |
| 1427 | + |
| 1428 | +private final LettuceConnectionProvider delegate; |
| 1429 | + |
| 1430 | +public ExceptionTranslatingConnectionProvider(LettuceConnectionProvider delegate) { |
| 1431 | +this.delegate = delegate; |
| 1432 | +} |
| 1433 | + |
| 1434 | +/* |
| 1435 | + * (non-Javadoc) |
| 1436 | + * @see org.springframework.data.redis.connection.lettuce.LettuceConnectionProvider#getConnection(java.lang.Class) |
| 1437 | + */ |
| 1438 | +@Override |
| 1439 | +public <T extends StatefulConnection<?, ?>> T getConnection(Class<T> connectionType) { |
| 1440 | + |
| 1441 | +try { |
| 1442 | +return delegate.getConnection(connectionType); |
| 1443 | +} catch (RuntimeException e) { |
| 1444 | +throw translateException(e); |
| 1445 | +} |
| 1446 | +} |
| 1447 | + |
| 1448 | +/* |
| 1449 | + * (non-Javadoc) |
| 1450 | + * @see org.springframework.data.redis.connection.lettuce.LettuceConnectionProvider#getConnection(java.lang.Class, RedisURI) |
| 1451 | + */ |
| 1452 | +@Override |
| 1453 | +public <T extends StatefulConnection<?, ?>> T getConnection(Class<T> connectionType, RedisURI redisURI) { |
| 1454 | + |
| 1455 | +try { |
| 1456 | +return ((TargetAware) delegate).getConnection(connectionType, redisURI); |
| 1457 | +} catch (RuntimeException e) { |
| 1458 | +throw translateException(e); |
| 1459 | +} |
| 1460 | +} |
| 1461 | + |
| 1462 | +/* |
| 1463 | + * (non-Javadoc) |
| 1464 | + * @see org.springframework.data.redis.connection.lettuce.LettuceConnectionProvider#getConnectionAsync(java.lang.Class) |
| 1465 | + */ |
| 1466 | +@Override |
| 1467 | +public <T extends StatefulConnection<?, ?>> CompletionStage<T> getConnectionAsync(Class<T> connectionType) { |
| 1468 | + |
| 1469 | +CompletableFuture<T> future = new CompletableFuture<>(); |
| 1470 | + |
| 1471 | +delegate.getConnectionAsync(connectionType).whenComplete((t, throwable) -> { |
| 1472 | + |
| 1473 | +if (throwable != null) { |
| 1474 | +future.completeExceptionally(translateException(throwable)); |
| 1475 | +} else { |
| 1476 | +future.complete(t); |
| 1477 | +} |
| 1478 | +}); |
| 1479 | + |
| 1480 | +return future; |
| 1481 | +} |
| 1482 | + |
| 1483 | +/* |
| 1484 | + * (non-Javadoc) |
| 1485 | + * @see org.springframework.data.redis.connection.lettuce.LettuceConnectionProvider#getConnectionAsync(java.lang.Class, RedisURI) |
| 1486 | + */ |
| 1487 | +@Override |
| 1488 | +public <T extends StatefulConnection<?, ?>> CompletionStage<T> getConnectionAsync(Class<T> connectionType, |
| 1489 | +RedisURI redisURI) { |
| 1490 | + |
| 1491 | +CompletableFuture<T> future = new CompletableFuture<>(); |
| 1492 | + |
| 1493 | +((TargetAware) delegate).getConnectionAsync(connectionType, redisURI).whenComplete((t, throwable) -> { |
| 1494 | + |
| 1495 | +if (throwable != null) { |
| 1496 | +future.completeExceptionally(translateException(throwable)); |
| 1497 | +} else { |
| 1498 | +future.complete(t); |
| 1499 | +} |
| 1500 | +}); |
| 1501 | + |
| 1502 | +return future; |
| 1503 | +} |
| 1504 | + |
| 1505 | +/* |
| 1506 | + * (non-Javadoc) |
| 1507 | + * @see org.springframework.data.redis.connection.lettuce.LettuceConnectionProvider#release(io.lettuce.core.api.StatefulConnection) |
| 1508 | + */ |
| 1509 | +@Override |
| 1510 | +public void release(StatefulConnection<?, ?> connection) { |
| 1511 | +delegate.release(connection); |
| 1512 | +} |
| 1513 | + |
| 1514 | +/* |
| 1515 | + * (non-Javadoc) |
| 1516 | + * @see org.springframework.data.redis.connection.lettuce.LettuceConnectionProvider#releaseAsync(io.lettuce.core.api.StatefulConnection) |
| 1517 | + */ |
| 1518 | +@Override |
| 1519 | +public CompletableFuture<Void> releaseAsync(StatefulConnection<?, ?> connection) { |
| 1520 | +return delegate.releaseAsync(connection); |
| 1521 | +} |
| 1522 | + |
| 1523 | +/* |
| 1524 | + * (non-Javadoc) |
| 1525 | + * @see org.springframework.beans.factory.DisposableBean#destroy() |
| 1526 | + */ |
| 1527 | +@Override |
| 1528 | +public void destroy() throws Exception { |
| 1529 | + |
| 1530 | +if (delegate instanceof DisposableBean) { |
| 1531 | +((DisposableBean) delegate).destroy(); |
| 1532 | +} |
| 1533 | +} |
| 1534 | + |
| 1535 | +private RuntimeException translateException(Throwable e) { |
| 1536 | +return e instanceof RedisConnectionFailureException ? (RedisConnectionFailureException) e |
| 1537 | +: new RedisConnectionFailureException("Unable to connect to Redis", e); |
| 1538 | +} |
| 1539 | + |
| 1540 | +} |
1421 | 1541 | }
|
0 commit comments