diff --git a/servers/boe-server-all/src/main/java/com/xboe/school/study/api/StudyCourseTask.java b/servers/boe-server-all/src/main/java/com/xboe/school/study/api/StudyCourseTask.java index de8d0dc7..9b8de218 100644 --- a/servers/boe-server-all/src/main/java/com/xboe/school/study/api/StudyCourseTask.java +++ b/servers/boe-server-all/src/main/java/com/xboe/school/study/api/StudyCourseTask.java @@ -18,6 +18,7 @@ import java.time.format.DateTimeFormatter; import java.util.List; import java.util.Objects; import java.util.concurrent.TimeUnit; +import java.util.function.BiConsumer; /** * @author by lyc @@ -37,9 +38,8 @@ public class StudyCourseTask { * 定时任务 * 获取redis 中学习结束的数据更新入库 * */ - @XxlJob("saveStudyCourseItemLastTime") - public void saveStudyCourseItemLastTime() { - log.info("------定时任务-获取redis 中学习结束的数据更新入库------" ); + @XxlJob("saveStudyCourseItemLastTime2") + public void saveStudyCourseItemLastTime2() { // 1. 定义匹配模式(匹配所有目标key) final String KEY_PATTERN = "studyContentId:*:last_active"; DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"); @@ -54,10 +54,9 @@ public class StudyCourseTask { // 3. 遍历处理符合条件的key while (cursor.hasNext()) { String redisKey = new String(cursor.next()); - log.info("------定时任务-获取redis 中学习结束的数据更新入库------redisKey = " + redisKey ); // 4. 获取剩余TTL(秒) Long ttl = redisTemplate.getExpire(redisKey, TimeUnit.SECONDS); - log.info("------定时任务-获取redis 中学习结束的数据更新入库------ttl = " + ttl ); + // 5. 过滤条件:剩余时间 >= 29天23小时30分钟(转换为秒) // 总需时间 = (30天 - 30分钟) = 29天23小时30分钟 = 2590200秒 // 5分钟 300秒 || 2592000 - 300 = 2591700 @@ -76,7 +75,6 @@ public class StudyCourseTask { if (partValues.length >= 2){ timestamp = LocalDateTime.parse(partValues[1], formatter); } - log.info("-定时任务-获取redis 中学习结束的数据更新入库---studyContentId = " + studyContentId + ",lastStudyTime = " + lastStudyTime + ", timestamp = " + timestamp); // 8. 更新数据库(调用已有服务方法) studyService.updateStudyCourseItemLastTime(studyContentId, lastStudyTime, timestamp); // 9. 删除Redis键(原子操作) @@ -164,4 +162,90 @@ public class StudyCourseTask { } + + @XxlJob("saveStudyCourseItemLastTime") + public void saveStudyCourseItemLastTime() { + // 定义需要处理的键模式集合 + processKeys("studyContentId:*:last_active", this::handleLastActiveKey); + processKeys("studyId:*:courseId:*:courseContentId:*", this::handleDurationKey); + } + + private void processKeys(String keyPattern, BiConsumer keyHandler) { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"); + ScanOptions options = ScanOptions.scanOptions() + .match(keyPattern) + .count(100) + .build(); + + try (RedisConnection connection = Objects.requireNonNull(redisTemplate.getConnectionFactory()).getConnection()) { + Cursor cursor = connection.scan(options); + while (cursor.hasNext()) { + String redisKey = new String(cursor.next()); + Long ttl = redisTemplate.getExpire(redisKey, TimeUnit.SECONDS); + + if (ttl != null && ttl <= 2590200) { + try { + String redisValue = redisTemplate.opsForValue().get(redisKey); + if (redisValue != null) { + // 调用对应的处理方法 + keyHandler.accept(redisKey, redisValue); + } + redisTemplate.delete(redisKey); + log.info("Key processed: {}", redisKey); + } catch (Exception e) { + log.error("Process failed [{}]", redisKey, e); + } + } + } + cursor.close(); + } catch (Exception e) { + log.error("Key processing error: {}", keyPattern, e); + } + } + + // 处理 last_active 类型键 + private void handleLastActiveKey(String redisKey, String redisValue) { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"); + String[] parts = redisKey.split(":"); + String studyContentId = parts[1]; + + String[] values = redisValue.split("&"); + int lastStudyTime = Integer.parseInt(values[0]); + LocalDateTime timestamp = values.length >= 2 ? + LocalDateTime.parse(values[1], formatter) : null; + + studyService.updateStudyCourseItemLastTime(studyContentId, lastStudyTime, timestamp); + } + + // 处理 duration 类型键 + private void handleDurationKey(String redisKey, String redisValue) { + String[] parts = redisKey.split(":"); + String studyId = parts[1]; + String courseId = parts[3]; + String courseContentId = parts[5]; + + String[] values = redisValue.split("&"); + int duration = Integer.parseInt(values[0]); + LocalDateTime timestamp = values.length >= 2 ? + LocalDateTime.parse(values[1], DateTimeFormatter.ISO_LOCAL_DATE_TIME) : null; + + studyService.newAppendStudyDuration(studyId, null, courseContentId, duration, timestamp); + + // 保留第三方调用 + List allUserList = thirdApi.getStudyCourseList(studyId, courseId, null); + log.info("Study records synced: {}", allUserList.size()); + } + + + + + + + + + + + + + }