deason 8 hónapja
szülő
commit
a7670a4ea2

+ 55 - 50
src/main/java/com/qmth/exam/reserve/cache/impl/ApplyTaskCacheService.java

@@ -106,39 +106,6 @@ public class ApplyTaskCacheService implements CacheConstants {
         log.warn("DELETE cacheKey:{}", cacheKey);
     }
 
-    /**
-     * 获取某考点的“可预约总量”缓存
-     */
-    public int getApplyTotalCount(Long examSiteId) {
-        String cacheKey = String.format(CACHE_APPLY_TOTAL, examSiteId);
-        Integer value = redisClient.get(cacheKey, Integer.class);
-        if (value != null) {
-            return value;
-        }
-
-        value = examSiteService.countExamSiteCapacityById(examSiteId);
-        redisClient.set(cacheKey, value, CACHE_TIME_OUT_10, TimeUnit.MINUTES);
-        log.info("SET cacheKey:{} value:{}", cacheKey, value);
-
-        return value;
-    }
-
-    /**
-     * 清除某考点的“可预约总量”缓存
-     */
-    public void clearApplyTotalCountCache(Long examSiteId) {
-        String cacheKey = String.format(CACHE_APPLY_TOTAL, examSiteId);
-        redisClient.delete(cacheKey);
-        log.warn("DELETE cacheKey:{}", cacheKey);
-    }
-
-    /**
-     * 获取某考点某时段的“已预约数量”(查数据库)
-     */
-    public int getApplyFinishCountFormDB(Long examSiteId, Long timePeriodId) {
-        return studentApplyService.countApplyFinishForExamSiteAndTimePeriod(examSiteId, timePeriodId);
-    }
-
     /**
      * 获取某考点某时段的“剩余可约数量”缓存
      */
@@ -195,18 +162,16 @@ public class ApplyTaskCacheService implements CacheConstants {
     }
 
     /**
-     * 初始化 某考点某时段的“剩余可约数量”缓存
+     * 刷新 某考点某时段的“剩余可约数量”缓存
      */
-    public void initApplyAvailableCountCache(Long examSiteId, int oldCapacity, int newCapacity) {
-        String examSiteCapacityLockKey = String.format(CacheConstants.LOCK_EXAM_SITE_CAPACITY, examSiteId);
-        Lock examSiteCapacityLock = concurrentService.getLock(examSiteCapacityLockKey);
+    public void refreshApplyAvailableCountCache(Long examSiteId, int oldCapacity, int newCapacity) {
+        String lockKey = String.format(CacheConstants.LOCK_EXAM_SITE_CAPACITY, examSiteId);
+        Lock lock = concurrentService.getLock(lockKey);
 
         try {
-            if (!examSiteCapacityLock.tryLock()) {
-                log.warn("获取锁失败,不允许同时操作!lockKey:{}", examSiteCapacityLockKey);
-                return;
+            if (!lock.tryLock()) {
+                throw new RuntimeException("获取锁失败,不允许同时操作!" + lockKey);
             }
-            log.debug("获取锁成功!lockKey:{}", examSiteCapacityLockKey);
 
             // 获取所有时段ID集合
             List<TimePeriodEntity> timePeriods = timePeriodService.list(new LambdaQueryWrapper<TimePeriodEntity>().select(TimePeriodEntity::getId));
@@ -224,35 +189,75 @@ public class ApplyTaskCacheService implements CacheConstants {
                         continue;
                     }
 
-                    // 总容量变化时,则更新考点剩余量缓存
+                    // 总容量变化时,则更新考点剩余可约数量缓存
                     RAtomicLong atomic = redisClient.getRedissonClient().getAtomicLong(cacheKey);
                     long availableCount = Math.max(atomic.get() + diffCapacity, 0);
                     atomic.set(availableCount);
                     log.warn("SET cacheKey:{} value:{}", cacheKey, availableCount);
                 } else {
-                    // 初始考点剩余量缓存
+                    // 初始考点剩余可约数量缓存
                     RAtomicLong atomic = redisClient.getRedissonClient().getAtomicLong(cacheKey);
                     atomic.set(newCapacity);
-                    log.debug("SET cacheKey:{} value:{}", cacheKey, newCapacity);
+                    log.info("SET cacheKey:{} value:{}", cacheKey, newCapacity);
                 }
             }
         } finally {
             try {
-                examSiteCapacityLock.unlock();
-                log.debug("解锁成功!lockKey:{}", examSiteCapacityLockKey);
+                lock.unlock();
             } catch (Exception e) {
-                log.warn("解锁失败!lockKey:{} err:{}", examSiteCapacityLockKey, e.getMessage());
+                log.warn("解锁失败!lockKey:{} err:{}", lockKey, e.getMessage());
             }
         }
     }
 
     /**
-     * 初始 所有考点所有时段的“剩余可约数量”缓存
+     * 初始或重置计算 所有考点所有时段的“剩余可约数量”缓存
      */
