refactor: Reconnect to Redis when connection lost (#230)

* Add redis reconnection

* Add separated method to handle thread unlock

* Add reconnection time constant
feat/data-edit-commands
Rubén 10 months ago committed by GitHub
parent 6641e11fd9
commit 31920d056d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -41,12 +41,16 @@ import java.util.logging.Level;
public class RedisManager extends JedisPubSub {
protected static final String KEY_NAMESPACE = "husksync:";
private static final int RECONNECTION_TIME = 8000;
private final HuskSync plugin;
private final String clusterId;
private Pool<Jedis> jedisPool;
private final Map<UUID, CompletableFuture<Optional<DataSnapshot.Packed>>> pendingRequests;
private boolean enabled;
private boolean reconnected;
public RedisManager(@NotNull HuskSync plugin) {
this.plugin = plugin;
this.clusterId = plugin.getSettings().getClusterId();
@ -88,18 +92,53 @@ public class RedisManager extends JedisPubSub {
}
// Subscribe using a thread (rather than a task)
enabled = true;
new Thread(this::subscribe, "husksync:redis_subscriber").start();
}
@Blocking
private void subscribe() {
try (Jedis jedis = jedisPool.getResource()) {
jedis.subscribe(
this,
Arrays.stream(RedisMessage.Type.values())
.map(type -> type.getMessageChannel(clusterId))
.toArray(String[]::new)
);
while (enabled && !Thread.interrupted() && jedisPool != null && !jedisPool.isClosed()) {
try (Jedis jedis = jedisPool.getResource()) {
if (reconnected) {
plugin.log(Level.INFO, "Redis connection is alive again");
}
// Subscribe channels and lock the thread
jedis.subscribe(
this,
Arrays.stream(RedisMessage.Type.values())
.map(type -> type.getMessageChannel(clusterId))
.toArray(String[]::new)
);
} catch (Throwable t) {
// Thread was unlocked due error
onThreadUnlock(t);
}
}
}
private void onThreadUnlock(Throwable t) {
if (enabled) {
if (reconnected) {
plugin.log(Level.WARNING,
"Connection to the Redis server was lost. Attempting reconnection in 8 seconds...", t);
}
try {
this.unsubscribe();
} catch (Throwable ignored) {
// empty catch
}
// Make an instant subscribe if occurs any error on initialization
if (!reconnected) {
reconnected = true;
} else {
try {
Thread.sleep(RECONNECTION_TIME);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
@ -136,6 +175,16 @@ public class RedisManager extends JedisPubSub {
}
}
@Override
public void onSubscribe(String channel, int subscribedChannels) {
plugin.log(Level.INFO, "Redis subscribed to channel '" + channel + "'");
}
@Override
public void onUnsubscribe(String channel, int subscribedChannels) {
plugin.log(Level.INFO, "Redis unsubscribed from channel '" + channel + "'");
}
@Blocking
protected void sendMessage(@NotNull String channel, @NotNull String message) {
try (Jedis jedis = jedisPool.getResource()) {
@ -329,6 +378,7 @@ public class RedisManager extends JedisPubSub {
@Blocking
public void terminate() {
enabled = false;
if (jedisPool != null) {
if (!jedisPool.isClosed()) {
jedisPool.close();

Loading…
Cancel
Save