package cn.axzo.workflow.starter.handler.execute.interceptor;

import cn.axzo.workflow.starter.handler.execute.ListenerExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.function.Consumer;

/**
 * 当前listener执行出错，忽略继续往下执行，可配置重试相关参数，不抛出异常
 */
public final class FailOverInterceptor extends AbstractListenerInterceptor {

    private static final Logger LOGGER = LoggerFactory.getLogger(FailOverInterceptor.class);

    private int numOfRetries = 3;
    private int waitTimeInMs = 50;
    private int waitIncreaseFactor = 5;

    public FailOverInterceptor() {
    }

    public FailOverInterceptor(int numOfRetries, int waitTimeInMs, int waitIncreaseFactor) {
        this.numOfRetries = numOfRetries;
        this.waitTimeInMs = waitTimeInMs;
        this.waitIncreaseFactor = waitIncreaseFactor;
    }

    @Override
    public <T> void execute(ListenerExecutor executor, Consumer<T> consumer, T t) {
        long waitTime = waitTimeInMs;
        int failedAttempts = 0;
        do {
            if (failedAttempts > 0) {
                LOGGER.info("Waiting for {}ms before retrying the command.", waitTime);
                waitBeforeRetry(waitTime);
                waitTime *= waitIncreaseFactor;
            }
            try {
                getNext().execute(executor, consumer, t);
                return;
            } catch (Exception e) {
                LOGGER.info("Caught exception: {}", e.getMessage(), e);
            }
            failedAttempts++;
        } while (failedAttempts <= numOfRetries);
//        throw new ServiceException(numOfRetries + " retries failed with Exception. Giving up.");
    }

    private void waitBeforeRetry(long waitTime) {
        try {
            Thread.sleep(waitTime);
        } catch (InterruptedException e) {
            LOGGER.debug(" interrupted while waiting for a retry.");
        }
    }
}
