107 lines
2.6 KiB
Java
107 lines
2.6 KiB
Java
|
package mineplex.reportserver;
|
||
|
|
||
|
import java.util.logging.Level;
|
||
|
import java.util.logging.Logger;
|
||
|
|
||
|
import org.apache.commons.lang3.Validate;
|
||
|
import org.apache.commons.lang3.time.DurationFormatUtils;
|
||
|
import redis.clients.jedis.Jedis;
|
||
|
import redis.clients.jedis.JedisPool;
|
||
|
|
||
|
/**
|
||
|
* Establishes and maintains a connection to Redis.
|
||
|
*/
|
||
|
public class RedisConnectionHandler implements Runnable
|
||
|
{
|
||
|
private final String _name;
|
||
|
private final JedisPool _jedisPool;
|
||
|
private final RedisCommandHandler _handler;
|
||
|
private final String[] _channels;
|
||
|
private final Logger _logger;
|
||
|
|
||
|
private long _lastConnectionMillis = -1;
|
||
|
private Throwable _lastThrowable = null;
|
||
|
|
||
|
public RedisConnectionHandler(String name, JedisPool jedisPool, RedisCommandHandler handler, String[] channels, Logger logger)
|
||
|
{
|
||
|
_name = name;
|
||
|
_jedisPool = jedisPool;
|
||
|
_handler = handler;
|
||
|
_channels = channels;
|
||
|
_logger = logger;
|
||
|
|
||
|
Validate.isTrue(channels.length > 0, "Must provide at least one channel.");
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void run()
|
||
|
{
|
||
|
while (!Thread.interrupted())
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
registerChannelHandlers();
|
||
|
}
|
||
|
catch (Throwable e)
|
||
|
{
|
||
|
// Only log new errors (prevents same error being spammed)
|
||
|
if (_lastThrowable == null || !e.getClass().equals(_lastThrowable.getClass()))
|
||
|
{
|
||
|
if (_lastThrowable == null) // connection just failed
|
||
|
{
|
||
|
_lastConnectionMillis = System.currentTimeMillis();
|
||
|
}
|
||
|
|
||
|
_logger.log(Level.SEVERE, prefixMessage(
|
||
|
"Exception in Redis connection"
|
||
|
+ (_lastConnectionMillis != -1 ? " (no connection for " + getLastConnectionDuration() + ")" : "")
|
||
|
+ ", attempting to regain connection."
|
||
|
), e);
|
||
|
|
||
|
_lastThrowable = e;
|
||
|
}
|
||
|
|
||
|
try
|
||
|
{
|
||
|
Thread.sleep(1000 * 5);
|
||
|
}
|
||
|
catch (InterruptedException ignored) {}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
_jedisPool.destroy();
|
||
|
_logger.warning("Thread interrupted, end of connection.");
|
||
|
}
|
||
|
|
||
|
private void registerChannelHandlers()
|
||
|
{
|
||
|
try (Jedis jedis = _jedisPool.getResource())
|
||
|
{
|
||
|
connectionEstablished();
|
||
|
jedis.subscribe(_handler, _channels);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void connectionEstablished()
|
||
|
{
|
||
|
// subscribe blocks so we need to do all this before
|
||
|
_logger.info(
|
||
|
_lastThrowable == null
|
||
|
? prefixMessage("Connected.")
|
||
|
: prefixMessage(String.format("Connected after %s.", getLastConnectionDuration()))
|
||
|
);
|
||
|
|
||
|
_lastThrowable = null;
|
||
|
}
|
||
|
|
||
|
private String prefixMessage(String message)
|
||
|
{
|
||
|
return String.format("[%s] %s", _name, message);
|
||
|
}
|
||
|
|
||
|
private String getLastConnectionDuration()
|
||
|
{
|
||
|
return DurationFormatUtils.formatDurationWords(System.currentTimeMillis() - _lastConnectionMillis, true, true);
|
||
|
}
|
||
|
}
|