mirror of
https://github.com/signalapp/Signal-Server
synced 2026-04-22 01:08:05 +01:00
Improve Redis exception handling
This commit is contained in:
@@ -21,7 +21,6 @@ import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.whispersystems.textsecuregcm.redis.RedisClusterExtension;
|
||||
import org.whispersystems.textsecuregcm.redis.RedisException;
|
||||
import org.whispersystems.textsecuregcm.storage.Account;
|
||||
import org.whispersystems.textsecuregcm.storage.AccountsManager;
|
||||
import org.whispersystems.textsecuregcm.storage.Device;
|
||||
@@ -67,7 +66,7 @@ class ApnFallbackManagerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testClusterInsert() throws RedisException {
|
||||
void testClusterInsert() {
|
||||
final String endpoint = apnFallbackManager.getEndpointKey(account, device);
|
||||
|
||||
assertTrue(apnFallbackManager.getPendingDestinations(SlotHash.getSlot(endpoint), 1).isEmpty());
|
||||
@@ -88,7 +87,7 @@ class ApnFallbackManagerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testProcessNextSlot() throws RedisException {
|
||||
void testProcessNextSlot() {
|
||||
final ApnFallbackManager.NotificationWorker worker = apnFallbackManager.new NotificationWorker();
|
||||
|
||||
apnFallbackManager.schedule(account, device, System.currentTimeMillis() - 30_000);
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2020 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.redis;
|
||||
|
||||
import io.lettuce.core.RedisClient;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.whispersystems.textsecuregcm.configuration.CircuitBreakerConfiguration;
|
||||
import org.whispersystems.textsecuregcm.providers.RedisClientFactory;
|
||||
import redis.embedded.RedisServer;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assume.assumeFalse;
|
||||
|
||||
public class AbstractRedisSingletonTest {
|
||||
|
||||
private static RedisServer redisServer;
|
||||
|
||||
private FaultTolerantRedisClient redisClient;
|
||||
private ReplicatedJedisPool replicatedJedisPool;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpBeforeClass() throws Exception {
|
||||
assumeFalse(System.getProperty("os.name").equalsIgnoreCase("windows"));
|
||||
|
||||
redisServer = RedisServer.builder()
|
||||
.setting("appendonly no")
|
||||
.setting("dir " + System.getProperty("java.io.tmpdir"))
|
||||
.port(AbstractRedisClusterTest.getNextRedisClusterPort())
|
||||
.build();
|
||||
|
||||
redisServer.start();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
final String redisUrl = String.format("redis://127.0.0.1:%d", redisServer.ports().get(0));
|
||||
|
||||
redisClient = new FaultTolerantRedisClient("test-client",
|
||||
RedisClient.create(redisUrl),
|
||||
Duration.ofSeconds(2),
|
||||
new CircuitBreakerConfiguration());
|
||||
|
||||
replicatedJedisPool = new RedisClientFactory("test-pool",
|
||||
redisUrl,
|
||||
List.of(redisUrl),
|
||||
new CircuitBreakerConfiguration()).getRedisClientPool();
|
||||
|
||||
redisClient.useClient(connection -> connection.sync().flushall());
|
||||
}
|
||||
|
||||
protected FaultTolerantRedisClient getRedisClient() {
|
||||
return redisClient;
|
||||
}
|
||||
|
||||
protected ReplicatedJedisPool getJedisPool() {
|
||||
return replicatedJedisPool;
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
redisClient.shutdown();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownAfterClass() {
|
||||
redisServer.stop();
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ import org.whispersystems.textsecuregcm.configuration.RetryConfiguration;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
@@ -56,15 +57,17 @@ public class FaultTolerantPubSubConnectionTest {
|
||||
public void testBreaker() {
|
||||
when(pubSubCommands.get(anyString()))
|
||||
.thenReturn("value")
|
||||
.thenThrow(new io.lettuce.core.RedisException("Badness has ensued."));
|
||||
.thenThrow(new RuntimeException("Badness has ensued."));
|
||||
|
||||
assertEquals("value", faultTolerantPubSubConnection.withPubSubConnection(connection -> connection.sync().get("key")));
|
||||
|
||||
assertThrows(RedisException.class,
|
||||
() -> faultTolerantPubSubConnection.withPubSubConnection(connection -> connection.sync().get("OH NO")));
|
||||
|
||||
assertThrows(CallNotPermittedException.class,
|
||||
final RedisException redisException = assertThrows(RedisException.class,
|
||||
() -> faultTolerantPubSubConnection.withPubSubConnection(connection -> connection.sync().get("OH NO")));
|
||||
|
||||
assertTrue(redisException.getCause() instanceof CallNotPermittedException);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2020 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.redis;
|
||||
|
||||
import io.github.resilience4j.circuitbreaker.CallNotPermittedException;
|
||||
import io.lettuce.core.RedisClient;
|
||||
import io.lettuce.core.RedisException;
|
||||
import io.lettuce.core.api.StatefulRedisConnection;
|
||||
import io.lettuce.core.api.sync.RedisCommands;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.whispersystems.textsecuregcm.configuration.CircuitBreakerConfiguration;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class FaultTolerantRedisClientTest {
|
||||
|
||||
private RedisCommands<String, String> commands;
|
||||
private FaultTolerantRedisClient faultTolerantRedisClient;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Before
|
||||
public void setUp() {
|
||||
final RedisClient redisClient = mock(RedisClient.class);
|
||||
final StatefulRedisConnection<String, String> clusterConnection = mock(StatefulRedisConnection.class);
|
||||
|
||||
commands = mock(RedisCommands.class);
|
||||
|
||||
when(redisClient.connect()).thenReturn(clusterConnection);
|
||||
when(clusterConnection.sync()).thenReturn(commands);
|
||||
|
||||
final CircuitBreakerConfiguration breakerConfiguration = new CircuitBreakerConfiguration();
|
||||
breakerConfiguration.setFailureRateThreshold(100);
|
||||
breakerConfiguration.setRingBufferSizeInClosedState(1);
|
||||
breakerConfiguration.setWaitDurationInOpenStateInSeconds(Integer.MAX_VALUE);
|
||||
|
||||
faultTolerantRedisClient = new FaultTolerantRedisClient("test", redisClient, Duration.ofSeconds(2), breakerConfiguration);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBreaker() {
|
||||
when(commands.get(anyString()))
|
||||
.thenReturn("value")
|
||||
.thenThrow(new io.lettuce.core.RedisException("Badness has ensued."));
|
||||
|
||||
assertEquals("value", faultTolerantRedisClient.withClient(connection -> connection.sync().get("key")));
|
||||
|
||||
assertThrows(RedisException.class,
|
||||
() -> faultTolerantRedisClient.withClient(connection -> connection.sync().get("OH NO")));
|
||||
|
||||
assertThrows(CallNotPermittedException.class,
|
||||
() -> faultTolerantRedisClient.withClient(connection -> connection.sync().get("OH NO")));
|
||||
}
|
||||
}
|
||||
@@ -66,15 +66,17 @@ public class FaultTolerantRedisClusterTest {
|
||||
public void testBreaker() {
|
||||
when(clusterCommands.get(anyString()))
|
||||
.thenReturn("value")
|
||||
.thenThrow(new RedisException("Badness has ensued."));
|
||||
.thenThrow(new RuntimeException("Badness has ensued."));
|
||||
|
||||
assertEquals("value", faultTolerantCluster.withCluster(connection -> connection.sync().get("key")));
|
||||
|
||||
assertThrows(RedisException.class,
|
||||
() -> faultTolerantCluster.withCluster(connection -> connection.sync().get("OH NO")));
|
||||
|
||||
assertThrows(CallNotPermittedException.class,
|
||||
final RedisException redisException = assertThrows(RedisException.class,
|
||||
() -> faultTolerantCluster.withCluster(connection -> connection.sync().get("OH NO")));
|
||||
|
||||
assertTrue(redisException.getCause() instanceof CallNotPermittedException);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user