package com.fdkankan.ucenter.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fdkankan.common.exception.BusinessException;
import com.fdkankan.common.util.RandomUtil;
import com.fdkankan.redis.util.RedisUtil;
import com.fdkankan.ucenter.common.CameraTypeEnum;
import com.fdkankan.ucenter.common.RedisKeyUtil;
import com.fdkankan.ucenter.entity.Scene3dNum;
import com.fdkankan.ucenter.mapper.IScene3dNumMapper;
import com.fdkankan.ucenter.service.IScene3dNumService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import java.util.*;
import java.util.stream.Collectors;
/**
*
* 场景编码表 服务实现类
*
*
* @author
* @since 2022-07-12
*/
@Service
@Slf4j
public class Scene3dNumServiceImpl extends ServiceImpl implements IScene3dNumService {
@Autowired
RedisUtil redisUtil;
@Override
public String generateSceneNum(Integer cameraType) {
String sceneNum = redisUtil.lLeftPop(RedisKeyUtil.SCENE_UNUSED_NUMS);
if(!StringUtils.isEmpty(sceneNum)){
return addPrefix(sceneNum,cameraType);
}
long incr = redisUtil.incr(RedisKeyUtil.SCENE_NUMS_LOADING, 1);
if(incr == 1){
try {
log.info("开始从数据库加载场景码");
List numList = this.getSceneNum();
redisUtil.lRightPushAll(RedisKeyUtil.SCENE_UNUSED_NUMS,numList);
log.info("场景码加载完成");
}catch ( Exception e){
e.printStackTrace();
}finally {
redisUtil.del(RedisKeyUtil.SCENE_NUMS_LOADING);
}
}else {
// 等待1秒加载缓存
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
String num = redisUtil.lLeftPop(RedisKeyUtil.SCENE_UNUSED_NUMS);
if(ObjectUtils.isEmpty(num)){
log.error("场景码加载失败");
throw new BusinessException(-1,"场景码生成失败,请重试");
}
return addPrefix(num,cameraType);
}
private static String addPrefix( String num,Integer cameraType){
if(cameraType == null){
return num;
}
return CameraTypeEnum.getSceneNumPrefixByType(cameraType) + num;
}
private List getSceneNum() {
LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>();
wrapper.eq(Scene3dNum::getUsed,0);
long count = this.count(wrapper);
List numList ;
if(count < 10){
log.info("场景码数量不足生成场景码");
numList = this.createNum(10);
}else {
wrapper.last("limit 100");
numList = this.list(wrapper);
for (Scene3dNum scene3dNum : numList) {
scene3dNum.setUsed(1);
}
this.updateBatchById(numList);
}
return numList.parallelStream().map(Scene3dNum::getCode).collect(Collectors.toList());
}
private List createNum(Integer size) {
//uuid 作为生成批次
List scene3dNums = new ArrayList<>();
String uuid = UUID.randomUUID().toString().replace("-", "");
HashSet codeList = this.createCode(size);
while (codeList.size() < size){
codeList.addAll(this.createCode(size - codeList.size()));
}
for (String code : codeList) {
Scene3dNum scene3dNum = new Scene3dNum();
scene3dNum.setUsed(1);
scene3dNum.setCode(code);
scene3dNum.setFolderName(uuid);
scene3dNum.setCreateTime(new Date());
scene3dNum.setUpdateTime(new Date());
scene3dNums.add(scene3dNum);
}
this.saveBatch(scene3dNums);
return scene3dNums;
}
private HashSet createCode(Integer size) {
HashSet codeList = new HashSet<>();
while (codeList.size() < size){
String code = RandomUtil.generateShortUuid().substring(0,8);
codeList.add(code);
}
LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>();
wrapper.in(Scene3dNum::getCode,codeList);
List list = this.list(wrapper);
if(list.size() <=0){
return codeList;
}
for (Scene3dNum scene3dNum : list) {
codeList.remove(scene3dNum.getCode());
}
return codeList;
}
}