| | |
| | | |
| | | final static Integer MAX_QUEUE_NUM = 3; |
| | | |
| | | @Resource |
| | | private queueMapper queueMapper; |
| | | |
| | | @Resource |
| | | private RoomMapper roomMapper; |
| | | |
| | | AtomicInteger openingFlag = new AtomicInteger(0); |
| | | |
| | | AtomicInteger curSeqNum = new AtomicInteger(0); |
| | | |
| | | PriorityBlockingQueue<BedQueueBO> priorityQueue = new PriorityBlockingQueue<>(); |
| | |
| | | |
| | | ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor(); |
| | | |
| | | @Resource |
| | | private queueMapper queueMapper; |
| | | |
| | | @Resource |
| | | private RoomMapper roomMapper; |
| | | |
| | | @Override |
| | | public Integer createqueue(QueueSaveReqVO createReqVO) { |
| | |
| | | queueMapper.deleteById(id); |
| | | } |
| | | |
| | | @Override |
| | | public Integer bedControl(Long roomId, String bedNo, Integer status) { |
| | | // 营业期间不能关闭工位 |
| | | if ( status == 0 && openingFlag.get() == 1 ) |
| | | return 301; |
| | | |
| | | // 当前状态 |
| | | roomMapper.select |
| | | |
| | | // DB update |
| | | Integer updateNum = roomMapper.setBedStatus(roomId, bedNo, status); |
| | | if ( null==updateNum || 0 == updateNum ) |
| | | return 310; |
| | | |
| | | if ( status == 10 ) { |
| | | BedQueueBO bedQueueBO = new BedQueueBO(); |
| | | bedQueueBO.setRoomId(roomId); |
| | | bedQueueBO.setBedNo(bedNo); |
| | | bedQueueBO.setMaxQueueNum(MAX_QUEUE_NUM); |
| | | bedQueueBO.setQueueNum(new AtomicInteger(0)); |
| | | priorityQueue.offer(bedQueueBO); |
| | | mapBedVsQueue.put(String.format("%09d%s", bedQueueBO.roomId, bedQueueBO.bedNo), bedQueueBO); |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | private void validatequeueExists(Integer id) { |
| | | if (queueMapper.selectById(id) == null) { |
| | | throw exception(QUEUE_NOT_EXISTS); |
| | |
| | | } |
| | | |
| | | /** |
| | | * 系统重启时,从DB同步队列数据到 工位优先队列 |
| | | * !!开诊期间,不能执行这个方法,否则会有 P0 问题 |
| | | * 1. 每天开诊前 从DB同步工位的患者队列数据到 工位优先队列 |
| | | * 2. 服务运维重启时 |
| | | */ |
| | | public void initQueue() { |
| | | public void initBedQueueAndSeqNumFromDB() { |
| | | priorityQueue.clear(); |
| | | mapBedVsQueue.clear(); |
| | | |
| | |
| | | } |
| | | |
| | | /** |
| | | * 这个逻辑 不需要了 |
| | | */ |
| | | public void reorderQueue() { |
| | | // 根据预约前后,从DB 获取 队列中 就诊准备中人员 列表 |
| | | List<Byte> queueStatusList = new ArrayList<>(); |
| | | queueStatusList.add(QueueStatusEnum.READY.getStatus()); |
| | | List<QueueDO> queueDOList = queueMapper.getOrderedQueue(queueStatusList); |
| | | if (queueDOList.isEmpty()) |
| | | return; |
| | | |
| | | AtomicInteger seqNum = new AtomicInteger(1); |
| | | queueDOList.forEach(item -> {item.setSeqNum(seqNum.getAndIncrement());}); |
| | | queueMapper.updateBatch(queueDOList); |
| | | |
| | | curSeqNum.set( seqNum.get() ); |
| | | } |
| | | |
| | | /** |
| | | * TODO 新开队列时,需要把排队中的人 转到 就诊准备 状态 |
| | | * 等到取下一个 排队中人员 的逻辑完成后,再回来不错 |
| | | */ |
| | | public void hurryup() { |
| | | if (0 == openingFlag.get()) |
| | | return; |
| | | |
| | | // 处理 过号-回来 的人 |
| | | for (BedQueueBO bedQueueBO : mapBedVsQueue.values()) { |
| | | while (bedQueueBO.queueNum.get() < bedQueueBO.maxQueueNum) { |
| | | // 查看 当前工位 是否有过号-回来的患者 |
| | | Integer updateNum = queueMapper.procPassedReturnPatient( |
| | | bedQueueBO.getRoomId(), |
| | | bedQueueBO.getRoomName(), |
| | | bedQueueBO.getBedNo(), |
| | | curSeqNum.get() + 1, |
| | | QueueStatusEnum.PASSED_RETURN.getStatus(), |
| | | QueueStatusEnum.READY.getStatus()); |
| | | if (null == updateNum || 0 == updateNum) |
| | | break; |
| | | |
| | | curSeqNum.getAndIncrement(); |
| | | |
| | | // 可能已经【并发的】在 nextPatient 中改变了值 |
| | | bedQueueBO.queueNum.incrementAndGet(); |
| | | |
| | | // 可能已经【并发的】在 nextPatient 中改变了优先队列顺序 |
| | | priorityQueue.remove(bedQueueBO); |
| | | priorityQueue.offer(bedQueueBO); |
| | | } |
| | | } |
| | | |
| | | // 处理 排队中 患者 |
| | | while (true) { |
| | | BedQueueBO bedQueueBO = priorityQueue.peek(); |
| | | if (null == bedQueueBO) |
| | |
| | | if (curQueueNum == bedQueueBO.maxQueueNum) |
| | | return; |
| | | |
| | | // 查看 是否有排队中的患者 |
| | | Integer updateNum = queueMapper.preemptPatient( |
| | | bedQueueBO.getRoomId(), |
| | | bedQueueBO.getRoomName(), |
| | | bedQueueBO.getBedNo(), |
| | | curSeqNum.get() + 1, |
| | | QueueStatusEnum.WAITING.getStatus(), |
| | | QueueStatusEnum.READY.getStatus()); |
| | | bedQueueBO.getRoomId(), |
| | | bedQueueBO.getRoomName(), |
| | | bedQueueBO.getBedNo(), |
| | | curSeqNum.get() + 1, |
| | | QueueStatusEnum.WAITING.getStatus(), |
| | | QueueStatusEnum.READY.getStatus()); |
| | | |
| | | // 没有抢到排队患者 |
| | | if (null == updateNum || 0 == updateNum) { |
| | |
| | | QueueDO queue = BeanUtils.toBean(queueSaveReqVO, QueueDO.class); |
| | | queueMapper.insert(queue); |
| | | |
| | | singleThreadExecutor.execute( () -> { |
| | | hurryup(); |
| | | }); |
| | | if (0 == openingFlag.get()) |
| | | return; |
| | | |
| | | startHurryUp(); |
| | | } |
| | | |
| | | private void nextPatient(Long roomId, String bedNo) { |
| | |
| | | priorityQueue.remove(bo); |
| | | priorityQueue.offer(bo); |
| | | |
| | | singleThreadExecutor.execute( () -> { |
| | | hurryup(); |
| | | }); |
| | | startHurryUp(); |
| | | } |
| | | |
| | | public void finishNextPatient(Long roomId, String bedNo) { |
| | |
| | | return patientStatisticVO; |
| | | } |
| | | |
| | | public void startBiz() { |
| | | if (1 == openingFlag.get()) |
| | | return; |
| | | |
| | | // 清除非当天的排队人员 |
| | | queueMapper.clearQueue(); |
| | | |
| | | initBedQueueAndSeqNumFromDB(); |
| | | |
| | | openingFlag.set(1); |
| | | hurryup(); |
| | | } |
| | | |
| | | public void closeBiz() { |
| | | openingFlag.set(0); |
| | | } |
| | | |
| | | @Override |
| | | public Integer recallPatient(Long roomId, String bedNo, String patId) { |
| | | Integer updateNum = queueMapper.passedPatientReturn(roomId, bedNo, patId, |
| | | QueueStatusEnum.PASSED.getStatus(), QueueStatusEnum.PASSED_RETURN.getStatus()); |
| | | startHurryUp(); |
| | | return updateNum; |
| | | } |
| | | |
| | | @Override |
| | | public Integer patientJump(String patId, Byte jumped) { |
| | | Integer updateNum = queueMapper.queueJump(patId, QueueStatusEnum.WAITING.getStatus(), jumped); |
| | | startHurryUp(); |
| | | return updateNum; |
| | | } |
| | | |
| | | private void startHurryUp() { |
| | | singleThreadExecutor.execute( () -> { |
| | | hurryup(); |
| | | }); |
| | | } |
| | | |
| | | } |
| | | |