You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
191 lines
6.7 KiB
191 lines
6.7 KiB
package com.iflytop.gd.app.service;
|
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
import com.iflytop.gd.app.core.CraftsContext;
|
|
import com.iflytop.gd.app.mapper.CraftsMapper;
|
|
import com.iflytop.gd.app.model.entity.Crafts;
|
|
import com.iflytop.gd.app.model.entity.Ores;
|
|
import com.iflytop.gd.app.model.vo.CraftStatusVO;
|
|
import com.iflytop.gd.app.model.vo.SetCraftsVO;
|
|
import com.iflytop.gd.common.enums.automaton.CraftEvents;
|
|
import com.iflytop.gd.common.enums.automaton.CraftStates;
|
|
import com.iflytop.gd.common.exception.AppException;
|
|
import com.iflytop.gd.common.result.ResultCode;
|
|
import jakarta.annotation.PostConstruct;
|
|
import lombok.RequiredArgsConstructor;
|
|
import org.springframework.statemachine.config.StateMachineFactory;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
import java.util.Arrays;
|
|
import java.util.List;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
import java.util.concurrent.ExecutorService;
|
|
import java.util.concurrent.Executors;
|
|
import java.util.concurrent.Future;
|
|
import java.util.stream.Collectors;
|
|
|
|
/**
|
|
* 工艺执行管理服务
|
|
*/
|
|
@Service
|
|
@RequiredArgsConstructor
|
|
public class CraftsService extends ServiceImpl<CraftsMapper, Crafts> {
|
|
private final StateMachineFactory<CraftStates, CraftEvents> stateMachineFactory;
|
|
private final WebSocketService webSocketService;
|
|
private final CraftsStepService craftsStepService;
|
|
private final OresService oresService;
|
|
private final ConcurrentHashMap<String, CraftsContext> contextMap = new ConcurrentHashMap<>();
|
|
private final ConcurrentHashMap<String, Future<?>> futureMap = new ConcurrentHashMap<>();
|
|
private ExecutorService executor;
|
|
|
|
@PostConstruct
|
|
public void init() {
|
|
this.executor = Executors.newCachedThreadPool();
|
|
}
|
|
|
|
/**
|
|
* 配置工艺
|
|
*/
|
|
public synchronized SetCraftsVO setCraft(Long craftId, String heatId) {
|
|
// 校验已有上下文状态,仅允许在 READY、STOPPED 或 FINISHED 状态下重置
|
|
CraftsContext existing = contextMap.get(heatId);
|
|
if (existing != null) {
|
|
CraftStates state = existing.getSm().getState().getId();
|
|
if (state == CraftStates.RUNNING || state == CraftStates.PAUSED) {
|
|
throw new AppException(ResultCode.CRAFT_RUNNING);
|
|
}
|
|
clearCraftContext(heatId);
|
|
}
|
|
Crafts craft = this.getById(craftId);
|
|
Ores ores = oresService.getById(craft.getOresId());
|
|
CraftsContext ctx = new CraftsContext(
|
|
heatId,
|
|
ores,
|
|
craft,
|
|
stateMachineFactory,
|
|
webSocketService,
|
|
craftsStepService
|
|
);
|
|
contextMap.put(heatId, ctx);
|
|
SetCraftsVO setCraftsVO = new SetCraftsVO();
|
|
setCraftsVO.setHeatId(heatId);
|
|
setCraftsVO.setCraftsName(craft.getName());
|
|
setCraftsVO.setCraftsId(craft.getId());
|
|
setCraftsVO.setOresName(ores.getName());
|
|
setCraftsVO.setOresId(ores.getId());
|
|
return setCraftsVO;
|
|
}
|
|
|
|
/**
|
|
* 启动执行工艺(需先调用 setCraft)
|
|
*/
|
|
public synchronized void startCrafts(String heatId) {
|
|
CraftsContext ctx = contextMap.get(heatId);
|
|
if (ctx == null) {
|
|
throw new AppException(ResultCode.CRAFT_CONTEXT_NULL);
|
|
}
|
|
if (futureMap.containsKey(heatId)) {
|
|
throw new AppException(ResultCode.CRAFT_RUNNING);
|
|
}
|
|
Future<?> future = executor.submit(ctx);
|
|
futureMap.put(heatId, future);
|
|
}
|
|
|
|
/**
|
|
* 暂停执行工艺
|
|
*/
|
|
public synchronized void pauseCrafts(String heatId) {
|
|
CraftsContext ctx = contextMap.get(heatId);
|
|
if (ctx == null) {
|
|
throw new AppException(ResultCode.CRAFT_CONTEXT_NULL);
|
|
}
|
|
ctx.pause();
|
|
}
|
|
|
|
/**
|
|
* 恢复执行工艺
|
|
*/
|
|
public synchronized void resumeCrafts(String heatId) {
|
|
CraftsContext ctx = contextMap.get(heatId);
|
|
if (ctx == null) {
|
|
throw new AppException(ResultCode.CRAFT_CONTEXT_NULL);
|
|
}
|
|
ctx.resume();
|
|
}
|
|
|
|
/**
|
|
* 停止执行工艺,不清除上下文
|
|
*/
|
|
public synchronized void stopCrafts(String heatId) {
|
|
CraftsContext ctx = contextMap.get(heatId);
|
|
Future<?> future = futureMap.remove(heatId);
|
|
if (ctx == null || future == null) {
|
|
throw new AppException(ResultCode.CRAFT_CONTEXT_NULL);
|
|
}
|
|
ctx.stop();
|
|
future.cancel(true);
|
|
}
|
|
|
|
/**
|
|
* 清理指定 heatId 的执行上下文和 Future
|
|
*/
|
|
public synchronized void clearCraftContext(String heatId) {
|
|
contextMap.remove(heatId);
|
|
Future<?> future = futureMap.remove(heatId);
|
|
if (future != null) future.cancel(true);
|
|
}
|
|
|
|
/**
|
|
* 查询指定 heatId 的执行状态
|
|
*/
|
|
public CraftStatusVO getStatus(String heatId) {
|
|
CraftsContext ctx = contextMap.get(heatId);
|
|
if (ctx == null) {
|
|
return null;
|
|
}
|
|
CraftStatusVO vo = new CraftStatusVO();
|
|
vo.setHeatId(heatId);
|
|
vo.setOresId(ctx.getOres().getId());
|
|
vo.setOresName(ctx.getOres().getName());
|
|
vo.setCraftsId(ctx.getCraft().getId());
|
|
vo.setCraftsName(ctx.getCraft().getName());
|
|
vo.setState(ctx.getSm().getState().getId());
|
|
vo.setCurrentIndex(ctx.getCurrentIndex());
|
|
vo.setSteps(ctx.getCraftsStepList());
|
|
return vo;
|
|
}
|
|
|
|
/**
|
|
* 查询所有正在执行的工艺状态
|
|
*/
|
|
public List<CraftStatusVO> getAllStatuses() {
|
|
return contextMap.entrySet().stream().map(entry -> {
|
|
String heatIdKey = entry.getKey();
|
|
CraftsContext ctx = entry.getValue();
|
|
CraftStatusVO vo = new CraftStatusVO();
|
|
vo.setHeatId(heatIdKey);
|
|
vo.setOresId(ctx.getOres().getId());
|
|
vo.setOresName(ctx.getOres().getName());
|
|
vo.setCraftsId(ctx.getCraft().getId());
|
|
vo.setCraftsName(ctx.getCraft().getName());
|
|
vo.setState(ctx.getSm().getState().getId());
|
|
vo.setCurrentIndex(ctx.getCurrentIndex());
|
|
vo.setSteps(ctx.getCraftsStepList());
|
|
return vo;
|
|
}).collect(Collectors.toList());
|
|
}
|
|
|
|
public List<Crafts> selectAllByOresId(Long oresId) {
|
|
return this.baseMapper.selectAllByOresId(oresId);
|
|
}
|
|
|
|
public Crafts findByName(String name) {
|
|
return this.getOne(new LambdaQueryWrapper<>(new Crafts()).eq(Crafts::getName, name));
|
|
}
|
|
|
|
public boolean deleteCrafts(String idsStr) {
|
|
List<Long> ids = Arrays.stream(idsStr.split(",")).map(Long::parseLong).collect(Collectors.toList());
|
|
return this.removeByIds(ids);
|
|
}
|
|
}
|