package com.fdkankan.scene.service.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; import cn.hutool.core.io.FileUtil; import cn.hutool.core.lang.UUID; import cn.hutool.core.util.RandomUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.fdkankan.common.constant.CommonStatus; import com.fdkankan.common.util.FileUtils; import com.fdkankan.model.utils.CreateObjUtil; import com.fdkankan.redis.constant.RedisKey; import com.fdkankan.redis.constant.RedisLockKey; import com.fdkankan.redis.util.RedisLockUtil; import com.fdkankan.redis.util.RedisUtil; import com.fdkankan.scene.bean.SceneBean; import com.fdkankan.scene.entity.SceneClean; import com.fdkankan.scene.mapper.ISceneCleanMapper; import com.fdkankan.scene.service.ISceneCleanService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import java.util.Calendar; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; /** *

* 服务实现类 *

* * @author * @since 2022-10-09 */ @RefreshScope @Service public class SceneCleanServiceImpl extends ServiceImpl implements ISceneCleanService { @Autowired private RedisLockUtil redisLockUtil; @Autowired private RedisUtil redisUtil; @Value("${scene.clean.size:10}") private Integer sceneCleanSize; @Transactional @Override public void sceneCleanResource(){ //这里考虑到日后会集群部署,所以查询需要清理资源的场景的写法是负载均衡写法,为了避免幻读影响到查询结果,所以写库放在循环外层 List allInsertList = Lists.newArrayList(); Set allUpdateSet = Sets.newHashSet(); DateTime dateTime = DateUtil.beginOfDay(DateUtil.offsetMonth(Calendar.getInstance().getTime(), -6)); while (true){ String uuid = UUID.randomUUID().toString(); boolean lock = redisLockUtil.lock(RedisLockKey.LOCK_SCENE_CLEAN, uuid, RedisKey.EXPIRE_TIME_1_MINUTE); if(!lock){ try { Thread.sleep(RandomUtil.randomLong(1000L, 2000L)); continue; } catch (InterruptedException e) { e.printStackTrace(); } } long index = 0; String indexStr = redisUtil.get(RedisKey.SCENE_CLEAN_INDEX); if(StringUtils.isNotBlank(indexStr)){ index = Long.valueOf(indexStr); } //下标增加1000 redisUtil.incr(RedisKey.SCENE_CLEAN_INDEX, sceneCleanSize); //解锁 redisLockUtil.unlockLua(RedisLockKey.LOCK_SCENE_CLEAN, uuid); //查询需要清理资源的场景 List sceneBeanList = this.selectNeadCleanScene(index, sceneCleanSize, dateTime); //如果查出来的场景集合是空,证明已经没有场景资源需要删除,则需要把查询下表删除,等待下一次定时任务执行 if(CollectionUtils.isEmpty(sceneBeanList)){ redisUtil.del(RedisKey.SCENE_CLEAN_INDEX); break; } List insertList = Lists.newArrayList(); List numList = sceneBeanList.stream().map(scene -> scene.getNum()).collect(Collectors.toList()); List updateList = this.list(new LambdaQueryWrapper().in(SceneClean::getNum, numList)); Set updateSet = new HashSet<>(); if(!CollectionUtils.isEmpty(updateList)){ updateList.stream().forEach(item->{ updateSet.add(item.getNum()); }); } sceneBeanList.stream().forEach(scene -> { if(StringUtils.isNotBlank(scene.getDataSource())){ try { CreateObjUtil.deleteFile(scene.getDataSource()); } catch (Exception e) { e.printStackTrace(); } } if(!updateSet.contains(scene.getNum())){ SceneClean sceneClean = new SceneClean(); sceneClean.setNum(scene.getNum()); insertList.add(sceneClean); } }); if(!CollectionUtils.isEmpty(insertList)){ allInsertList.addAll(insertList); } if(!CollectionUtils.isEmpty(updateSet)){ allUpdateSet.addAll(updateSet); } } //写库 if(CollUtil.isNotEmpty(allInsertList)){ this.saveBatch(allInsertList); } if(CollUtil.isNotEmpty(allUpdateSet)){ this.update(new LambdaUpdateWrapper().set(SceneClean::getState, CommonStatus.YES.code()).in(SceneClean::getNum, allUpdateSet)); } } @Override public List selectNeadCleanScene(long index, int size, Date time) { return this.baseMapper.selectNeadCleanScene(index, size, time); } }