package com.qmth.exam.reserve.cache.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.qmth.exam.reserve.bean.apply.ApplyRecordCacheBean; import com.qmth.exam.reserve.bean.applytask.CurrentApplyTaskVO; import com.qmth.exam.reserve.cache.CacheConstants; import com.qmth.exam.reserve.cache.RedisClient; import com.qmth.exam.reserve.entity.StudentApplyEntity; import com.qmth.exam.reserve.service.ApplyTaskService; import com.qmth.exam.reserve.service.ExamSiteService; import com.qmth.exam.reserve.service.StudentApplyService; import com.qmth.exam.reserve.service.StudentService; import org.apache.commons.collections4.CollectionUtils; import org.redisson.api.RAtomicLong; import org.redisson.api.RBlockingQueue; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; @Component public class ApplyTaskCacheService implements CacheConstants { private static final Logger log = LoggerFactory.getLogger(ApplyTaskCacheService.class); @Autowired private RedisClient redisClient; @Autowired private ApplyTaskService applyTaskService; @Autowired private ExamSiteService examSiteService; @Autowired private StudentService studentService; @Autowired private StudentApplyService studentApplyService; /** * 获取当前启用的预约任务缓存 */ public CurrentApplyTaskVO currentApplyTask(Long orgId) { String cacheKey = String.format(CACHE_CURRENT_APPLY_TASK, orgId); CurrentApplyTaskVO value = redisClient.get(cacheKey, CurrentApplyTaskVO.class); if (value != null) { return value; } value = applyTaskService.currentApplyTask(orgId); if (value == null) { return null; } redisClient.set(cacheKey, value, 5, TimeUnit.MINUTES); log.info("SET cacheKey:{} curApplyTaskId:{}", cacheKey, value.getTaskId()); return value; } public void clearCurrentApplyTaskCache(Long orgId) { String cacheKey = String.format(CACHE_CURRENT_APPLY_TASK, orgId); redisClient.delete(cacheKey); log.warn("DELETE cacheKey:{}", cacheKey); } /** * 获取某考生的“允许预约时段次数” */ public int getStudentApplyNumber(Long studentId) { String cacheKey = String.format(CACHE_STUDENT_APPLY_NUMBER, studentId); Integer value = redisClient.get(cacheKey, Integer.class); if (value != null) { return value; } value = studentService.findStudentApplyNumberById(studentId); redisClient.set(cacheKey, value, 5, TimeUnit.MINUTES); log.info("SET cacheKey:{} value:{}", cacheKey, value); return value; } public void clearStudentApplyNumberCache(Long studentId) { String cacheKey = String.format(CACHE_STUDENT_APPLY_NUMBER, studentId); redisClient.delete(cacheKey); 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, 5, 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 getApplyFinishCount(Long examSiteId, Long timePeriodId) { String cacheKey = String.format(CACHE_APPLY_FINISH, examSiteId, timePeriodId); if (redisClient.exist(cacheKey)) { return (int) redisClient.getRedissonClient().getAtomicLong(cacheKey).get(); } RAtomicLong atomic = redisClient.getRedissonClient().getAtomicLong(cacheKey); int value = studentApplyService.countApplyFinishForExamSiteAndTimePeriod(examSiteId, timePeriodId); atomic.set(value); atomic.expire(30, TimeUnit.DAYS); log.info("SET cacheKey:{} value:{}", cacheKey, value); return value; } /** * 累加 某考点某时段的“已预约数量” */ public void increaseApplyFinishCount(Long examSiteId, Long timePeriodId) { String cacheKey = String.format(CACHE_APPLY_FINISH, examSiteId, timePeriodId); RAtomicLong atomic = redisClient.getRedissonClient().getAtomicLong(cacheKey); atomic.incrementAndGet(); } /** * 累减 某考点某时段的“已预约数量” */ public void decreaseApplyFinishCount(Long examSiteId, Long timePeriodId) { String cacheKey = String.format(CACHE_APPLY_FINISH, examSiteId, timePeriodId); RAtomicLong atomic = redisClient.getRedissonClient().getAtomicLong(cacheKey); if (atomic.get() > 0) { atomic.decrementAndGet(); } } /** * 获取某考生的 已完成预约次数 */ public int getStudentApplyFinishCount(Long studentId) { String cacheKey = String.format(CACHE_STUDENT_APPLY_RECORD, studentId); if (!redisClient.exist(cacheKey)) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(StudentApplyEntity::getStudentId, studentId); wrapper.eq(StudentApplyEntity::getCancel, Boolean.FALSE); return studentApplyService.count(wrapper); } // todo不走数据库查询,以redis中数据为准 Map maps = this.getStudentApplyRecords(studentId); int studentApplyFinishCount = 0; for (ApplyRecordCacheBean bean : maps.values()) { if (!bean.getCancel()) { studentApplyFinishCount++; } } return studentApplyFinishCount; } /** * 获取某考生的 所有的“预约记录”缓存 */ public Map getStudentApplyRecords(Long studentId) { String cacheKey = String.format(CACHE_STUDENT_APPLY_RECORD, studentId); if (!redisClient.exist(cacheKey)) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(StudentApplyEntity::getStudentId, studentId); List list = studentApplyService.list(wrapper); Map maps = new HashMap<>(); if (CollectionUtils.isNotEmpty(list)) { for (StudentApplyEntity entity : list) { ApplyRecordCacheBean bean = new ApplyRecordCacheBean(); bean.setStudentId(entity.getStudentId()); bean.setExamSiteId(entity.getExamSiteId()); bean.setTimePeriodId(entity.getTimePeriodId()); bean.setCancel(entity.getCancel()); bean.setOperateId(entity.getOperateId()); bean.setOperateTime(entity.getUpdateTime()); this.saveStudentApplyRecord(bean); String hashKey = String.format("%s_%s", entity.getExamSiteId(), entity.getTimePeriodId()); maps.put(hashKey, bean); } redisClient.expire(cacheKey, 30, TimeUnit.DAYS); } return maps; } // todo不走数据库查询,以redis中数据为准 return redisClient.getEntriesForHash(cacheKey, ApplyRecordCacheBean.class); } /** * 获取某考生的 某考点某时段的“预约记录”缓存 */ public ApplyRecordCacheBean getStudentApplyRecord(Long studentId, Long examSiteId, Long timePeriodId) { String cacheKey = String.format(CACHE_STUDENT_APPLY_RECORD, studentId); String hashKey = String.format("%s_%s", examSiteId, timePeriodId); return redisClient.getForHash(cacheKey, hashKey, ApplyRecordCacheBean.class); } /** * 保存某考生的 某考点某时段的“预约记录”缓存 */ public void saveStudentApplyRecord(ApplyRecordCacheBean value) { String cacheKey = String.format(CACHE_STUDENT_APPLY_RECORD, value.getStudentId()); String hashKey = String.format("%s_%s", value.getExamSiteId(), value.getTimePeriodId()); redisClient.setForHash(cacheKey, hashKey, value); log.info("SET cacheKey:{} hashKey:{} cancel:{}", cacheKey, hashKey, value.getCancel()); } /** * 推送至考生预约记录队列 */ public void pushStudentApplyRecordQueue(ApplyRecordCacheBean value) { if (value == null) { return; } RBlockingQueue queue = redisClient.getRedissonClient() .getBlockingQueue(QUEUE_STUDENT_APPLY_RECORD); boolean success = queue.offer(value); if (!success) { throw new RuntimeException("推送至考生预约记录队列失败"); } } /** * 获取考生预约记录队列数量 */ public int getStudentApplyRecordQueueSize() { RBlockingQueue queue = redisClient.getRedissonClient() .getBlockingQueue(QUEUE_STUDENT_APPLY_RECORD); return queue.size(); } }