package com.zcxk.core.utils;

import com.zcxk.core.common.enums.RespCodeEnum;
import com.zcxk.core.common.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.function.Supplier;

/**
 * 缓存锁模板
 */
/**
 * @author Andy
 * @date 2021-07-22 11:03
 */
@Component
@Slf4j
public class DistributedLockTemplateService {

    private final DistributedLock distributedLock;

    DistributedLockTemplateService(DistributedLock distributedLock) {
        this.distributedLock = distributedLock;
    }

    /**
     * 获取锁
     *
     * @param key        加锁key
     * @param keepMills  超时时间
     * @param retry      重试次数
     * @param sleepMills 重试等待间隔
     * @param supplier   加锁执行方法 lambda 函数接口
     * @return T
     * @author Richard
     **/
    public <T> T lock(String key, Long keepMills, Integer retry, Long sleepMills,
                      Supplier<T> supplier) {
        try {
            boolean lock = distributedLock.lock(key, keepMills, retry, sleepMills);
            if (!lock) {
                log.warn("获取锁失败,key:{}", key);
                throw BusinessException.builder(RespCodeEnum.GLOBAL_GET_DISTRIBUTED_LOCK_ERROR);
            }
            return supplier.get();
        } catch (Exception e) {
            if (e instanceof BusinessException) {
                throw e;
            } else {
                log.error("获取锁异常", e);
                throw BusinessException.builder(RespCodeEnum.ERROR_500.getStatus(), e.getMessage());
            }
        } finally {
            boolean releaseResult = distributedLock.releaseLock(key);
            if (log.isDebugEnabled()) {
                log.debug("release lock : " + key + (releaseResult ? " success" : " failed"));
            }
        }
    }
}
