package com.yiqiniu.easytrans.executor; import java.io.Serializable; import java.util.concurrent.Callable; import java.util.concurrent.Future; 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.config.EasyTransConifg; 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.tcc.PreTccCallContent; import com.yiqiniu.easytrans.log.vo.tcc.TccCallCancelledContent; import com.yiqiniu.easytrans.log.vo.tcc.TccCallConfirmedContent; import com.yiqiniu.easytrans.protocol.BusinessIdentifer; import com.yiqiniu.easytrans.protocol.EasyTransRequest; import com.yiqiniu.easytrans.protocol.tcc.TccMethod; import com.yiqiniu.easytrans.util.ReflectUtil; @RelativeInterface(TccMethod.class) public class TccMethodExecutor implements EasyTransExecutor,LogProcessor,DemiLogEventHandler { @Resource private EasyTransSynchronizer transSynchronizer; @Resource private RemoteServiceCaller rpcClient; @Resource private EasyTransConifg config; private Logger LOG = LoggerFactory.getLogger(this.getClass()); private static final String TRY_METHOD_NAME = "doTry"; private static final String CONFIRM_METHOD_NAME = "doConfirm"; private static final String CANCEL_METHOD_NAME = "doCancel"; @Override public <P extends EasyTransRequest<R,E>,E extends EasyTransExecutor,R extends Serializable> Future<R> execute(final P params) { final LogProcessContext logProcessContext = transSynchronizer.getLogProcessContext(); Callable<R> callable = new Callable<R>() { @Override public R call() throws Exception { BusinessIdentifer businessIdentifer = ReflectUtil.getBusinessIdentifer(params.getClass()); return (R) rpcClient.call(businessIdentifer.appId(), businessIdentifer.busCode(), TRY_METHOD_NAME, params,logProcessContext); } }; PreTccCallContent content = new PreTccCallContent(); content.setParams(params); return transSynchronizer.executeMethod(callable, content); } @Override public boolean logProcess(LogProcessContext ctx, Content currentContent) { if(currentContent instanceof PreTccCallContent){ PreTccCallContent preCallContent = (PreTccCallContent) currentContent; //register DemiLogEvent ctx.getDemiLogManager().registerSemiLogEventListener(preCallContent, 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) { PreTccCallContent preCallContent = (PreTccCallContent) leftContent; EasyTransRequest<?,?> params = preCallContent.getParams(); BusinessIdentifer businessIdentifer = ReflectUtil.getBusinessIdentifer(params.getClass()); if(logCtx.getFinalMasterTransStatus() == null){ LOG.info("final trans status unknown,process later." + logCtx.getLogCollection()); return false;//unknown,process later }else if(logCtx.getFinalMasterTransStatus()){ //commit //execute confirm and then write Log rpcClient.callWithNoReturn(businessIdentifer.appId(), businessIdentifer.busCode(), CONFIRM_METHOD_NAME, preCallContent.getParams(),logCtx); TccCallConfirmedContent tccCallConfirmedContent = new TccCallConfirmedContent(); tccCallConfirmedContent.setLeftDemiConentId(leftContent.getcId()); logCtx.getLogCache().cacheLog(tccCallConfirmedContent); return true; }else{ //roll back //execute cancel and then write Log rpcClient.callWithNoReturn(businessIdentifer.appId(), businessIdentifer.busCode(), CANCEL_METHOD_NAME, preCallContent.getParams(),logCtx); TccCallCancelledContent tccCallCanceledContent = new TccCallCancelledContent(); tccCallCanceledContent.setLeftDemiConentId(leftContent.getcId()); return true; } } }