package com.yiqiniu.easytrans.executor; import java.io.Serializable; import java.util.concurrent.Callable; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; import javax.annotation.Resource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.yiqiniu.easytrans.EasyTransSynchronizer; import com.yiqiniu.easytrans.LogProcessor; import com.yiqiniu.easytrans.RemoteServiceCaller; import com.yiqiniu.easytrans.context.LogProcessContext; import com.yiqiniu.easytrans.context.event.DemiLogEventHandler; import com.yiqiniu.easytrans.log.vo.Content; import com.yiqiniu.easytrans.log.vo.msg.MessageRecordContent; import com.yiqiniu.easytrans.log.vo.msg.MessageSentContent; import com.yiqiniu.easytrans.protocol.BusinessIdentifer; import com.yiqiniu.easytrans.protocol.EasyTransRequest; import com.yiqiniu.easytrans.protocol.IdempotentTypeDeclare.TransactionId; import com.yiqiniu.easytrans.protocol.msg.PublishResult; import com.yiqiniu.easytrans.queue.producer.EasyTransMsgPublishResult; import com.yiqiniu.easytrans.serialization.ObjectSerializer; import com.yiqiniu.easytrans.util.ReflectUtil; public class ReliableMessageMethodExecutor implements EasyTransExecutor,LogProcessor,DemiLogEventHandler { @Resource private EasyTransSynchronizer transSynchronizer; @Resource private RemoteServiceCaller publisher; @Resource private ObjectSerializer serialization; private Logger LOG = LoggerFactory.getLogger(this.getClass()); @SuppressWarnings("unchecked") @Override public <P extends EasyTransRequest<R,E>,E extends EasyTransExecutor,R extends Serializable> Future<R> execute(final P params) { MessageRecordContent content = new MessageRecordContent(); content.setParams(params); transSynchronizer.registerLog(content); final PublishResult result = new PublishResult(); result.setMessageContentId(content.getcId()); FutureTask<PublishResult> future = new FutureTask<PublishResult>(new Callable<PublishResult>() { @Override public PublishResult call() throws Exception { return result; } }); future.run(); return (Future<R>) future; } @Override public boolean logProcess(LogProcessContext ctx, Content currentContent) { if(currentContent instanceof MessageRecordContent){ MessageRecordContent msgRecordContent = (MessageRecordContent) currentContent; //register DemiLogEvent ctx.getDemiLogManager().registerSemiLogEventListener(msgRecordContent, this); } return true; } @Override public boolean onMatch(LogProcessContext logCtx, Content leftContent, Content rightContent) { return true;// do nothig } @Override public boolean onDismatch(LogProcessContext logCtx, Content leftContent) { if(logCtx.getFinalMasterTransStatus() == null){ LOG.info("final trans status unknown,process later." + logCtx.getLogCollection()); return false;//unknown,process later }else if(logCtx.getFinalMasterTransStatus()){ //commit //get Log message MessageRecordContent content = (MessageRecordContent) leftContent; EasyTransRequest<?,?> msg = content.getParams(); TransactionId parentTrxId = logCtx.getTransactionId(); //send message BusinessIdentifer businessIdentifer = ReflectUtil.getBusinessIdentifer(msg.getClass()); EasyTransMsgPublishResult send = publisher.publish(businessIdentifer.appId(), businessIdentifer.busCode(), getMessageId(content, parentTrxId), msg,logCtx); //writeLog MessageSentContent messageSentContent = new MessageSentContent(); messageSentContent.setLeftDemiConentId(leftContent.getcId()); messageSentContent.setRemoteMessageId(send.getMessageId()); logCtx.getLogCache().cacheLog(messageSentContent); LOG.info("Reliable message sent:" + businessIdentifer); return true; }else{ //rollback //do nothing return true; } } private String getMessageId(MessageRecordContent content, TransactionId parentTrxId) { return parentTrxId.getAppId()+"|"+parentTrxId.getBusCode()+"|"+parentTrxId.getTrxId()+"|"+content.getcId(); } }