eight
2025-04-09 b1b98bdda00a94cada2035293d6bcad10bec0578
jh-module-ecg/jh-module-ecg-biz/src/main/java/cn/lihu/jh/module/ecg/service/queue/QueueServiceTxFunctions.java
@@ -69,10 +69,10 @@
    AtomicInteger curSeqNum = new AtomicInteger(0);
    // 维护 开放的工位
    ConcurrentHashMap<String, RoutingBedBO> mapOpeningBed = new ConcurrentHashMap<>();
    ConcurrentHashMap<String, BedBO> mapOpeningBed = new ConcurrentHashMap<>();
    // 装机工位..不进入分流队列
    Map<Integer, PriorityBlockingQueue<RoutingBedBO>> mapCheckTypeRoutingQueue = new HashMap();
    Map<Integer, PriorityBlockingQueue<BedBO>> mapCheckTypeRoutingQueue = new HashMap();
    
    Map<Integer, CheckTypeDO> mapCheckTypeVsReadyMax = null;
@@ -83,8 +83,8 @@
     * @return
     */
    public ErrorCode bedOpen(Long roomId, String roomName, String bedNo) {
        RoutingBedBO routingBedBO2 = mapOpeningBed.get( Utils.formatRoomBed(roomId, bedNo) );
        if (null != routingBedBO2) {
        BedBO bedBO2 = mapOpeningBed.get( Utils.formatRoomBed(roomId, bedNo) );
        if (null != bedBO2) {
            log.error("bedOpen mapBedVsQueue has existed. " + roomId + " " + bedNo);
            return QUEUE_BED_EXIST;
        }
@@ -105,23 +105,23 @@
        RoomDO roomDO = roomMapper.getRoom(roomId, bedNo);
        // 新增..工位队列
        RoutingBedBO routingBedBO = new RoutingBedBO();
        routingBedBO.setRoomId(roomId);
        routingBedBO.setRoomName(roomName);
        routingBedBO.setBedNo(bedNo);
        routingBedBO.setMaxReadyPatNum(getBedReadyMax(roomId, bedNo));
        routingBedBO.setReadyPatNum(new AtomicInteger(queueDOList.size()));
        routingBedBO.setStatus(BedStatusEnum.OPENING.getStatus());
        routingBedBO.setCheckTypes( roomDO.getCheckTypes() );
        routingBedBO.setOpType( roomDO.getOpType() );
        mapOpeningBed.put( Utils.formatRoomBed(roomId, bedNo), routingBedBO);
        BedBO bedBO = new BedBO();
        bedBO.setRoomId(roomId);
        bedBO.setRoomName(roomName);
        bedBO.setBedNo(bedNo);
        bedBO.setMaxReadyPatNum(getBedReadyMax(roomId, bedNo));
        bedBO.setReadyPatNum(new AtomicInteger(queueDOList.size()));
        bedBO.setStatus(BedStatusEnum.OPENING.getStatus());
        bedBO.setCheckTypes( roomDO.getCheckTypes() );
        bedBO.setOpType( roomDO.getOpType() );
        mapOpeningBed.put( Utils.formatRoomBed(roomId, bedNo), bedBO);
        return GlobalErrorCodeConstants.SUCCESS;
    }
    public ErrorCode bedClose(Long roomId, String bedNo) {
        RoutingBedBO routingBedBO = mapOpeningBed.get( Utils.formatRoomBed(roomId, bedNo) );
        if (null == routingBedBO) {
        BedBO bedBO = mapOpeningBed.get( Utils.formatRoomBed(roomId, bedNo) );
        if (null == bedBO) {
            log.error("bedClose mapBedVsQueue DONOT existed. " + roomId + " " + bedNo);
            return QUEUE_BED_NOT_EXIST;
        }
@@ -154,13 +154,13 @@
        }
        mapOpeningBed.remove( Utils.formatRoomBed(roomId, bedNo) );
        removeRoutingQueue(routingBedBO);
        removeRoutingQueue(bedBO);
        return GlobalErrorCodeConstants.SUCCESS;
    }
    public ErrorCode bedDoctorPause(Long roomId, String bedNo, Long docId, String docName) {
        RoutingBedBO routingBedBO = mapOpeningBed.get( Utils.formatRoomBed(roomId, bedNo) );
        if (null == routingBedBO) {
        BedBO bedBO = mapOpeningBed.get( Utils.formatRoomBed(roomId, bedNo) );
        if (null == bedBO) {
            log.error("bedDoctorPause mapBedVsQueue DONOT existed. " + roomId + " " + bedNo);
            return QUEUE_BED_NOT_EXIST;
        }
@@ -174,14 +174,14 @@
            return ROOM_INVALID_STATUS;
        }
        routingBedBO.setStatus(BedStatusEnum.DOCTOR_PAUSE.getStatus());
        removeRoutingQueue(routingBedBO);
        bedBO.setStatus(BedStatusEnum.DOCTOR_PAUSE.getStatus());
        removeRoutingQueue(bedBO);
        return GlobalErrorCodeConstants.SUCCESS;
    }
    public ErrorCode bedDoctorResume(Long roomId, String bedNo, Long docId, String docName) {
        RoutingBedBO routingBedBO = mapOpeningBed.get( Utils.formatRoomBed(roomId, bedNo) );
        if (null == routingBedBO || !routingBedBO.getStatus().equals(BedStatusEnum.DOCTOR_PAUSE.getStatus())) {
        BedBO bedBO = mapOpeningBed.get( Utils.formatRoomBed(roomId, bedNo) );
        if (null == bedBO || !bedBO.getStatus().equals(BedStatusEnum.DOCTOR_PAUSE.getStatus())) {
            log.error("bedDoctorResume mapBedVsQueue DONOT existed OR NOT Paused. " + roomId + " " + bedNo);
            return QUEUE_BED_NOT_EXIST;
        }
@@ -196,14 +196,14 @@
            return ROOM_INVALID_STATUS;
        }
        routingBedBO.setStatus(BedStatusEnum.DOCTOR_ON.getStatus());
        addRoutingQueue(routingBedBO);
        bedBO.setStatus(BedStatusEnum.DOCTOR_ON.getStatus());
        addRoutingQueue(bedBO);
        return GlobalErrorCodeConstants.SUCCESS;
    }
    public ErrorCode bedDoctorOn(Long roomId, String bedNo, Long docId, String docName) {
        RoutingBedBO routingBedBO = mapOpeningBed.get( Utils.formatRoomBed(roomId, bedNo) );
        if (null == routingBedBO) {
        BedBO bedBO = mapOpeningBed.get( Utils.formatRoomBed(roomId, bedNo) );
        if (null == bedBO) {
            log.error("bedDoctorOn mapBedVsQueue DONOT existed. " + roomId + " " + bedNo);
            return QUEUE_BED_NOT_EXIST;
        }
@@ -217,14 +217,14 @@
            return ROOM_INVALID_STATUS;
        }
        routingBedBO.setStatus(BedStatusEnum.DOCTOR_ON.getStatus());
        addRoutingQueue(routingBedBO);
        bedBO.setStatus(BedStatusEnum.DOCTOR_ON.getStatus());
        addRoutingQueue(bedBO);
        return GlobalErrorCodeConstants.SUCCESS;
    }
    public ErrorCode bedDoctorOff(Long roomId, String bedNo, Long docId, String docName) {
        RoutingBedBO routingBedBO = mapOpeningBed.get( Utils.formatRoomBed( roomId, bedNo ) );
        if (null == routingBedBO) {
        BedBO bedBO = mapOpeningBed.get( Utils.formatRoomBed( roomId, bedNo ) );
        if (null == bedBO) {
            log.error("bedDoctorOff mapBedVsQueue DONOT existed. " + roomId + " " + bedNo);
            return QUEUE_BED_NOT_EXIST;
        }
@@ -239,9 +239,9 @@
            return ROOM_INVALID_STATUS;
        }
        removeRoutingQueue(routingBedBO);
        removeRoutingQueue(bedBO);
        routingBedBO.setStatus(BedStatusEnum.OPENING.getStatus());
        bedBO.setStatus(BedStatusEnum.OPENING.getStatus());
        return GlobalErrorCodeConstants.SUCCESS;
    }
@@ -278,7 +278,7 @@
        queueMapper.updateById( firstReadyQueueItem );
        // 分流队列中 该工位 候诊中中人的数量 减一
        RoutingBedBO bo = mapOpeningBed.get( Utils.formatRoomBed( roomId, bedNo ) );
        BedBO bo = mapOpeningBed.get( Utils.formatRoomBed( roomId, bedNo ) );
        bo.readyPatNum.getAndDecrement(); // 可能已经【并发的】在 hurry-up 中改变了值
        refreshRoutingQueue(bo);
@@ -332,14 +332,14 @@
        bedStatusEnumList.add(BedStatusEnum.DOCTOR_ON);
        bedStatusEnumList.add(BedStatusEnum.DOCTOR_PAUSE);
        List<RoomDO> roomDOList = roomMapper.simpleRoomList(bedStatusEnumList);
        List<RoutingBedBO> routingBedBOList = roomDOList.stream().map(item -> BeanUtils.toBean(item, RoutingBedBO.class)).toList();
        List<BedBO> bedBOList = roomDOList.stream().map(item -> BeanUtils.toBean(item, BedBO.class)).toList();
        // 从DB 获取 队列中 【候诊中】人员统计 列表
        List<Integer> queueStatusList = new ArrayList<>();
        queueStatusList.add(QueueStatusEnum.READY.getStatus());
        List<QueueStatisticDO> queueStatisticDOList = queueMapper.queueStatistic(queueStatusList);
        routingBedBOList.forEach(item -> {
        bedBOList.forEach(item -> {
            item.setMaxReadyPatNum( getBedReadyMax(item.roomId, item.bedNo) );
            Optional<QueueStatisticDO> queueStatisticDOOptional = queueStatisticDOList.stream().filter(it->it.getRoomId()==item.roomId && it.getBedNo().equals(item.getBedNo())).findFirst();
            int queueNum = queueStatisticDOOptional.isPresent() ? queueStatisticDOOptional.get().getTotalInStatus() : 0;
@@ -388,15 +388,15 @@
        if (0 == openingFlag.get())
            return;
        RoutingBedBO routingBedBO = getBedQueueBO(roomId, bedNo);
        BedBO bedBO = getBedQueueBO(roomId, bedNo);
        // 处理 过号-回来 的人
        while (routingBedBO.readyPatNum.get() < routingBedBO.maxReadyPatNum) {
        while (bedBO.readyPatNum.get() < bedBO.maxReadyPatNum) {
            // 查看 当前工位 是否有过号-回来的患者
            Integer updateNum = queueMapper.queueRecalledPatient(
                    routingBedBO.getRoomId(),
                    routingBedBO.getRoomName(),
                    routingBedBO.getBedNo(),
                    bedBO.getRoomId(),
                    bedBO.getRoomName(),
                    bedBO.getBedNo(),
                    curSeqNum.get() + 1,  // 过号回来,排到当前的下一位
                    QueueStatusEnum.RECALLED.getStatus(), // 不需要处理 [安装召回], 原因: 安装工位 不进入分流队列
                    QueueStatusEnum.READY.getStatus());
@@ -414,14 +414,14 @@
            curSeqNum.getAndIncrement();
            // 可能已经【并发的】在 nextPatient 中改变了值
            routingBedBO.readyPatNum.incrementAndGet();
            bedBO.readyPatNum.incrementAndGet();
            // 可能已经【并发的】在 nextPatient 中改变了分流队列顺序
            refreshRoutingQueue(routingBedBO);
            refreshRoutingQueue(bedBO);
        }
        // 处理 排队中 患者
        hurryupOneBedCheckTypeList(routingBedBO);
        hurryupOneBedCheckTypeList(bedBO);
    }
    /**
@@ -433,31 +433,31 @@
     */
    public void hurryupOneCheckType(Integer checkType) {
        PriorityBlockingQueue<RoutingBedBO> routingQueue = mapCheckTypeRoutingQueue.get(checkType);
        PriorityBlockingQueue<BedBO> routingQueue = mapCheckTypeRoutingQueue.get(checkType);
        if (null == routingQueue)
            return;
        while (true) {
            RoutingBedBO routingBedBO = routingQueue.peek();
            if (null == routingBedBO)
            BedBO bedBO = routingQueue.peek();
            if (null == bedBO)
                return;
            int curQueueNum = routingBedBO.readyPatNum.get();
            if (curQueueNum > routingBedBO.maxReadyPatNum)
            int curQueueNum = bedBO.readyPatNum.get();
            if (curQueueNum > bedBO.maxReadyPatNum)
                throw new RuntimeException("hurryupOneCheckType: exceed max queue number!");
            if (curQueueNum == routingBedBO.maxReadyPatNum)
            if (curQueueNum == bedBO.maxReadyPatNum)
                return;
            // 查看 是否有排队中的患者
            Integer updateNum = queueMapper.preemptWaitingPatientWithBedCheckTypes(
                    routingBedBO.getRoomId(),
                    routingBedBO.getRoomName(),
                    routingBedBO.getBedNo(),
                    bedBO.getRoomId(),
                    bedBO.getRoomName(),
                    bedBO.getBedNo(),
                    curSeqNum.get() + 1,
                    QueueStatusEnum.WAITING.getStatus(),
                    QueueStatusEnum.READY.getStatus(),
                    routingBedBO.checkTypes);  //关键点 关键点 关键点 checkType
                    bedBO.checkTypes);  //关键点 关键点 关键点 checkType
            // 没有抢到排队患者
            if (null == updateNum || 0 == updateNum) {
@@ -475,10 +475,10 @@
            curSeqNum.getAndIncrement();
            // 可能已经【并发的】在 nextPatient 中改变了值
            routingBedBO.readyPatNum.incrementAndGet();
            bedBO.readyPatNum.incrementAndGet();
            // 可能已经【并发的】在 nextPatient 中改变了分流队列顺序
            refreshRoutingQueue(routingBedBO);
            refreshRoutingQueue(bedBO);
        }
    }
@@ -499,7 +499,7 @@
        return mapCheckTypeVsReadyMax.get( checkType );
    }
    public RoutingBedBO getBedQueueBO(Long roomId, String bedNo) {
    public BedBO getBedQueueBO(Long roomId, String bedNo) {
        return mapOpeningBed.get( Utils.formatRoomBed(roomId, bedNo) );
    }
@@ -517,17 +517,17 @@
        log.info(" opening " + openingFlag.get() + " " + monitorInfoVO.getOpeningBedNum() + " " + monitorInfoVO.getDocBedNum() + " " + monitorInfoVO.getCheckTypeBedInfo().toString() );
    }
    private void hurryupOneBedCheckTypeList(RoutingBedBO routingBedBO) {
        while (routingBedBO.readyPatNum.get() < routingBedBO.maxReadyPatNum) {
    private void hurryupOneBedCheckTypeList(BedBO bedBO) {
        while (bedBO.readyPatNum.get() < bedBO.maxReadyPatNum) {
            // 抢占 是否有排队中的患者
            Integer updateNum = queueMapper.preemptWaitingPatientWithBedCheckTypes(
                    routingBedBO.getRoomId(),
                    routingBedBO.getRoomName(),
                    routingBedBO.getBedNo(),
                    bedBO.getRoomId(),
                    bedBO.getRoomName(),
                    bedBO.getBedNo(),
                    curSeqNum.get() + 1,
                    QueueStatusEnum.WAITING.getStatus(),
                    QueueStatusEnum.READY.getStatus(),
                    routingBedBO.checkTypes);
                    bedBO.checkTypes);
            // 没有抢到排队患者
            if (null == updateNum || 0 == updateNum) {
@@ -544,11 +544,11 @@
            curSeqNum.getAndIncrement();
            routingBedBO.readyPatNum.incrementAndGet();
            bedBO.readyPatNum.incrementAndGet();
        }
        // 改变了分流队列顺序
        refreshRoutingQueue(routingBedBO);
        refreshRoutingQueue(bedBO);
    }
    /**
@@ -594,51 +594,51 @@
        return ret;
    }
    private void addRoutingQueue(RoutingBedBO routingBedBO) {
    private void addRoutingQueue(BedBO bedBO) {
        // 装机工位 不进 分流队列,不接收 【排队中】患者分流
        if (BedOpTypeEnum.OP_INSTALL.getOpType() == routingBedBO.getOpType())
        if (BedOpTypeEnum.OP_INSTALL.getOpType() == bedBO.getOpType())
            return;
        Integer[] checkTypes = routingBedBO.getCheckTypes();
        Integer[] checkTypes = bedBO.getCheckTypes();
        Arrays.stream(checkTypes).forEach(checkType -> {
            CheckTypeDO checkTypeDO = mapCheckTypeVsReadyMax.get(checkType);
            PriorityBlockingQueue<RoutingBedBO> routingQueue = mapCheckTypeRoutingQueue.get(checkType);
            PriorityBlockingQueue<BedBO> routingQueue = mapCheckTypeRoutingQueue.get(checkType);
            if (null == routingQueue) {
                routingQueue = new PriorityBlockingQueue<RoutingBedBO>();
                routingQueue = new PriorityBlockingQueue<BedBO>();
                mapCheckTypeRoutingQueue.put( checkType, routingQueue );
            }
            if (!routingQueue.contains(routingBedBO)) {
                routingQueue.offer(routingBedBO);
            if (!routingQueue.contains(bedBO)) {
                routingQueue.offer(bedBO);
            } else {
                log.error("bedDoctorResume routingQueue still exist!. " + routingBedBO.getRoomId() + " " + routingBedBO.getBedNo());
                log.error("bedDoctorResume routingQueue still exist!. " + bedBO.getRoomId() + " " + bedBO.getBedNo());
            }
        });
    }
    private void removeRoutingQueue(RoutingBedBO routingBedBO) {
    private void removeRoutingQueue(BedBO bedBO) {
        // 装机工位 不进 分流队列,不接收 【排队中】患者分流
        if (BedOpTypeEnum.OP_INSTALL.getOpType() == routingBedBO.getOpType())
        if (BedOpTypeEnum.OP_INSTALL.getOpType() == bedBO.getOpType())
            return;
        Integer[] checkTypes = routingBedBO.getCheckTypes();
        Integer[] checkTypes = bedBO.getCheckTypes();
        Arrays.stream(checkTypes).forEach(checkType -> {
            PriorityBlockingQueue<RoutingBedBO> routingQueue = mapCheckTypeRoutingQueue.get(checkType);
            PriorityBlockingQueue<BedBO> routingQueue = mapCheckTypeRoutingQueue.get(checkType);
            if (null != routingQueue)
                routingQueue.remove(routingBedBO);
                routingQueue.remove(bedBO);
        });
    }
    private void refreshRoutingQueue(RoutingBedBO routingBedBO) {
    private void refreshRoutingQueue(BedBO bedBO) {
        // 装机工位 不进 分流队列,不接收 【排队中】患者分流
        if (BedOpTypeEnum.OP_INSTALL.getOpType() == routingBedBO.getOpType())
        if (BedOpTypeEnum.OP_INSTALL.getOpType() == bedBO.getOpType())
            return;
        Integer[] checkTypes = routingBedBO.getCheckTypes();
        Integer[] checkTypes = bedBO.getCheckTypes();
        Arrays.stream(checkTypes).forEach(checkType -> {
            PriorityBlockingQueue<RoutingBedBO> routingQueue = mapCheckTypeRoutingQueue.get(checkType);
            routingQueue.remove(routingBedBO);
            routingQueue.offer(routingBedBO);
            PriorityBlockingQueue<BedBO> routingQueue = mapCheckTypeRoutingQueue.get(checkType);
            routingQueue.remove(bedBO);
            routingQueue.offer(bedBO);
        });
    }
@@ -689,7 +689,7 @@
        });
        // 接收..排队中患者..的分流队列
        HashSet<RoutingBedBO> hashSetOperatingBedQueue = new HashSet<>();
        HashSet<BedBO> hashSetOperatingBedQueue = new HashSet<>();
        mapCheckTypeRoutingQueue.values().forEach(routingQueue->{
            routingQueue.stream().forEach(bedQueueBO -> hashSetOperatingBedQueue.add(bedQueueBO));
        });