Polishing.

We now ensure proper exception handling in connection close methods to avoid resource leaks. Also, exceptions during connection close are no longer thrown to ensure proper resource cleanup behavior and API design.

See #2356
This commit is contained in:
Mark Paluch
2022-07-14 16:04:37 +02:00
parent e13370307c
commit 0c51d99e9b
2 changed files with 32 additions and 14 deletions

View File

@@ -19,10 +19,12 @@ import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.dao.InvalidDataAccessResourceUsageException;
import org.springframework.data.redis.RedisSystemException;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
@@ -33,6 +35,8 @@ import org.springframework.util.Assert;
*/
public abstract class AbstractRedisConnection implements DefaultedRedisConnection {
private final Log LOGGER = LogFactory.getLog(getClass());
private @Nullable RedisSentinelConfiguration sentinelConfiguration;
private final Map<RedisNode, RedisSentinelConnection> connectionCache = new ConcurrentHashMap<>();
@@ -104,18 +108,23 @@ public abstract class AbstractRedisConnection implements DefaultedRedisConnectio
@Override
public void close() throws DataAccessException {
if (!connectionCache.isEmpty()) {
for (RedisNode node : connectionCache.keySet()) {
RedisSentinelConnection connection = connectionCache.remove(node);
if (connection.isOpen()) {
try {
connection.close();
} catch (IOException e) {
throw new RedisSystemException("Failed to close sentinel connection", e);
}
}
if (connectionCache.isEmpty()) {
return;
}
for (RedisNode node : connectionCache.keySet()) {
RedisSentinelConnection connection = connectionCache.remove(node);
if (!connection.isOpen()) {
continue;
}
try {
connection.close();
} catch (IOException e) {
LOGGER.info("Failed to close sentinel connection", e);
}
}
}
}

View File

@@ -56,6 +56,9 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Supplier;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.core.convert.converter.Converter;
import org.springframework.dao.DataAccessException;
@@ -91,6 +94,8 @@ import org.springframework.util.ObjectUtils;
*/
public class LettuceConnection extends AbstractRedisConnection {
private final Log LOGGER = LogFactory.getLog(getClass());
static final RedisCodec<byte[], byte[]> CODEC = ByteArrayCodec.INSTANCE;
private static final ExceptionTranslationStrategy EXCEPTION_TRANSLATION = new FallbackExceptionTranslationStrategy(
@@ -414,7 +419,7 @@ public class LettuceConnection extends AbstractRedisConnection {
* @see org.springframework.data.redis.connection.AbstractRedisConnection#close()
*/
@Override
public void close() throws DataAccessException {
public void close() {
super.close();
@@ -424,7 +429,11 @@ public class LettuceConnection extends AbstractRedisConnection {
isClosed = true;
reset();
try {
reset();
} catch (RuntimeException e) {
LOGGER.debug("Failed to reset connection during close", e);
}
}
private void reset() {