|
@@ -2,7 +2,9 @@ package com.qmth.exam.reserve.service.impl;
|
|
|
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|
|
+import com.qmth.boot.core.concurrent.service.ConcurrentService;
|
|
|
import com.qmth.boot.core.exception.StatusException;
|
|
|
+import com.qmth.exam.reserve.bean.Constants;
|
|
|
import com.qmth.exam.reserve.bean.RichTextBean;
|
|
|
import com.qmth.exam.reserve.bean.apply.ApplyTimePeriodResult;
|
|
|
import com.qmth.exam.reserve.bean.apply.ApplyVO;
|
|
@@ -10,6 +12,7 @@ import com.qmth.exam.reserve.bean.apply.TicketInfo;
|
|
|
import com.qmth.exam.reserve.bean.apply.TimePeriodInfo;
|
|
|
import com.qmth.exam.reserve.bean.applytask.CurrentApplyTaskVO;
|
|
|
import com.qmth.exam.reserve.bean.login.LoginUser;
|
|
|
+import com.qmth.exam.reserve.cache.CacheConstants;
|
|
|
import com.qmth.exam.reserve.dao.StudentApplyDao;
|
|
|
import com.qmth.exam.reserve.entity.*;
|
|
|
import com.qmth.exam.reserve.enums.ApplyStatus;
|
|
@@ -26,6 +29,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
|
import java.text.ParseException;
|
|
|
import java.util.*;
|
|
|
+import java.util.concurrent.locks.Lock;
|
|
|
|
|
|
@Service
|
|
|
public class ExamReserveServiceImpl implements ExamReserveService {
|
|
@@ -47,6 +51,9 @@ public class ExamReserveServiceImpl implements ExamReserveService {
|
|
|
@Autowired
|
|
|
private ExamSiteService examSiteService;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ private ConcurrentService concurrentService;
|
|
|
+
|
|
|
@Override
|
|
|
@Transactional
|
|
|
public void saveStudentApply(LoginUser student, Long examSiteId, Long timePeriodId) {
|
|
@@ -68,18 +75,6 @@ public class ExamReserveServiceImpl implements ExamReserveService {
|
|
|
throw new StatusException("当前预约任务与学生的不匹配");
|
|
|
}
|
|
|
|
|
|
- StudentEntity stu = studentService.findLessInfoByStudentId(student.getId());
|
|
|
- if (stu == null) {
|
|
|
- log.warn("预约失败,学生信息不存在!studentId:{}", student.getId());
|
|
|
- throw new StatusException("学生信息不存在");
|
|
|
- }
|
|
|
-
|
|
|
- if (stu.getApplyFinished()) {
|
|
|
- String msg = "当前学生无剩余可约时段,已完成预约" + stu.getApplyNumber() + "次";
|
|
|
- log.warn(msg);
|
|
|
- // throw new StatusException(msg);
|
|
|
- }
|
|
|
-
|
|
|
TimePeriodEntity timePeriod = timePeriodService.getById(timePeriodId);
|
|
|
if (timePeriod == null || !curApplyTask.getTaskId().equals(timePeriod.getApplyTaskId())) {
|
|
|
log.warn("预约失败,当前预约时段信息有误!timePeriodId:{}", timePeriodId);
|
|
@@ -96,41 +91,68 @@ public class ExamReserveServiceImpl implements ExamReserveService {
|
|
|
throw new StatusException("当前预约时段已禁止预约");
|
|
|
}
|
|
|
|
|
|
- // 当前预约时段剩余可约数量
|
|
|
- int availableCount = 0;//todo
|
|
|
- // if (availableCount == 0) {
|
|
|
- // throw new StatusException("当前预约时段已约满");
|
|
|
- // }
|
|
|
-
|
|
|
// 考生预约操作锁
|
|
|
- // 更新预约时段、机房容量等操作
|
|
|
- // 系统自动预约“任务执行期间”不允许预约
|
|
|
-
|
|
|
- LambdaQueryWrapper<StudentApplyEntity> wrapper = new LambdaQueryWrapper<>();
|
|
|
- wrapper.eq(StudentApplyEntity::getStudentId, student.getId());
|
|
|
- wrapper.eq(StudentApplyEntity::getExamSiteId, examSiteId);
|
|
|
- wrapper.eq(StudentApplyEntity::getTimePeriodId, timePeriodId);
|
|
|
- StudentApplyEntity existEntity = studentApplyService.getOne(wrapper);
|
|
|
- if (existEntity != null) {
|
|
|
- if (!existEntity.getCancel()) {
|
|
|
- log.warn("预约失败,当前时段已预约,请勿重复预约!applyId:{}", existEntity.getId());
|
|
|
- throw new StatusException("当前时段已预约,请勿重复预约");
|
|
|
+ String studentApplyLockKey = String.format(CacheConstants.LOCK_STUDENT_APPLY, student.getId());
|
|
|
+ Lock studentApplyLock = concurrentService.getLock(studentApplyLockKey);
|
|
|
+ try {
|
|
|
+ if (!studentApplyLock.tryLock()) {
|
|
|
+ log.warn("获取锁失败,不允许同一个考生同时操作预约!lockKey:{}", studentApplyLockKey);
|
|
|
+ throw new StatusException(Constants.SYSTEM_BUSY);
|
|
|
}
|
|
|
|
|
|
- // 存在“已取消”预约记录,则恢复预约
|
|
|
- this.updateStudentApplyForCancel(existEntity.getId(), false, student.getId());
|
|
|
- } else {
|
|
|
- // 不存在则新增预约记录
|
|
|
- StudentApplyEntity entity = new StudentApplyEntity();
|
|
|
- entity.setStudentId(student.getId());
|
|
|
- entity.setExamSiteId(examSiteId);
|
|
|
- entity.setTimePeriodId(timePeriodId);
|
|
|
- entity.setOperateId(student.getId());
|
|
|
- entity.setCancel(false);
|
|
|
- studentApplyService.save(entity);
|
|
|
- log.warn("新增考生预约记录!applyId:{} examSiteId:{} timePeriodId:{}", entity.getId(), examSiteId, timePeriodId);
|
|
|
- }
|
|
|
+ if (concurrentService.isLocked(CacheConstants.LOCK_AUTO_APPLY)) {
|
|
|
+ // 系统自动预约“任务执行期间”不允许预约
|
|
|
+ log.warn("系统自动预约中,不允许考生操作预约!lockKey:{}", CacheConstants.LOCK_AUTO_APPLY);
|
|
|
+ throw new StatusException(Constants.SYSTEM_BUSY);
|
|
|
+ }
|
|
|
+
|
|
|
+ StudentEntity stu = studentService.findLessInfoByStudentId(student.getId());
|
|
|
+ if (stu == null) {
|
|
|
+ log.warn("预约失败,学生信息不存在!studentId:{}", student.getId());
|
|
|
+ throw new StatusException("学生信息不存在");
|
|
|
+ }
|
|
|
|
|
|
+ if (stu.getApplyFinished()) {
|
|
|
+ String msg = "当前学生无剩余可约时段,已完成预约" + stu.getApplyNumber() + "次";
|
|
|
+ log.warn(msg);
|
|
|
+ // throw new StatusException(msg);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 当前预约时段剩余可约数量
|
|
|
+ int availableCount = 0;//todo
|
|
|
+ // if (availableCount == 0) {
|
|
|
+ // throw new StatusException("当前预约时段已约满");
|
|
|
+ // }
|
|
|
+
|
|
|
+ // 更新预约时段、机房容量等操作
|
|
|
+
|
|
|
+ LambdaQueryWrapper<StudentApplyEntity> wrapper = new LambdaQueryWrapper<>();
|
|
|
+ wrapper.eq(StudentApplyEntity::getStudentId, student.getId());
|
|
|
+ wrapper.eq(StudentApplyEntity::getExamSiteId, examSiteId);
|
|
|
+ wrapper.eq(StudentApplyEntity::getTimePeriodId, timePeriodId);
|
|
|
+ StudentApplyEntity existEntity = studentApplyService.getOne(wrapper);
|
|
|
+ if (existEntity != null) {
|
|
|
+ if (!existEntity.getCancel()) {
|
|
|
+ log.warn("预约失败,当前时段已预约,请勿重复预约!applyId:{}", existEntity.getId());
|
|
|
+ throw new StatusException("当前时段已预约,请勿重复预约");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 存在“已取消”预约记录,则恢复预约
|
|
|
+ this.updateStudentApplyForCancel(existEntity.getId(), false, student.getId());
|
|
|
+ } else {
|
|
|
+ // 不存在则新增预约记录
|
|
|
+ StudentApplyEntity entity = new StudentApplyEntity();
|
|
|
+ entity.setStudentId(student.getId());
|
|
|
+ entity.setExamSiteId(examSiteId);
|
|
|
+ entity.setTimePeriodId(timePeriodId);
|
|
|
+ entity.setOperateId(student.getId());
|
|
|
+ entity.setCancel(false);
|
|
|
+ studentApplyService.save(entity);
|
|
|
+ log.warn("新增考生预约记录!applyId:{} examSiteId:{} timePeriodId:{}", entity.getId(), examSiteId, timePeriodId);
|
|
|
+ }
|
|
|
+ } finally {
|
|
|
+ studentApplyLock.unlock();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
@Override
|
|
@@ -181,12 +203,28 @@ public class ExamReserveServiceImpl implements ExamReserveService {
|
|
|
throw new StatusException("当前预约记录已禁止取消预约");
|
|
|
}
|
|
|
|
|
|
- // todo
|
|
|
// 考生预约操作锁
|
|
|
- // 更新预约时段、机房容量等操作
|
|
|
- // 系统自动预约“任务执行期间”不允许取消预约
|
|
|
+ String studentApplyLockKey = String.format(CacheConstants.LOCK_STUDENT_APPLY, student.getId());
|
|
|
+ Lock studentApplyLock = concurrentService.getLock(studentApplyLockKey);
|
|
|
+ try {
|
|
|
+ if (!studentApplyLock.tryLock()) {
|
|
|
+ log.warn("获取锁失败,不允许同一个考生同时操作预约!lockKey:{}", studentApplyLockKey);
|
|
|
+ throw new StatusException(Constants.SYSTEM_BUSY);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (concurrentService.isLocked(CacheConstants.LOCK_AUTO_APPLY)) {
|
|
|
+ // 系统自动预约“任务执行期间”不允许取消预约
|
|
|
+ log.warn("系统自动预约中,不允许考生操作预约!lockKey:{}", CacheConstants.LOCK_AUTO_APPLY);
|
|
|
+ throw new StatusException(Constants.SYSTEM_BUSY);
|
|
|
+ }
|
|
|
|
|
|
- this.updateStudentApplyForCancel(applyId, true, student.getId());
|
|
|
+ this.updateStudentApplyForCancel(applyId, true, student.getId());
|
|
|
+
|
|
|
+ // todo
|
|
|
+ // 更新预约时段、机房容量等操作
|
|
|
+ } finally {
|
|
|
+ studentApplyLock.unlock();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
private void updateStudentApplyForCancel(Long applyId, boolean cancel, Long operateId) {
|