From 6c330764ea3bd3bdd2df9aa280b1222bf416f8e3 Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Thu, 5 Feb 2026 00:58:14 +0800 Subject: [PATCH 1/3] =?UTF-8?q?refactor(statistics):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E5=BA=94=E7=94=A8=E7=BB=9F=E8=AE=A1=E6=BC=8F=E6=96=97=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E7=9A=84Redis=E7=BC=93=E5=AD=98=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除固定的Redis缓存key,改为包含日期维度的动态key - 修复日期范围检查逻辑中的时间顺序问题 - 统一多处相同的日期范围条件判断代码 - 移除实时模式下的数据持久化操作以避免缓存污染 --- .../mobile/impl/AppStatisticsServiceImpl.java | 19 +++++++------------ .../com/ycwl/basic/task/ScenicStatsTask.java | 11 +++++++---- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/ycwl/basic/service/mobile/impl/AppStatisticsServiceImpl.java b/src/main/java/com/ycwl/basic/service/mobile/impl/AppStatisticsServiceImpl.java index b2390fab..a4ae4a8d 100644 --- a/src/main/java/com/ycwl/basic/service/mobile/impl/AppStatisticsServiceImpl.java +++ b/src/main/java/com/ycwl/basic/service/mobile/impl/AppStatisticsServiceImpl.java @@ -145,7 +145,6 @@ public class AppStatisticsServiceImpl implements AppStatisticsService { @Override public ApiResponse userConversionFunnel(CommonQueryReq query) { - String redisKey = "statistics:tmp_cache:"+query.getScenicId(); AppStatisticsFunnelVO vo = new AppStatisticsFunnelVO(); if(query.getEndTime()==null && query.getStartTime()==null){ // 没有传时间,则代表用户没有自定义查询时间,使用standard来判断查询时间范围 @@ -156,8 +155,12 @@ public class AppStatisticsServiceImpl implements AppStatisticsService { //获取当前周期的具体时间范围 standardToNewSpecificTime(query); } + // 构建包含日期维度的 Redis 缓存 key + String redisKey = String.format("statistics:tmp_cache:%s:%s", + query.getScenicId(), + query.getStartTime() != null ? DateUtil.formatDate(query.getStartTime()) : "null"); if (!query.isRealtime()) { - if (!(DateUtil.isIn(query.getStartTime(), DateUtil.tomorrow(), DateUtil.yesterday()) && DateUtil.isIn(query.getEndTime(), DateUtil.tomorrow(), DateUtil.yesterday()))) { + if (!(DateUtil.isIn(query.getStartTime(), DateUtil.yesterday(), DateUtil.tomorrow()) && DateUtil.isIn(query.getEndTime(), DateUtil.yesterday(), DateUtil.tomorrow()))) { // 查询缓存数据 List list = statisticsMapper.listStatByScenic(query.getScenicId(), query.getStartTime(), query.getEndTime()); AppStatisticsFunnelVO resp = new AppStatisticsFunnelVO(); @@ -189,7 +192,7 @@ public class AppStatisticsServiceImpl implements AppStatisticsService { } } if (!query.isRealtime()) { - if (DateUtil.isIn(query.getStartTime(), DateUtil.tomorrow(), DateUtil.yesterday()) && DateUtil.isIn(query.getEndTime(), DateUtil.tomorrow(), DateUtil.yesterday())) { + if (DateUtil.isIn(query.getStartTime(), DateUtil.yesterday(), DateUtil.tomorrow()) && DateUtil.isIn(query.getEndTime(), DateUtil.yesterday(), DateUtil.tomorrow())) { // 缓存 if (redisTemplate.hasKey(redisKey)) { String s = redisTemplate.opsForValue().get(redisKey); @@ -203,7 +206,7 @@ public class AppStatisticsServiceImpl implements AppStatisticsService { try { // 缓存 if (!query.isRealtime()) { - if (DateUtil.isIn(query.getStartTime(), DateUtil.tomorrow(), DateUtil.yesterday()) && DateUtil.isIn(query.getEndTime(), DateUtil.tomorrow(), DateUtil.yesterday())) { + if (DateUtil.isIn(query.getStartTime(), DateUtil.yesterday(), DateUtil.tomorrow()) && DateUtil.isIn(query.getEndTime(), DateUtil.yesterday(), DateUtil.tomorrow())) { // 缓存 if (redisTemplate.hasKey(redisKey)) { String s = redisTemplate.opsForValue().get(redisKey); @@ -270,14 +273,6 @@ public class AppStatisticsServiceImpl implements AppStatisticsService { vo.setPayOfOrderAmount(payOfOrderAmount.setScale(2, RoundingMode.HALF_UP)); vo.setRefundOfOrderNum(refundOfOrderNum); vo.setRefundOfOrderAmount(refundOfOrderAmount.setScale(2, RoundingMode.HALF_UP)); - // 仅在非 realtime 模式下写入缓存 - // realtime=true 时由调用方(如定时任务)自行控制写入目标日期,不污染当天缓存 - if (!query.isRealtime()) { - if (query.getScenicId() != null) { - statisticsMapper.insertStat(query.getScenicId(), new Date(), vo); - } - redisTemplate.opsForValue().set(redisKey, JacksonUtil.toJSONString(vo), 60, TimeUnit.SECONDS); - } return ApiResponse.success(vo); } finally { lock.unlock(); diff --git a/src/main/java/com/ycwl/basic/task/ScenicStatsTask.java b/src/main/java/com/ycwl/basic/task/ScenicStatsTask.java index c20584f9..88db088c 100644 --- a/src/main/java/com/ycwl/basic/task/ScenicStatsTask.java +++ b/src/main/java/com/ycwl/basic/task/ScenicStatsTask.java @@ -93,8 +93,8 @@ public class ScenicStatsTask { // 写入数据库(REPLACE INTO 会自动更新已存在的记录) statisticsMapper.insertStat(scenicId, startTime, data); - // 删除该景区的缓存,确保下次查询时获取最新数据 - invalidateStatisticsCache(scenicId); + // 删除该景区该日期的缓存,确保下次查询时获取最新数据 + invalidateStatisticsCache(scenicId, startTime); } catch (Exception e) { log.error("统计景区 {} 在日期 {} 的数据时发生错误", scenic.getId(), DateUtil.formatDate(startTime), e); } @@ -109,9 +109,12 @@ public class ScenicStatsTask { /** * 删除景区统计缓存 * @param scenicId 景区ID + * @param date 统计日期 */ - private void invalidateStatisticsCache(Long scenicId) { - String redisKey = "statistics:tmp_cache:" + scenicId; + private void invalidateStatisticsCache(Long scenicId, Date date) { + String redisKey = String.format("statistics:tmp_cache:%s:%s", + scenicId, + DateUtil.formatDate(date)); redisTemplate.delete(redisKey); } } From a85d6b0ead7ff4227312549db31bcc81e2b16449 Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Thu, 5 Feb 2026 01:05:56 +0800 Subject: [PATCH 2/3] =?UTF-8?q?feat(statistics):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=BD=93=E6=97=A5=E6=95=B0=E6=8D=AERedis=E7=BC=93=E5=AD=98?= =?UTF-8?q?=E5=B9=B6=E8=B0=83=E6=95=B4=E5=AE=9A=E6=97=B6=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在AppStatisticsServiceImpl中实现当日数据的Redis缓存机制 - 仅对实时查询且查询日期为当天的数据进行缓存 - 设置缓存时间为60秒以减少实时查询压力 - 将历史数据查询与实时数据查询分离 - 调整ScenicStatsTask定时任务执行时间 - 添加每日凌晨3点执行的任务配置 - 新增每天0点1分执行的统计任务调度 --- .../service/mobile/impl/AppStatisticsServiceImpl.java | 9 +++++++++ src/main/java/com/ycwl/basic/task/ScenicStatsTask.java | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/ycwl/basic/service/mobile/impl/AppStatisticsServiceImpl.java b/src/main/java/com/ycwl/basic/service/mobile/impl/AppStatisticsServiceImpl.java index a4ae4a8d..199b4707 100644 --- a/src/main/java/com/ycwl/basic/service/mobile/impl/AppStatisticsServiceImpl.java +++ b/src/main/java/com/ycwl/basic/service/mobile/impl/AppStatisticsServiceImpl.java @@ -273,6 +273,15 @@ public class AppStatisticsServiceImpl implements AppStatisticsService { vo.setPayOfOrderAmount(payOfOrderAmount.setScale(2, RoundingMode.HALF_UP)); vo.setRefundOfOrderNum(refundOfOrderNum); vo.setRefundOfOrderAmount(refundOfOrderAmount.setScale(2, RoundingMode.HALF_UP)); + + // 仅对当天数据启用 Redis 缓存(短期缓存,减少实时查询压力) + // 历史数据已在 scenic_stats 表中持久化,不需要 Redis 缓存 + if (!query.isRealtime() && query.getStartTime() != null) { + // 判断查询日期是否为今天 + if (DateUtil.isSameDay(query.getStartTime(), new Date())) { + redisTemplate.opsForValue().set(redisKey, JacksonUtil.toJSONString(vo), 60, TimeUnit.SECONDS); + } + } return ApiResponse.success(vo); } finally { lock.unlock(); diff --git a/src/main/java/com/ycwl/basic/task/ScenicStatsTask.java b/src/main/java/com/ycwl/basic/task/ScenicStatsTask.java index 88db088c..ba34d63a 100644 --- a/src/main/java/com/ycwl/basic/task/ScenicStatsTask.java +++ b/src/main/java/com/ycwl/basic/task/ScenicStatsTask.java @@ -60,7 +60,8 @@ public class ScenicStatsTask { }); } } - @Scheduled(cron = "0 0 2 * * *") + @Scheduled(cron = "0 0 3 * * *") + @Scheduled(cron = "0 1 0 * * *") public void countScenicStats() { log.info("开始执行景区统计任务,统计前7天至昨天的数据"); From 95c82cfcf26d3840edef9b21de50a73180b2bee4 Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Thu, 5 Feb 2026 14:16:16 +0800 Subject: [PATCH 3/3] =?UTF-8?q?refactor(storage):=20=E7=AE=80=E5=8C=96?= =?UTF-8?q?=E5=AD=98=E5=82=A8=E9=80=82=E9=85=8D=E5=99=A8=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E9=80=BB=E8=BE=91=E5=B9=B6=E7=A7=BB=E9=99=A4=E9=99=8D=E7=BA=A7?= =?UTF-8?q?=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除默认存储配置常量 DEFAULT_STORAGE - 简化 UploadStage 中的存储适配器获取逻辑,直接使用 StorageFactory.use() - 移除降级到默认存储的处理机制 - 在 PuzzleGenerateServiceImpl 中复用存储适配器实例 - 移除 SourceRepository 中的 StorageUnsupportedException 导入 - 移除 GoodsServiceImpl 中的 StorageType 枚举导入 - 移除 SourceServiceImpl 中的 ScenicService 依赖注入 - 移除 PrinterServiceImpl 中的复杂存储适配器配置逻辑 - 在 TaskTaskServiceImpl 中统一使用景点存储适配器 - 在 FaceCleaner 中添加新的存储清理逻辑,使用独立的图片存储适配器 - 添加 sourceImageUrlMap 和 sourceScenicIdMap 来优化文件清理逻辑 --- .../image/pipeline/stages/UploadStage.java | 40 ++---------- .../impl/PuzzleGenerateServiceImpl.java | 10 +-- .../basic/repository/SourceRepository.java | 10 +-- .../service/mobile/impl/GoodsServiceImpl.java | 9 +-- .../service/pc/impl/SourceServiceImpl.java | 5 +- .../printer/impl/PrinterServiceImpl.java | 20 +----- .../task/impl/TaskTaskServiceImpl.java | 9 +-- .../java/com/ycwl/basic/task/FaceCleaner.java | 65 ++++++++++++++----- 8 files changed, 66 insertions(+), 102 deletions(-) diff --git a/src/main/java/com/ycwl/basic/image/pipeline/stages/UploadStage.java b/src/main/java/com/ycwl/basic/image/pipeline/stages/UploadStage.java index ffc5d5f5..9e573687 100644 --- a/src/main/java/com/ycwl/basic/image/pipeline/stages/UploadStage.java +++ b/src/main/java/com/ycwl/basic/image/pipeline/stages/UploadStage.java @@ -25,8 +25,6 @@ import java.io.File; ) public class UploadStage extends AbstractPipelineStage { - private static final String DEFAULT_STORAGE = "assets-ext"; - @Override public String getName() { return "UploadStage"; @@ -39,17 +37,11 @@ public class UploadStage extends AbstractPipelineStage { return StageResult.failed("没有可上传的文件"); } - IStorageAdapter adapter = context.getStorageAdapter(); - boolean usingDefaultStorage = false; - - if (adapter == null) { - log.debug("未配置存储适配器,使用默认存储: {}", DEFAULT_STORAGE); - try { - adapter = StorageFactory.use(DEFAULT_STORAGE); - usingDefaultStorage = true; - } catch (Exception e) { - return StageResult.failed("无法获取默认存储: " + e.getMessage(), e); - } + IStorageAdapter adapter; + try { + adapter = StorageFactory.use(); + } catch (Exception e) { + return StageResult.failed("无法获取存储: " + e.getMessage(), e); } try { @@ -57,32 +49,10 @@ public class UploadStage extends AbstractPipelineStage { context.setResultUrl(uploadedUrl); log.info("文件上传成功: {}", uploadedUrl); - - if (usingDefaultStorage) { - return StageResult.degraded("降级: 使用默认存储 " + DEFAULT_STORAGE); - } - return StageResult.success("已上传"); } catch (Exception e) { log.error("文件上传失败", e); - - if (!usingDefaultStorage) { - log.warn("尝试降级到默认存储"); - try { - IStorageAdapter defaultAdapter = StorageFactory.use(DEFAULT_STORAGE); - String uploadedUrl = uploadFile(defaultAdapter, fileToUpload); - context.setResultUrl(uploadedUrl); - - log.info("降级上传成功: {}", uploadedUrl); - return StageResult.degraded("降级: 使用默认存储 " + DEFAULT_STORAGE); - - } catch (Exception fallbackEx) { - log.error("降级上传也失败", fallbackEx); - return StageResult.failed("上传失败(包括降级): " + fallbackEx.getMessage(), fallbackEx); - } - } - return StageResult.failed("上传失败: " + e.getMessage(), e); } } diff --git a/src/main/java/com/ycwl/basic/puzzle/service/impl/PuzzleGenerateServiceImpl.java b/src/main/java/com/ycwl/basic/puzzle/service/impl/PuzzleGenerateServiceImpl.java index c7e7fd85..2aaeb56b 100644 --- a/src/main/java/com/ycwl/basic/puzzle/service/impl/PuzzleGenerateServiceImpl.java +++ b/src/main/java/com/ycwl/basic/puzzle/service/impl/PuzzleGenerateServiceImpl.java @@ -468,12 +468,14 @@ public class PuzzleGenerateServiceImpl implements IPuzzleGenerateService { // 上传到OSS try (FileInputStream fis = new FileInputStream(qrcode)) { String fileName = String.format("qrcode_%d.jpg", faceId); - boolean exists = StorageFactory.use().isExists("puzzle", "wechat_qrcode", fileName); + var storageAdapter = StorageFactory.use(); + boolean exists = storageAdapter.isExists("puzzle", "wechat_qrcode", fileName); if (exists) { - log.debug("微信小程序二维码已存在, 不重复上传: faceId={}, url={}", faceId, StorageFactory.use().getUrl("puzzle", "wechat_qrcode", fileName)); - return StorageFactory.use().getUrl("puzzle", "wechat_qrcode", fileName); + String url = storageAdapter.getUrl("puzzle", "wechat_qrcode", fileName); + log.debug("微信小程序二维码已存在, 不重复上传: faceId={}, url={}", faceId, url); + return url; } - return StorageFactory.use().uploadFile( + return storageAdapter.uploadFile( "image/jpeg", fis, "puzzle", diff --git a/src/main/java/com/ycwl/basic/repository/SourceRepository.java b/src/main/java/com/ycwl/basic/repository/SourceRepository.java index 8a0d0698..7d45d213 100644 --- a/src/main/java/com/ycwl/basic/repository/SourceRepository.java +++ b/src/main/java/com/ycwl/basic/repository/SourceRepository.java @@ -19,7 +19,6 @@ import com.ycwl.basic.pricing.enums.VoucherDiscountType; import com.ycwl.basic.pricing.service.IVoucherService; import com.ycwl.basic.storage.StorageFactory; import com.ycwl.basic.storage.adapters.IStorageAdapter; -import com.ycwl.basic.storage.exceptions.StorageUnsupportedException; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; @@ -154,14 +153,7 @@ public class SourceRepository { .build(); context.enableStage("image_sr"); context.enableStage("image_enhance"); - ScenicConfigManager configManager = scenicRepository.getScenicConfigManager(source.getScenicId()); - IStorageAdapter adapter; - try { - adapter = StorageFactory.get(configManager.getString("store_type")); - adapter.loadConfig(configManager.getObject("store_config_json", Map.class)); - } catch (StorageUnsupportedException ignored) { - adapter = StorageFactory.use("assets-ext"); - } + IStorageAdapter adapter = StorageFactory.use(); context.setStorageAdapter(adapter); // 2. 设置结果URL回调 - 更新source记录 diff --git a/src/main/java/com/ycwl/basic/service/mobile/impl/GoodsServiceImpl.java b/src/main/java/com/ycwl/basic/service/mobile/impl/GoodsServiceImpl.java index 32a12539..9a314f8f 100644 --- a/src/main/java/com/ycwl/basic/service/mobile/impl/GoodsServiceImpl.java +++ b/src/main/java/com/ycwl/basic/service/mobile/impl/GoodsServiceImpl.java @@ -51,7 +51,6 @@ import com.ycwl.basic.model.repository.TaskUpdateResult; import com.ycwl.basic.storage.StorageFactory; import com.ycwl.basic.storage.adapters.IStorageAdapter; import com.ycwl.basic.storage.enums.StorageAcl; -import com.ycwl.basic.storage.enums.StorageType; import com.ycwl.basic.utils.ApiResponse; import com.ycwl.basic.utils.WxMpUtil; import lombok.extern.slf4j.Slf4j; @@ -573,13 +572,7 @@ public class GoodsServiceImpl implements GoodsService { if (configManager != null && configManager.getString("watermark_type") != null && !isBuy.isBuy()) { ImageWatermarkOperatorEnum type = ImageWatermarkOperatorEnum.getByCode(configManager.getString("watermark_type")); if (type != null) { - IStorageAdapter adapter; - if (configManager.getEnum("store_type", StorageType.class) != null) { - adapter = StorageFactory.get(configManager.getEnum("store_type", StorageType.class)); - adapter.loadConfig(JacksonUtil.parseObject(configManager.getString("store_config_json"), Map.class)); - } else { - adapter = StorageFactory.use("assets-ext"); - } + IStorageAdapter adapter = StorageFactory.use(); List watermarkEntityList = sourceMapper.listSourceWatermark(list.stream().map(SourceRespVO::getId).collect(Collectors.toList()), face.getId(), type.getType()); // 边缘端处理:需要二维码和头像 URL diff --git a/src/main/java/com/ycwl/basic/service/pc/impl/SourceServiceImpl.java b/src/main/java/com/ycwl/basic/service/pc/impl/SourceServiceImpl.java index dc6aa81f..68c0480c 100644 --- a/src/main/java/com/ycwl/basic/service/pc/impl/SourceServiceImpl.java +++ b/src/main/java/com/ycwl/basic/service/pc/impl/SourceServiceImpl.java @@ -13,7 +13,6 @@ import com.ycwl.basic.model.pc.source.resp.SourceRespVO; import com.ycwl.basic.repository.DeviceRepository; import com.ycwl.basic.repository.ScenicRepository; import com.ycwl.basic.repository.SourceRepository; -import com.ycwl.basic.service.pc.ScenicService; import com.ycwl.basic.service.pc.SourceService; import com.ycwl.basic.storage.adapters.IStorageAdapter; import com.ycwl.basic.task.VideoPieceGetter; @@ -47,8 +46,6 @@ public class SourceServiceImpl implements SourceService { @Autowired private SourceRepository sourceRepository; @Autowired - private ScenicService scenicService; - @Autowired private ScenicRepository scenicRepository; @Autowired private DeviceRepository deviceRepository; @@ -184,7 +181,7 @@ public class SourceServiceImpl implements SourceService { throw new BaseException("该素材不存在"); } try { - IStorageAdapter adapter = scenicService.getScenicStorageAdapter(source.getScenicId()); + IStorageAdapter adapter = StorageFactory.use(); String uploadedUrl = adapter.uploadFile("image/jpeg", file, PHOTO_PATH, id + "_q_.jpg"); SourceEntity sourceUpd = new SourceEntity(); diff --git a/src/main/java/com/ycwl/basic/service/printer/impl/PrinterServiceImpl.java b/src/main/java/com/ycwl/basic/service/printer/impl/PrinterServiceImpl.java index 5ff4f70a..375ea463 100644 --- a/src/main/java/com/ycwl/basic/service/printer/impl/PrinterServiceImpl.java +++ b/src/main/java/com/ycwl/basic/service/printer/impl/PrinterServiceImpl.java @@ -1103,25 +1103,7 @@ public class PrinterServiceImpl implements PrinterService { * 从context中的scenicConfigManager获取配置 */ private void prepareStorageAdapter(PhotoProcessContext context) { - ScenicConfigManager scenicConfig = context.getScenicConfigManager(); - if (scenicConfig == null) { - log.warn("scenicConfigManager未设置,将使用默认存储"); - return; - } - - try { - String storeType = scenicConfig.getString("store_type"); - if (storeType != null) { - IStorageAdapter adapter = StorageFactory.get(storeType); - String storeConfigJson = scenicConfig.getString("store_config_json"); - if (StringUtils.isNotBlank(storeConfigJson)) { - adapter.loadConfig(JacksonUtil.parseObject(storeConfigJson, Map.class)); - } - context.setStorageAdapter(adapter); - } - } catch (Exception e) { - log.warn("准备存储适配器失败,将使用默认存储: {}", e.getMessage()); - } + context.setStorageAdapter(StorageFactory.use()); } @Override diff --git a/src/main/java/com/ycwl/basic/service/task/impl/TaskTaskServiceImpl.java b/src/main/java/com/ycwl/basic/service/task/impl/TaskTaskServiceImpl.java index 9f8b2c17..874bcd12 100644 --- a/src/main/java/com/ycwl/basic/service/task/impl/TaskTaskServiceImpl.java +++ b/src/main/java/com/ycwl/basic/service/task/impl/TaskTaskServiceImpl.java @@ -615,14 +615,7 @@ public class TaskTaskServiceImpl implements TaskService { if (worker == null) { return null; } - RenderWorkerConfigManager config = repository.getWorkerConfigManager(worker.getId()); - IStorageAdapter adapter; - try { - adapter = StorageFactory.get(config.getString("store_type")); - adapter.loadConfig(config.getObject("store_config_json", Map.class)); - } catch (Exception e) { - adapter = scenicService.getScenicStorageAdapter(task.getScenicId()); - } + IStorageAdapter adapter = scenicService.getScenicStorageAdapter(task.getScenicId()); String hash = MD5.create().digestHex(task.getTaskParams() + task.getFaceId().toString()); String filename = StorageUtil.joinPath(StorageConstant.VLOG_PATH, task.getTemplateId().toString() + "_" + hash + "_" + task.getScenicId() + ".mp4"); // 生成 diff --git a/src/main/java/com/ycwl/basic/task/FaceCleaner.java b/src/main/java/com/ycwl/basic/task/FaceCleaner.java index 8c0f204e..6290cb5f 100644 --- a/src/main/java/com/ycwl/basic/task/FaceCleaner.java +++ b/src/main/java/com/ycwl/basic/task/FaceCleaner.java @@ -34,7 +34,9 @@ import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; import static com.ycwl.basic.constant.FaceConstant.USER_FACE_DB_NAME; @@ -226,6 +228,16 @@ public class FaceCleaner { public void cleanSourceOss() { log.info("开始清理源视频素材文件"); List list = sourceMapper.list(new SourceReqQuery()); + Map sourceImageUrlMap = new HashMap<>(); + Map sourceScenicIdMap = new HashMap<>(); + list.forEach(item -> { + if (item.getId() != null && item.getScenicId() != null) { + sourceScenicIdMap.put(item.getId(), item.getScenicId()); + } + if (item.getId() != null) { + sourceImageUrlMap.put(item.getId(), item.getUrl()); + } + }); ArrayList adapterIdentity = new ArrayList<>(); ScenicReqQuery query = new ScenicReqQuery(); query.setPageSize(1000); @@ -260,22 +272,45 @@ public class FaceCleaner { log.info("文件存在关系:{},未删除", fileObject); } }); - log.info("开始清理图片文件"); - fileObjectList = adapter.listDir(StorageConstant.PHOTO_PATH); - fileObjectList.parallelStream().forEach(fileObject -> { - if (fileObject.getModifyTime() != null) { - // 如果是一天以内修改的,则跳过 - if (DateUtil.between(fileObject.getModifyTime(), new Date(), DateUnit.DAY) <= 1) { - return; - } + }); + + log.info("开始清理图片文件"); + IStorageAdapter imageAdapter = StorageFactory.use(); + List fileObjectList = imageAdapter.listDir(StorageConstant.PHOTO_PATH); + fileObjectList.parallelStream().forEach(fileObject -> { + if (fileObject.getModifyTime() != null) { + // 如果是一天以内修改的,则跳过 + if (DateUtil.between(fileObject.getModifyTime(), new Date(), DateUnit.DAY) <= 1) { + return; } - if (list.parallelStream().filter(videoRespVO -> Objects.nonNull(videoRespVO.getUrl())).noneMatch(videoRespVO -> videoRespVO.getUrl().contains(fileObject.getName()))){ - log.info("删除文件:{}", fileObject); - adapter.deleteFile(fileObject.getFullPath()); - } else { - log.info("文件存在关系:{},未删除", fileObject); - } - }); + } + + String name = fileObject.getName(); + if (name == null) { + return; + } + int underscoreIndex = name.indexOf('_'); + if (underscoreIndex <= 0) { + return; + } + Long sourceId; + try { + sourceId = Long.parseLong(name.substring(0, underscoreIndex)); + } catch (NumberFormatException e) { + return; + } + Long scenicId = sourceScenicIdMap.get(sourceId); + if (scenicId == null || disableDeleteScenicIds.contains(scenicId.toString())) { + return; + } + + String imageUrl = sourceImageUrlMap.get(sourceId); + if (imageUrl != null && imageUrl.contains(name)) { + log.info("文件存在关系:{},未删除", fileObject); + return; + } + log.info("删除文件:{}", fileObject); + imageAdapter.deleteFile(fileObject.getFullPath()); }); } public void cleanVideoOss() {