package ddth.dasp.hetty.qnt.redis; import java.util.HashSet; import java.util.Set; import java.util.concurrent.TimeUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ddth.dasp.common.redis.IRedisClient; import ddth.dasp.common.redis.IRedisClientFactory; import ddth.dasp.common.redis.PoolConfig; import ddth.dasp.hetty.qnt.IQueueReader; import ddth.dasp.hetty.qnt.IQueueWriter; public class RedisQueue implements IQueueReader, IQueueWriter { private final Logger LOGGER = LoggerFactory.getLogger(RedisQueue.class); private final static long QUEUE_TTL_SECONDS = 60; private IRedisClientFactory redisClientFactory; private String redisHost = "localhost"; private int redisPort = IRedisClient.DEFAULT_REDIS_PORT; private String redisUsername, redisPassword; private PoolConfig poolConfig; private int queueSizeThreshold = 1000; private long lastWrite = System.currentTimeMillis(); private Set<IRedisClient> allocatedRedisClients = new HashSet<IRedisClient>(); protected IRedisClientFactory getRedisClientFactory() { return redisClientFactory; } public RedisQueue setRedisClientFactory(IRedisClientFactory redisClientFactory) { this.redisClientFactory = redisClientFactory; return this; } protected String getRedisHost() { return redisHost; } public RedisQueue setRedisHost(String redisHost) { this.redisHost = redisHost; return this; } protected int getRedisPort() { return redisPort; } public RedisQueue setRedisPort(int redisPort) { this.redisPort = redisPort; return this; } protected String getRedisUsername() { return redisUsername; } public RedisQueue setRedisUsername(String redisUsername) { this.redisUsername = redisUsername; return this; } protected String getRedisPassword() { return redisPassword; } public RedisQueue setRedisPassword(String redisPassword) { this.redisPassword = redisPassword; return this; } protected PoolConfig getPoolConfig() { return poolConfig; } public RedisQueue setPoolConfig(PoolConfig poolConfig) { this.poolConfig = poolConfig; return this; } protected int getQueueSizeThreshold() { return queueSizeThreshold; } public RedisQueue setQueueSizeThreshold(int queueSizeThreshold) { this.queueSizeThreshold = queueSizeThreshold; return this; } private IRedisClient getRedisClient() { IRedisClient redisClient = redisClientFactory.getRedisClient(redisHost, redisPort, redisUsername, redisPassword, poolConfig); if (redisClient != null) { allocatedRedisClients.add(redisClient); } return redisClient; } private void returnRedisClient(IRedisClient redisClient) { if (redisClient != null) { try { allocatedRedisClients.remove(redisClient); } finally { redisClientFactory.returnRedisClient(redisClient); } } } public void init() { } public void destroy() { for (IRedisClient redisClient : allocatedRedisClients) { try { redisClientFactory.returnRedisClient(redisClient); } catch (Exception e) { } } allocatedRedisClients.clear(); } /** * {@inheritDoc} */ @Override public boolean queueWrite(String queueName, Object value) { return queueWrite(queueName, value, 5000, TimeUnit.MILLISECONDS); } /** * {@inheritDoc} */ @Override public boolean queueWrite(String queueName, Object value, long timeout, TimeUnit timeUnit) { IRedisClient redisClient = getRedisClient(); if (redisClient != null) { try { int queueSize = (int) redisClient.listSize(queueName); if (queueSize < 0 || queueSize > queueSizeThreshold) { LOGGER.warn("Queue not available or full!"); return false; } if (value instanceof byte[]) { redisClient.listPush(queueName, (byte[]) value); } else { redisClient.listPush(queueName, value != null ? value.toString() : null); } if (System.currentTimeMillis() - lastWrite > QUEUE_TTL_SECONDS * 1000) { lastWrite = System.currentTimeMillis(); redisClient.expire(queueName, (int) QUEUE_TTL_SECONDS); } return true; } finally { returnRedisClient(redisClient); } } return false; } /** * {@inheritDoc} */ @Override public Object queueRead(String queueName) { return queueRead(queueName, 5000, TimeUnit.MILLISECONDS); } /** * {@inheritDoc} */ @Override public Object queueRead(String queueName, long timeout, TimeUnit timeUnit) { IRedisClient redisClient = getRedisClient(); try { return redisClient != null ? redisClient.listPopAsBinary(queueName, true, (int) timeUnit.toSeconds(timeout)) : null; } finally { returnRedisClient(redisClient); } } }