package com.hmsoft.common.util;

import java.util.Collections;
import java.util.Set;

import org.springframework.retry.RecoveryCallback;
import org.springframework.retry.RetryCallback;
import org.springframework.retry.RetryContext;
import org.springframework.retry.backoff.FixedBackOffPolicy;
import org.springframework.retry.policy.SimpleRetryPolicy;
import org.springframework.retry.support.RetryTemplate;

import com.hmsoft.common.bizinf.IExecuteLogic;

/**
 * 
 * @author zq
 *
 */
public class ExecuteRetryUtil {

	/**
	 * 重试执行
	 * @param retrys
	 * @param period
	 * @param logic
	 */
	public static Object execute(int retrys, int period, IExecuteLogic logic, Set<String> failSet) {
    	final RetryTemplate retryTemplate = new RetryTemplate();
    	SimpleRetryPolicy policy = new SimpleRetryPolicy(retrys, Collections.<Class<? extends Throwable>, Boolean> singletonMap(Exception.class, true));
    	FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy();
    	fixedBackOffPolicy.setBackOffPeriod(period);
        retryTemplate.setRetryPolicy(policy);
        retryTemplate.setBackOffPolicy(fixedBackOffPolicy);
        //重试业务操作
        final RetryCallback<Object, Exception> retryCallback = new RetryCallback<Object, Exception>() {

			@Override
			public Object doWithRetry(RetryContext context) throws Exception {
				if (context.getRetryCount() > 0) {
					System.err.println("第"+ context.getRetryCount() +"次尝试调用......!");
				}
				//业务逻辑
				Object result = logic.execute();
				if (context.getRetryCount() > 0) {
					System.err.println("重试"+ context.getRetryCount() +"次后执行成功!");
				}
				failSet.clear();
				return result;
			}
        	
        };
        //执行指定次数后任然失败的回调
        final RecoveryCallback<Object> recoveryCallback = new RecoveryCallback<Object>() {

			@Override
			public Object recover(RetryContext context) throws Exception {
				System.err.println("执行指定次重试后还是报错，回调.");
				return null;
			}
        	
        };
        try {
        	retryTemplate.execute(retryCallback, recoveryCallback);
        } catch(Exception e) {
        	e.printStackTrace();
        }
        return null;
	}
}
