package com.brilliance.isc.counter.service.impl;

import com.brilliance.isc.counter.mapper.SerialCounterMapper;
import com.brilliance.isc.counter.model.SerialBo;
import com.brilliance.isc.counter.service.SerialCounterService;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Objects;

@Component
public class SerialCounterServiceImpl implements SerialCounterService {
    @Resource
    SerialCounterMapper serialCounterMapper;

    /**
     * 基于DB获取连续计数器，CAS次数20次，如果还不成功，则
     *
     * @return 返回下个计数；如果取号失败返回-1
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public long genSerialNumberByDb(String tblNam, String couNam, Date couDat) {
        SerialBo serialBo = serialCounterMapper.select(tblNam, couNam, couDat);
        if (Objects.isNull(serialBo)) {
            //尝试插入
            try {
                Integer insert = serialCounterMapper.insert(tblNam, couNam, couDat);
                if (insert > 0) {
                    return 1L;
                }
            } catch (Exception e) {
                //插入失败，静默处理
                serialBo = serialCounterMapper.select(tblNam, couNam, couDat);
            }
        }
        //CAS（CopmpareAndSet）操作
        int num = 0;
        while (num < 20) {
            long nval = serialBo.getCouval() + serialBo.getCoustp() + num;
            long oval = serialBo.getCouval() + num;
            int update = serialCounterMapper.update(tblNam, nval, oval, couNam, couDat);
            if (update > 0) {
                return nval;
            }
            num++;
        }
        return -1l;
    }
}
