package com.glxp.api.task; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.thread.ThreadUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; import com.glxp.api.constant.ThirdSysConstant; import com.glxp.api.dao.schedule.ScheduledDao; import com.glxp.api.dao.system.SyncDataSetDao; import com.glxp.api.dao.thrsys.ThrSystemDetailDao; import com.glxp.api.entity.system.ScheduledEntity; import com.glxp.api.entity.thrsys.ThrSystemDetailEntity; import com.glxp.api.req.basic.GetSickRequest; import com.glxp.api.req.system.ScheduledRequest; import com.glxp.api.res.thrsys.ThirdSysInterfaceExecuteVo; import com.glxp.api.service.basic.BasicSkSickerService; import com.glxp.api.service.inout.IoOrderService; import com.glxp.api.service.thrsys.*; import com.glxp.api.util.RedisUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.exception.ExceptionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.SchedulingConfigurer; import org.springframework.scheduling.config.ScheduledTaskRegistrar; import org.springframework.scheduling.support.CronTrigger; import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; @Component @EnableScheduling @Slf4j public class SyncThirdSysTask implements SchedulingConfigurer { /** * redis key 前缀 */ private static final Map> keyMap = new ConcurrentHashMap<>(5); private volatile ExecutorService executor; @Resource private RedisUtil redisUtil; @Resource private ThrSystemDetailDao thrSystemDetailDao; @Resource private ThrInvWarehouseService thrInvWarehouseService; @Resource private ThrCorpService thrCorpService; @Resource private ThrProductsService thrProductsService; @Resource private IThrBusTypeOriginService thrBusTypeOriginService; @Resource private IoOrderService orderService; @Resource ThrOrderService thrOrderService; final Logger logger = LoggerFactory.getLogger(SyncHeartTask.class); @Resource protected ScheduledDao scheduledDao; @Override public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) { scheduledTaskRegistrar.addTriggerTask(() -> process(), triggerContext -> { ScheduledRequest scheduledRequest = new ScheduledRequest(); scheduledRequest.setCronName("dlThrSysHeartTask"); ScheduledEntity scheduledEntity = scheduledDao.findScheduled(scheduledRequest); if (scheduledEntity != null) { String cron = scheduledEntity.getCron(); if (cron.isEmpty()) { logger.error("cron is null"); } return new CronTrigger(cron).nextExecutionTime(triggerContext); } else return null; }); } private ExecutorService getExecutor() { if (null == executor) { synchronized (this) { log.info("初始化第三方系统接口执行线程池"); executor = ThreadUtil.newExecutor(10, 100, Integer.MAX_VALUE); } } return executor; } private void process() { log.info("开始扫描自动执行的第三方接口列表"); List list = thrSystemDetailDao.selectAutoExecuteList(); if (CollUtil.isNotEmpty(list)) { log.info("本次查询到的接口列表数量:{}", list.size()); list.parallelStream().forEach(thrSystemDetailEntity -> { switch (thrSystemDetailEntity.getKey()) { case ThirdSysConstant.WAREHOUSE_QUERY_URL: //下载第三方仓库信息 downloadThrInv(thrSystemDetailEntity); break; case ThirdSysConstant.CORP_URL: //下载往来单位信息 downloadThrCorp(thrSystemDetailEntity); break; case ThirdSysConstant.PI_QUERY_URL: //下载第三方产品信息 downloadThrPi(thrSystemDetailEntity); break; case ThirdSysConstant.BUS_TYPE_QUERY_URL: //下载第三方单据类型 downloadThrBusType(thrSystemDetailEntity); break; case ThirdSysConstant.ORDER_SUBMIT_URL: //提交单据 submitOrder(thrSystemDetailEntity); break; case ThirdSysConstant.ORDER_QUERY_URL: downloadThrOrder(thrSystemDetailEntity); break; case ThirdSysConstant.PI_SUBMIT_URL: //提交产品信息 postRelProduct(thrSystemDetailEntity); break; case ThirdSysConstant.SICKER_QUERY_URL: //下载患者信息 downloadSicker(thrSystemDetailEntity); break; default: //其他接口暂不处理 break; } }); } else { log.info("未配置自动执行的第三方接口列表"); } } /** * 提交单据到第三方系统 * * @param thrSystemDetailEntity */ private void submitOrder(ThrSystemDetailEntity thrSystemDetailEntity) { //校验任务并更新redis数据执行标识 if (verifyTask(thrSystemDetailEntity)) { getExecutor().submit(() -> { log.info("开始提交单据到第三方系统"); try { orderService.submitOrderToThrSys(thrSystemDetailEntity); } catch (Exception e) { log.error("提交单据到第三方系统异常", ExceptionUtils.getStackTrace(e)); } finally { updateTask(getTaskKey(thrSystemDetailEntity)); } log.info("提交单据到第三方系统完成"); }); } } /** * 下载第三方单据类型 * * @param thrSystemDetailEntity */ private void downloadThrBusType(ThrSystemDetailEntity thrSystemDetailEntity) { //校验任务并更新redis数据执行标识 if (verifyTask(thrSystemDetailEntity)) { getExecutor().submit(() -> { log.info("开始下载第三方单据类型"); try { thrBusTypeOriginService.downloadThrBusType(thrSystemDetailEntity); } catch (Exception e) { log.error("下载第三方单据类型异常", ExceptionUtils.getStackTrace(e)); } finally { updateTask(getTaskKey(thrSystemDetailEntity)); } log.info("第三方单据类型下载完成"); }); } } /** * 下载第三方产品信息 * * @param thrSystemDetailEntity */ private void downloadThrPi(ThrSystemDetailEntity thrSystemDetailEntity) { //校验任务并更新redis数据执行标识 if (verifyTask(thrSystemDetailEntity)) { getExecutor().submit(() -> { log.info("开始下载第三方产品信息"); try { thrProductsService.downloadThrPi(thrSystemDetailEntity); } catch (Exception e) { log.error("下载第三方产品信息异常", ExceptionUtils.getStackTrace(e)); } finally { updateTask(getTaskKey(thrSystemDetailEntity)); } log.info("第三方产品信息下载完成"); }); } } /** * 下载第三方往来单位 * * @param thrSystemDetailEntity */ private void downloadThrCorp(ThrSystemDetailEntity thrSystemDetailEntity) { //校验任务并更新redis数据执行标识 if (verifyTask(thrSystemDetailEntity)) { getExecutor().submit(() -> { log.info("开始下载第三方往来单位信息"); try { thrCorpService.downloadThrCorp(thrSystemDetailEntity); } catch (Exception e) { log.error("下载第三方往来单位异常", ExceptionUtils.getStackTrace(e)); } finally { updateTask(getTaskKey(thrSystemDetailEntity)); } log.info("第三方往来单位信息下载完成"); }); } } /** * 下载第三方系统仓库 * * @param thrSystemDetailEntity */ private void downloadThrInv(ThrSystemDetailEntity thrSystemDetailEntity) { //校验任务并更新redis数据执行标识 if (verifyTask(thrSystemDetailEntity)) { getExecutor().submit(() -> { log.info("开始下载第三方仓库信息"); try { thrInvWarehouseService.downloadThrInv(thrSystemDetailEntity); } catch (Exception e) { log.error("下载第三方仓库信息异常", ExceptionUtils.getStackTrace(e)); } finally { //保证任务标识一定会被修改回去 updateTask(getTaskKey(thrSystemDetailEntity)); } log.info("第三方仓库信息下载完成"); }); } } /** * 下载第三方业务单据 * * @param thrSystemDetailEntity */ private void downloadThrOrder(ThrSystemDetailEntity thrSystemDetailEntity) { //校验任务并更新redis数据执行标识 if (verifyTask(thrSystemDetailEntity)) { getExecutor().submit(() -> { log.info("开始下载第三方业务单据"); try { thrOrderService.downloadThrOrder(thrSystemDetailEntity); } catch (Exception e) { log.error("下载第三方业务单据", ExceptionUtils.getStackTrace(e)); } finally { updateTask(getTaskKey(thrSystemDetailEntity)); } log.info("第三方业务单据下载完成"); }); } } /** * 上传已关联产品信息 * * @param thrSystemDetailEntity */ private void postRelProduct(ThrSystemDetailEntity thrSystemDetailEntity) { //校验任务并更新redis数据执行标识 if (verifyTask(thrSystemDetailEntity)) { getExecutor().submit(() -> { log.info("开始上传关联第三方产品信息"); try { thrProductsService.uploadThrProduct(thrSystemDetailEntity); } catch (Exception e) { log.error("开始上传关联第三方产品信息", ExceptionUtils.getStackTrace(e)); } finally { updateTask(getTaskKey(thrSystemDetailEntity)); } log.info("开始上传关联第三方产品信息完成"); }); } } @Resource BasicSkSickerService skSickerService; /** * 下载患者信息 */ private void downloadSicker(ThrSystemDetailEntity thrSystemDetailEntity) { //校验任务并更新redis数据执行标识 if (verifyTask(thrSystemDetailEntity)) { getExecutor().submit(() -> { log.info("开始下载患者信息"); try { skSickerService.downloadSicker(new GetSickRequest(), null); } catch (Exception e) { log.error("开始下载患者信息", ExceptionUtils.getStackTrace(e)); } finally { updateTask(getTaskKey(thrSystemDetailEntity)); } log.info("开始下载患者信息完成"); }); } } /** * 更新任务状态为已完成 * * @param taskKey */ private void updateTask(String taskKey) { ThirdSysInterfaceExecuteVo vo = getLastResult(taskKey); vo.setFinished(true); vo.setNextTime(new Date().getTime()); redisUtil.set(taskKey, vo); } /** * 校验当前任务是否可以执行 * * @param thrSystemDetailEntity * @return */ private boolean verifyTask(ThrSystemDetailEntity thrSystemDetailEntity) { String taskKey = getTaskKey(thrSystemDetailEntity); ThirdSysInterfaceExecuteVo vo = getLastResult(taskKey); if (null != vo && !vo.isFinished()) { log.info(vo.getKey() + "有任务尚未执行完成,当前任务key:{}", taskKey); return false; } long curTime = new Date().getTime(); if (vo != null) { long lastTime = vo.getNextTime(); long timeInterval = Long.parseLong(thrSystemDetailEntity.getTime().intValue() + "") * 1000 * 60; if (curTime - lastTime < timeInterval) { log.info("定时任务时间未到---" + taskKey); return false; } else { return true; } } else { vo = Optional.ofNullable(vo).orElse(new ThirdSysInterfaceExecuteVo()); vo.setKey(taskKey); vo.setNextTime(curTime); vo.setFinished(false); redisUtil.set(taskKey, vo); } return true; } /** * 获取上一次执行结果 * * @param taskKey * @return */ private ThirdSysInterfaceExecuteVo getLastResult(String taskKey) { String json = redisUtil.getJSON(taskKey); return StrUtil.isBlank(json) ? null : JSONUtil.toBean(json, ThirdSysInterfaceExecuteVo.class); } /** * 拼接redis Key * * @param thrSystemDetailEntity * @return */ private String getTaskKey(ThrSystemDetailEntity thrSystemDetailEntity) { String key = ""; Map keys = keyMap.get(thrSystemDetailEntity.getThirdSysFk()); if (CollUtil.isEmpty(keys)) { Map map = new HashMap<>(1); key = "thirdI:" + thrSystemDetailEntity.getThirdSysFk() + ":" + thrSystemDetailEntity.getKey(); map.put(thrSystemDetailEntity.getKey(), key); keyMap.put(thrSystemDetailEntity.getThirdSysFk(), map); } else { key = keys.get(thrSystemDetailEntity.getKey()); if (StrUtil.isBlank(key)) { key = "thirdI:" + thrSystemDetailEntity.getThirdSysFk() + ":" + thrSystemDetailEntity.getKey(); Map map = new HashMap<>(1); map.put(thrSystemDetailEntity.getKey(), key); keyMap.put(thrSystemDetailEntity.getThirdSysFk(), map); } } return key; } }