-    public void initApplyAvailableCountCacheForAllExamSites() {
+    public void initApplyAvailableCountCacheForAllExamSites(boolean skipExisted) {
+        // 获取所有考点和考点总容量集合
         List<ExamSiteCapacityInfo> examSites = examSiteService.findAllExamSiteCapacityList();
+        if (CollectionUtils.isEmpty(examSites)) {
+            return;
+        }
+
+        // 获取所有时段ID集合
+        List<TimePeriodEntity> timePeriods = timePeriodService.list(new LambdaQueryWrapper<TimePeriodEntity>().select(TimePeriodEntity::getId));
+        if (CollectionUtils.isEmpty(timePeriods)) {
+            return;
+        }
+
         for (ExamSiteCapacityInfo examSite : examSites) {
-            this.initApplyAvailableCountCache(examSite.getExamSiteId(), examSite.getCapacity(), examSite.getCapacity());
+            String lockKey = String.format(CacheConstants.LOCK_EXAM_SITE_CAPACITY, examSite.getExamSiteId());
+            Lock lock = concurrentService.getLock(lockKey);
+
+            try {
+                if (!lock.tryLock()) {
+                    log.warn("获取锁失败,不允许同时操作!{}", lockKey);
+                    return;
+                }
+
+                for (TimePeriodEntity timePeriod : timePeriods) {
+                    String cacheKey = String.format(CACHE_APPLY_AVAILABLE_COUNT, examSite.getExamSiteId(), timePeriod.getId());
+                    if (redisClient.exist(cacheKey) && skipExisted) {
+                        // 跳过存在的缓存
+                        continue;
+                    }
+
+                    // 获取某考点某时段的“已预约数量”(仅查数据库会有误差,需等预约队列中全部完成数据库持久化后再执行!)
+                    int finishCount = studentApplyService.countApplyFinishForExamSiteAndTimePeriod(examSite.getExamSiteId(), timePeriod.getId());
+                    // 剩余可约数量
+                    int availableCount = Math.max(examSite.getCapacity() - finishCount, 0);
+                    RAtomicLong atomic = redisClient.getRedissonClient().getAtomicLong(cacheKey);
+                    atomic.set(availableCount);
+                    log.warn("SET cacheKey:{} value:{}", cacheKey, availableCount);
+                }
+            } finally {
+                try {
+                    lock.unlock();
+                } catch (Exception e) {
+                    log.warn("解锁失败!lockKey:{} err:{}", lockKey, e.getMessage());
+                }
+            }
         }
     }
 

+ 1 - 1
src/main/java/com/qmth/exam/reserve/config/InitApplyTaskCacheData.java

@@ -19,7 +19,7 @@ public class InitApplyTaskCacheData implements CommandLineRunner {
     public void run(String... args) throws Exception {
         log.info("initApplyTaskCacheData start...");
         long startTime = System.currentTimeMillis();
-        applyTaskCacheService.initApplyAvailableCountCacheForAllExamSites();
+        applyTaskCacheService.initApplyAvailableCountCacheForAllExamSites(true);
         log.info("initApplyTaskCacheData ok... cost:{}ms", System.currentTimeMillis() - startTime);
     }
 

+ 12 - 1
src/main/java/com/qmth/exam/reserve/controller/IndexController.java

@@ -1,6 +1,7 @@
 package com.qmth.exam.reserve.controller;
 
 import com.qmth.exam.reserve.cache.RedisClient;
+import com.qmth.exam.reserve.cache.impl.ApplyTaskCacheService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -15,6 +16,9 @@ public class IndexController extends BaseController {
 
     private static final Logger log = LoggerFactory.getLogger(IndexController.class);
 
+    @Autowired
+    private ApplyTaskCacheService applyTaskCacheService;
+
     @Autowired
     private RedisClient redisClient;
 
@@ -25,7 +29,7 @@ public class IndexController extends BaseController {
 
     @GetMapping(value = "/api/cache/clear")
     public String clearCache() {
-        // 清理缓存接口(临时)
+        // 清理所有缓存信息接口(临时)
         RedisTemplate<String, Object> redisTemplate = redisClient.getRedisTemplate();
         Set<String> keys = redisTemplate.keys("$cache:*");
         if (keys != null && !keys.isEmpty()) {
@@ -37,4 +41,11 @@ public class IndexController extends BaseController {
         return "ok";
     }
 
+    @GetMapping(value = "/api/cache/init")
+    public String initCache() {
+        // 初始或修复关键缓存信息接口(临时)
+        applyTaskCacheService.initApplyAvailableCountCacheForAllExamSites(false);
+        return "ok";
+    }
+
 }

+ 1 - 1
src/main/java/com/qmth/exam/reserve/service/impl/ExamRoomServiceImpl.java

@@ -236,7 +236,7 @@ public class ExamRoomServiceImpl extends ServiceImpl<ExamRoomDao, ExamRoomEntity
         /*//清空考点容量缓存
         cacheService.clearApplyTotalCountCache(examSiteId);*/
         //清空考点容量缓存
-        cacheService.initApplyAvailableCountCache(examSiteId, oldExamSite.getCapacity(), newExamSite.getCapacity());
+        cacheService.refreshApplyAvailableCountCache(examSiteId, oldExamSite.getCapacity(), newExamSite.getCapacity());
     }
 
     private void checkExamRoom(ExamRoomSaveReq req) {