zoukankan      html  css  js  c++  java
  • TCC细读

    重试定时任务,通过外部调度实现

    package org.mengyun.tcctransaction.spring.recover;
    
    import org.mengyun.tcctransaction.SystemException;
    import org.mengyun.tcctransaction.recover.TransactionRecovery;
    import org.mengyun.tcctransaction.support.TransactionConfigurator;
    import org.quartz.Scheduler;
    import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
    import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;
    
    /**
     * Created by changming.xie on 6/2/16.
     */
    public class RecoverScheduledJob {
    
        private TransactionRecovery transactionRecovery;
    
        private TransactionConfigurator transactionConfigurator;
    
        private Scheduler scheduler;
    
        public void init() {
            try {
                MethodInvokingJobDetailFactoryBean jobDetail = new MethodInvokingJobDetailFactoryBean();
                jobDetail.setTargetObject(transactionRecovery);
                jobDetail.setTargetMethod("startRecover");
                jobDetail.setName("transactionRecoveryJob");
                jobDetail.setConcurrent(false);
                jobDetail.afterPropertiesSet();
    
                CronTriggerFactoryBean cronTrigger = new CronTriggerFactoryBean();
                cronTrigger.setBeanName("transactionRecoveryCronTrigger");
                cronTrigger.setCronExpression(transactionConfigurator.getRecoverConfig().getCronExpression());
                cronTrigger.setJobDetail(jobDetail.getObject());
                cronTrigger.afterPropertiesSet();
                scheduler.scheduleJob(jobDetail.getObject(), cronTrigger.getObject());
                scheduler.start();
            } catch (Exception e) {
                throw new SystemException(e);
            }
        }
    
        public void setTransactionRecovery(TransactionRecovery transactionRecovery) {
            this.transactionRecovery = transactionRecovery;
        }
    
        public Scheduler getScheduler() {
            return scheduler;
        }
    
        public void setScheduler(Scheduler scheduler) {
            this.scheduler = scheduler;
        }
    
        public void setTransactionConfigurator(TransactionConfigurator transactionConfigurator) {
            this.transactionConfigurator = transactionConfigurator;
        }
    }

    执行TransactionRecovery的startRecover方法,查找事物存储中,超过某一段设置时间一直没有修改的事物,执行恢复操作,更新或删除对应的状态和数据

    package org.mengyun.tcctransaction.recover;
    
    import com.alibaba.fastjson.JSON;
    import org.apache.commons.lang3.exception.ExceptionUtils;
    import org.apache.log4j.Logger;
    import org.mengyun.tcctransaction.OptimisticLockException;
    import org.mengyun.tcctransaction.Transaction;
    import org.mengyun.tcctransaction.TransactionRepository;
    import org.mengyun.tcctransaction.api.TransactionStatus;
    import org.mengyun.tcctransaction.common.TransactionType;
    import org.mengyun.tcctransaction.support.TransactionConfigurator;
    
    import java.util.Calendar;
    import java.util.Date;
    import java.util.List;
    
    /**
     * Created by changmingxie on 11/10/15.
     */
    public class TransactionRecovery {
    
        static final Logger logger = Logger.getLogger(TransactionRecovery.class.getSimpleName());
        private TransactionConfigurator transactionConfigurator;
    
        public void startRecover() {
            List<Transaction> transactions = loadErrorTransactions();
            recoverErrorTransactions(transactions);
        }
    
        private List<Transaction> loadErrorTransactions() {
            long currentTimeInMillis = Calendar.getInstance().getTimeInMillis();
            TransactionRepository transactionRepository = transactionConfigurator.getTransactionRepository();
            RecoverConfig recoverConfig = transactionConfigurator.getRecoverConfig();
            return transactionRepository.findAllUnmodifiedSince(new Date(currentTimeInMillis - recoverConfig.getRecoverDuration() * 1000));
        }
    
        private void recoverErrorTransactions(List<Transaction> transactions) {
            for (Transaction transaction : transactions) {
                if (transaction.getRetriedCount() > transactionConfigurator.getRecoverConfig().getMaxRetryCount()) {
                    logger.error(String.format("recover failed with max retry count,will not try again. txid:%s, status:%s,retried count:%d,transaction content:%s", transaction.getXid(), transaction.getStatus().getId(), transaction.getRetriedCount(), JSON.toJSONString(transaction)));
                    continue;
                }
    
                if (transaction.getTransactionType().equals(TransactionType.BRANCH)
                        && (transaction.getCreateTime().getTime() +
                        transactionConfigurator.getRecoverConfig().getMaxRetryCount() *
                                transactionConfigurator.getRecoverConfig().getRecoverDuration() * 1000
                        > System.currentTimeMillis())) {
                    continue;
                }
                
                try {
                    transaction.addRetriedCount();
                    if (transaction.getStatus().equals(TransactionStatus.CONFIRMING)) {
                        transaction.changeStatus(TransactionStatus.CONFIRMING);
                        transactionConfigurator.getTransactionRepository().update(transaction);
                        transaction.commit();
                        transactionConfigurator.getTransactionRepository().delete(transaction);
                    } else if (transaction.getStatus().equals(TransactionStatus.CANCELLING)
                            || transaction.getTransactionType().equals(TransactionType.ROOT)) {
                        transaction.changeStatus(TransactionStatus.CANCELLING);
                        transactionConfigurator.getTransactionRepository().update(transaction);
                        transaction.rollback();
                        transactionConfigurator.getTransactionRepository().delete(transaction);
                    }
                } catch (Throwable throwable) {
                    if (throwable instanceof OptimisticLockException
                            || ExceptionUtils.getRootCause(throwable) instanceof OptimisticLockException) {
                        logger.warn(String.format("optimisticLockException happened while recover. txid:%s, status:%s,retried count:%d,transaction content:%s", transaction.getXid(), transaction.getStatus().getId(), transaction.getRetriedCount(), JSON.toJSONString(transaction)), throwable);
                    } else {
                        logger.error(String.format("recover failed, txid:%s, status:%s,retried count:%d,transaction content:%s", transaction.getXid(), transaction.getStatus().getId(), transaction.getRetriedCount(), JSON.toJSONString(transaction)), throwable);
                    }
                }
            }
        }
    
        public void setTransactionConfigurator(TransactionConfigurator transactionConfigurator) {
            this.transactionConfigurator = transactionConfigurator;
        }
    }
  • 相关阅读:
    C语言实现两栈空间共享
    MyEclipse里项目部署到tomcat上之后,tomcat webpps文件夹里为什么找不到这个项目
    CSS选择器
    用友2016成都校园招聘笔试题
    windows、ubuntu下eclipse搭建java、Python环境问题总结
    ubuntu上用eclipse搭建java、python开发环境
    windows 下用eclipse搭建java、python开发环境
    简单事件机制的研究
    软件测试(软件安装:php+mysql+apache+mantis过程遇到的问题以及解决方法)
    4、总结一下,以软件开发生命周期来说明测试的使用情况。
  • 原文地址:https://www.cnblogs.com/it-worker365/p/10072202.html
Copyright © 2011-2022 走看看