Introduce FaultTolerantRedisClient

This commit is contained in:
Jon Chambers
2024-10-09 09:22:10 -04:00
committed by GitHub
parent 9d980f36b0
commit a9117010f9
61 changed files with 744 additions and 462 deletions

View File

@@ -35,8 +35,8 @@ import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.whispersystems.textsecuregcm.redis.ClusterLuaScript;
import org.whispersystems.textsecuregcm.redis.FaultTolerantPubSubConnection;
import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisCluster;
import org.whispersystems.textsecuregcm.redis.FaultTolerantPubSubClusterConnection;
import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisClusterClient;
import org.whispersystems.textsecuregcm.storage.Device;
/**
@@ -52,8 +52,8 @@ public class ClientPresenceManager extends RedisClusterPubSubAdapter<String, Str
private final String managerId = UUID.randomUUID().toString();
private final String connectedClientSetKey = getConnectedClientSetKey(managerId);
private final FaultTolerantRedisCluster presenceCluster;
private final FaultTolerantPubSubConnection<String, String> pubSubConnection;
private final FaultTolerantRedisClusterClient presenceCluster;
private final FaultTolerantPubSubClusterConnection<String, String> pubSubConnection;
private final ClusterLuaScript clearPresenceScript;
private final ClusterLuaScript renewPresenceScript;
@@ -80,7 +80,7 @@ public class ClientPresenceManager extends RedisClusterPubSubAdapter<String, Str
private static final Logger log = LoggerFactory.getLogger(ClientPresenceManager.class);
public ClientPresenceManager(final FaultTolerantRedisCluster presenceCluster,
public ClientPresenceManager(final FaultTolerantRedisClusterClient presenceCluster,
final ScheduledExecutorService scheduledExecutorService,
final ExecutorService keyspaceNotificationExecutorService) throws IOException {
this.presenceCluster = presenceCluster;
@@ -106,7 +106,7 @@ public class ClientPresenceManager extends RedisClusterPubSubAdapter<String, Str
}
@VisibleForTesting
FaultTolerantPubSubConnection<String, String> getPubSubConnection() {
FaultTolerantPubSubClusterConnection<String, String> getPubSubConnection() {
return pubSubConnection;
}

View File

@@ -10,12 +10,7 @@ import static com.codahale.metrics.MetricRegistry.name;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import io.dropwizard.lifecycle.Managed;
import io.github.resilience4j.circuitbreaker.CircuitBreaker;
import io.lettuce.core.RedisClient;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.codec.ByteArrayCodec;
import io.lettuce.core.pubsub.RedisPubSubAdapter;
import io.lettuce.core.pubsub.StatefulRedisPubSubConnection;
import io.micrometer.core.instrument.Metrics;
import io.micrometer.core.instrument.Tags;
import java.nio.charset.StandardCharsets;
@@ -24,18 +19,15 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.whispersystems.textsecuregcm.configuration.CircuitBreakerConfiguration;
import org.whispersystems.textsecuregcm.redis.FaultTolerantPubSubConnection;
import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisClient;
import org.whispersystems.textsecuregcm.redis.RedisOperation;
import org.whispersystems.textsecuregcm.storage.PubSubProtos;
import org.whispersystems.textsecuregcm.util.CircuitBreakerUtil;
public class ProvisioningManager extends RedisPubSubAdapter<byte[], byte[]> implements Managed {
private final RedisClient redisClient;
private final StatefulRedisPubSubConnection<byte[], byte[]> subscriptionConnection;
private final StatefulRedisConnection<byte[], byte[]> publicationConnection;
private final CircuitBreaker circuitBreaker;
private final FaultTolerantRedisClient pubSubClient;
private final FaultTolerantPubSubConnection<byte[], byte[]> pubSubConnection;
private final Map<String, Consumer<PubSubProtos.PubSubMessage>> listenersByProvisioningAddress =
new ConcurrentHashMap<>();
@@ -50,46 +42,31 @@ public class ProvisioningManager extends RedisPubSubAdapter<byte[], byte[]> impl
private static final Logger logger = LoggerFactory.getLogger(ProvisioningManager.class);
public ProvisioningManager(final RedisClient redisClient,
final CircuitBreakerConfiguration circuitBreakerConfiguration) {
this.redisClient = redisClient;
this.subscriptionConnection = redisClient.connectPubSub(new ByteArrayCodec());
this.publicationConnection = redisClient.connect(new ByteArrayCodec());
this.circuitBreaker = CircuitBreaker.of("pubsub-breaker", circuitBreakerConfiguration.toCircuitBreakerConfig());
CircuitBreakerUtil.registerMetrics(circuitBreaker, ProvisioningManager.class, Tags.empty());
public ProvisioningManager(final FaultTolerantRedisClient pubSubClient) {
this.pubSubClient = pubSubClient;
this.pubSubConnection = pubSubClient.createBinaryPubSubConnection();
Metrics.gaugeMapSize(ACTIVE_LISTENERS_GAUGE_NAME, Tags.empty(), listenersByProvisioningAddress);
}
@Override
public void start() throws Exception {
subscriptionConnection.addListener(this);
pubSubConnection.usePubSubConnection(connection -> connection.addListener(this));
}
@Override
public void stop() throws Exception {
subscriptionConnection.removeListener(this);
subscriptionConnection.close();
publicationConnection.close();
redisClient.shutdown();
pubSubConnection.usePubSubConnection(connection -> connection.removeListener(this));
}
public void addListener(final String address, final Consumer<PubSubProtos.PubSubMessage> listener) {
listenersByProvisioningAddress.put(address, listener);
circuitBreaker.executeRunnable(
() -> subscriptionConnection.sync().subscribe(address.getBytes(StandardCharsets.UTF_8)));
pubSubConnection.usePubSubConnection(connection -> connection.sync().subscribe(address.getBytes(StandardCharsets.UTF_8)));
}
public void removeListener(final String address) {
RedisOperation.unchecked(() -> circuitBreaker.executeRunnable(
() -> subscriptionConnection.sync().unsubscribe(address.getBytes(StandardCharsets.UTF_8))));
RedisOperation.unchecked(() ->
pubSubConnection.usePubSubConnection(connection -> connection.sync().unsubscribe(address.getBytes(StandardCharsets.UTF_8))));
listenersByProvisioningAddress.remove(address);
}
@@ -100,9 +77,8 @@ public class ProvisioningManager extends RedisPubSubAdapter<byte[], byte[]> impl
.setContent(ByteString.copyFrom(body))
.build();
final boolean receiverPresent = circuitBreaker.executeSupplier(
() -> publicationConnection.sync()
.publish(address.getBytes(StandardCharsets.UTF_8), pubSubMessage.toByteArray()) > 0);
final boolean receiverPresent = pubSubClient.withBinaryConnection(connection ->
connection.sync().publish(address.getBytes(StandardCharsets.UTF_8), pubSubMessage.toByteArray()) > 0);
Metrics.counter(SEND_PROVISIONING_MESSAGE_COUNTER_NAME, "online", String.valueOf(receiverPresent)).increment();

View File

@@ -31,7 +31,7 @@ import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.whispersystems.textsecuregcm.redis.ClusterLuaScript;
import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisCluster;
import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisClusterClient;
import org.whispersystems.textsecuregcm.storage.Account;
import org.whispersystems.textsecuregcm.storage.AccountsManager;
import org.whispersystems.textsecuregcm.storage.Device;
@@ -62,7 +62,7 @@ public class PushNotificationScheduler implements Managed {
private final APNSender apnSender;
private final FcmSender fcmSender;
private final AccountsManager accountsManager;
private final FaultTolerantRedisCluster pushSchedulingCluster;
private final FaultTolerantRedisClusterClient pushSchedulingCluster;
private final Clock clock;
private final ClusterLuaScript scheduleBackgroundApnsNotificationScript;
@@ -141,7 +141,7 @@ public class PushNotificationScheduler implements Managed {
}
}
public PushNotificationScheduler(final FaultTolerantRedisCluster pushSchedulingCluster,
public PushNotificationScheduler(final FaultTolerantRedisClusterClient pushSchedulingCluster,
final APNSender apnSender,
final FcmSender fcmSender,
final AccountsManager accountsManager,
@@ -158,7 +158,7 @@ public class PushNotificationScheduler implements Managed {
}
@VisibleForTesting
PushNotificationScheduler(final FaultTolerantRedisCluster pushSchedulingCluster,
PushNotificationScheduler(final FaultTolerantRedisClusterClient pushSchedulingCluster,
final APNSender apnSender,
final FcmSender fcmSender,
final AccountsManager accountsManager,