package com.zy.acs.manager.core.scheduler; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.zy.acs.manager.core.domain.AgvTaskDto; import com.zy.acs.manager.core.service.MainLockWrapService; import com.zy.acs.manager.core.service.MainService; import com.zy.acs.manager.core.service.TrafficService; import com.zy.acs.manager.manager.entity.Bus; import com.zy.acs.manager.manager.entity.Segment; import com.zy.acs.manager.manager.entity.Task; import com.zy.acs.manager.manager.enums.ActionStsType; import com.zy.acs.manager.manager.enums.BusStsType; import com.zy.acs.manager.manager.enums.SegmentStateType; import com.zy.acs.manager.manager.enums.TaskStsType; import com.zy.acs.manager.manager.service.*; import com.zy.acs.manager.system.service.ConfigService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.event.EventListener; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import javax.annotation.PreDestroy; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; /** * to judgement agv idle status when generate action !!! * Created by vincent on 2023/6/18 */ @Slf4j @Component public class KernelScheduler { public static int CORE_SCAN_FREQUENCY_MILLISECOND = 15; private static final int LOCK_TIMEOUT = 5; private final ReentrantLock lock = new ReentrantLock(Boolean.TRUE); private Thread trafficCalcThread; private Thread actionPublicThread; @Autowired private AgvService agvService; @Autowired private BusService busService; @Autowired private TaskService taskService; @Autowired private MainService mainService; @Autowired private MainLockWrapService mainLockWrapService; @Autowired private ActionService actionService; @Autowired private SegmentService segmentService; @Autowired private TrafficService trafficService; @Autowired private ConfigService configService; @Autowired private LocService locService; @Autowired private AgvModelService agvModelService; @Scheduled(cron = "0/1 * * * * ? ") private void startupBus() throws InterruptedException { // if (!configService.getVal("TaskAssignMode", Boolean.class)) { return; } if (!this.lock.tryLock(LOCK_TIMEOUT, TimeUnit.SECONDS)) { return; } List busList = busService.selectInSts(BusStsType.RECEIVE, BusStsType.PROGRESS); for (Bus bus : busList) { mainService.allocateTask(bus); } this.lock.unlock(); } @Scheduled(cron = "0/1 * * * * ? ") private void calculateSeg() throws InterruptedException { if (!this.lock.tryLock(LOCK_TIMEOUT, TimeUnit.SECONDS)) { return; } List taskList = taskService.selectBySts(TaskStsType.WAITING); List taskDtoList = new ArrayList<>(); for (Task task : taskList) { AgvTaskDto taskDto = new AgvTaskDto(task.getAgvId(), task); if (AgvTaskDto.has(taskDtoList, taskDto)) { AgvTaskDto dto = AgvTaskDto.find(taskDtoList, taskDto); assert dto != null; dto.getTaskList().add(task); } else { taskDtoList.add(taskDto); } } for (AgvTaskDto dto : taskDtoList) { mainLockWrapService.buildMajorTask(dto.getAgvId(), dto.getTaskList()); } this.lock.unlock(); } @EventListener(ApplicationReadyEvent.class) public void init() { try { Thread.sleep(1200); } catch (InterruptedException ignore) {} // traffic calculate this.trafficCalcThread = new Thread(() -> { while (!Thread.currentThread().isInterrupted()) { try { Thread.sleep(CORE_SCAN_FREQUENCY_MILLISECOND); List segments = segmentService.list(new LambdaQueryWrapper() .eq(Segment::getState, SegmentStateType.WAITING.toString()) ); for (Segment segment : segments) { long startTime = System.currentTimeMillis(); trafficService.trigger(segment); // log.info("traffic calculation spend {} ms", System.currentTimeMillis() - startTime); } } catch (Exception e) { log.error("KernelScheduler.trafficCalcThread fail", e); } } }); this.trafficCalcThread.start(); // public action this.actionPublicThread = new Thread(() -> { while (!Thread.currentThread().isInterrupted()) { try { Thread.sleep(CORE_SCAN_FREQUENCY_MILLISECOND); List actionGroupIds = actionService.selectGroupNo(ActionStsType.PREPARE); for (String actionGroupId : actionGroupIds) { mainService.publishAction(actionGroupId); } } catch (Exception e) { log.error("KernelScheduler.actionPublicThread fail", e); } } }); this.actionPublicThread.start(); } // patch ---------------------------------------------------------------------------------------------- @Scheduled(cron = "0/3 * * * * ? ") private void busFinishPatch(){ List busList = busService.selectBySts(BusStsType.PROGRESS); for (Bus bus : busList) { boolean finish = true; List taskList = taskService.list(new LambdaQueryWrapper().eq(Task::getBusId, bus.getId())); for (Task task : taskList) { if (!task.getTaskSts().equals(TaskStsType.COMPLETE.val())) { finish = false; break; } } if (finish) { bus.setBusSts(BusStsType.FINISH.val()); bus.setEndTime(new Date()); bus.setUpdateTime(new Date()); if (!busService.updateById(bus)) { log.error("Bus [{}] 更新失败 !!!", bus.getUuid()); } } long cancelNum = taskList.stream().filter(task -> TaskStsType.CANCEL.val() == task.getTaskSts()).count(); if (cancelNum == taskList.size()) { bus.setBusSts(BusStsType.CANCEL.val()); bus.setUpdateTime(new Date()); if (!busService.updateById(bus)) { log.error("Bus [{}] 更新失败 !!!", bus.getUuid()); } } } } @PreDestroy public void shutDown(){ if (this.trafficCalcThread != null) { this.trafficCalcThread .interrupt(); } if (this.actionPublicThread != null) { this.actionPublicThread .interrupt(); } } }