package com.moshi.receptionist.redis.sub.handler;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.moshi.receptionist.redis.common.Constants;
import com.moshi.receptionist.redis.common.listener.MessageListener;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPubSub;
public class PSubHandler extends JedisPubSub {
private static final Logger log = LoggerFactory.getLogger(PSubHandler.class);
private Jedis jedis;
private String clientId;
private static Map<String, PSubHandler> pool = new ConcurrentHashMap<String, PSubHandler>();
private List<MessageListener> messageListeners = new ArrayList<MessageListener>();
private PSubHandler(Jedis jedis,String clientId){
this.jedis = jedis;
this.clientId = clientId;
}
public void handle(String channel,String message){
if(log.isDebugEnabled()){
log.debug("on message recv the channel is {} and the message is {}",channel,message);
}
int index = message.indexOf("/");
if(index < 0){
return;
}
Long txid = Long.valueOf(message.substring(0,index));
String messageTag = message.substring(index+1);
DateFormat df = new SimpleDateFormat("yyyyMMdd");
String key =Constants.MESSAGE_BOX+messageTag+":"+df.format(new Date());
while(true){
String lm = jedis.lindex(key, 0);//获取第一个消息
if(lm == null){
break;
}
int li = lm.indexOf("/");
//如果消息不合法,删除并处理
if(li < 0){
String result = jedis.lpop(key);//删除当前message
//为空
if(result == null){
break;
}
for(MessageListener listener:messageListeners){
listener.onMessageEvent(messageTag, lm);
}
continue;
}
Long lxid = Long.valueOf(lm.substring(0,li));//获取消息的txid
//直接消费txid之前的残留消息
if(txid >= lxid){
jedis.lpop(key);//删除当前message
continue;
}else{
break;
}
}
}
public void subscribe(String channel){
StringBuffer key = new StringBuffer();
key.append(clientId)
.append("/")
.append(channel);
if(log.isDebugEnabled()){
log.debug("subscribe key is {}.",key);
}
boolean exist = jedis.sismember(Constants.SUBSCRIBE_CENTER+channel,key.toString());
if(!exist){
jedis.sadd(Constants.SUBSCRIBE_CENTER+channel, key.toString());
}
}
public void unsubscribe(String channel){
StringBuffer key = new StringBuffer();
key.append(clientId)
.append("/")
.append(channel);
if(log.isDebugEnabled()){
log.debug("unsubscribe key is {}.",key);
}
jedis.srem(Constants.SUBSCRIBE_CENTER+channel, key.toString());//从“活跃订阅者”集合中删除
//jedis.del(key);//删除“订阅者消息队列”
}
public void registerMessageListener(MessageListener listener){
this.messageListeners.add(listener);
}
public void removeMessageListener(MessageListener listener){
this.messageListeners.remove(listener);
}
@Override
public void onMessage(String channel, String message) {
//此处我们可以取消订阅
if(message.equalsIgnoreCase("quit")){
this.unsubscribe(channel);
}
this.handle(channel, message);
}
@Override
public void onPMessage(String pattern, String channel, String message) {
if(log.isDebugEnabled()){
log.debug("pattern message the p {} c {} m {}.",pattern,channel,message);
}
this.handle(channel, message);
}
@Override
public void onSubscribe(String channel, int subscribedChannels) {
this.subscribe(channel);
if(log.isDebugEnabled()){
log.debug("onSubscribe the channel is {} and current subscribedChannels size is {}.",channel,subscribedChannels);
}
}
@Override
public void onUnsubscribe(String channel, int subscribedChannels) {
this.unsubscribe(channel);
if(log.isDebugEnabled()){
log.debug("onUnSubscribe the channel is {} and current subscribedChannels size is {}.",channel,subscribedChannels);
}
}
@Override
public void onPUnsubscribe(String pattern, int subscribedChannels) {
if(log.isDebugEnabled()){
log.debug("onPattern UnSubscribe the pattern is {} and current subscribedChannels size is {}.",pattern,subscribedChannels);
}
}
@Override
public void onPSubscribe(String pattern, int subscribedChannels) {
if(log.isDebugEnabled()){
log.debug("onPattern Subscribe the pattern is {} and current subscribedChannels size is {}.",pattern,subscribedChannels);
}
}
@Override
public void unsubscribe(String... channels) {
super.unsubscribe(channels);
for(String channel : channels){
this.unsubscribe(channel);
}
}
public static PSubHandler getInstance(Jedis jedis,String clientId){
if(!pool.containsKey(clientId)){
PSubHandler handler = new PSubHandler(jedis, clientId);
pool.put(clientId, handler);
}
return pool.get(clientId);
}
}