@Component
public class ReplenishIncompleteEmrScheduler extends RestSdkSupport {
private static final Logger logger = LoggerFactory.getLogger(ReplenishIncompleteEmrScheduler.class);
@Autowired
ElectronicMedicalRecordService electronicMedicalRecordService;
@Autowired
ConnectService connectService;
@Autowired
EmrParserAdapter emrParserAdapter;
private String emrUrl;
@Value("${server.port}")
private String port;
@Autowired
private EmrIntegrityRecordsService emrIntegrityRecordsService;
//是否更新电子病历数据
private static final String BackFill_YES = "1";
// 定时任务执行器
private final ScheduledExecutorService scheduledExecutorService
= Executors.newScheduledThreadPool(1, new NamedThreadFactory("补全定时器", true));
private ScheduledFuture<?> sendFuture = null;
//调用间隔10分钟
private static final int monitorInterval = 10 * 1;
//启动间隔1分钟
private static final int beginMonitorInterval = 1;
//未完成标识
private static final String inComplete = "0";
private static final String defaultToken = HealthConst.token_apiself;
//削峰,初始200,超过放入队列,再超过800起新线程,采用默认AbortPolicy策略,线程数超过2000抛异常
private final Executor executor = new ThreadPoolExecutor(200, 2000,
60L, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(800));
//初步测试没有压力,速度最快,没有线程上限
// private final Executor executor = Executors.newCachedThreadPool();
//单例模式
private ReplenishIncompleteEmrScheduler() {
}
@Override
protected Class getLoggerClass() {
return ReplenishIncompleteEmrScheduler.class;
}
private static ReplenishIncompleteEmrScheduler instance = null;
public static synchronized ReplenishIncompleteEmrScheduler getInstance() {
if (null == instance) {
instance = new ReplenishIncompleteEmrScheduler();
}
return instance;
}
@PostConstruct
public void init() {
//scheduleWithFixedDelay间隔时间从上次执行结束开计,不用考虑重复问题
sendFuture = scheduledExecutorService.scheduleWithFixedDelay(new Runnable() {
public void run() {
try {
syncEmr();
} catch (Throwable t) { // 防御性容错
logger.error("Unexpected error occur at send statistic, cause: " + t.getMessage(), t);
}
}
}, beginMonitorInterval, monitorInterval, TimeUnit.MINUTES);
}
public void syncEmr() {
List<String> eventList = connectService.getEventHaveingLeaveDateGt15();
QueryParam queryParam = QueryParamAsPO.build()
.where(EmrIntegrityRecordsPO.Property.complete, inComplete)
.and(EmrIntegrityRecordsPO.Property.groupId,"not",HosGroupEnum.leyue.getGroupId())
.lt(EmrIntegrityRecordsPO.Property.obtainNum, 6 * 24 * 30 * 12);
List<EmrIntegrityRecordsPO> incompleteList = emrIntegrityRecordsService.select(queryParam, EmrIntegrityRecordsPO.class);
logger.info("定时任务取得不完整的XX数为:{}", incompleteList.size());
if (incompleteList.size() > 0 && incompleteList != null) {
//去除XX时间大于15天的数据
List<EmrIntegrityRecordsPO> toDolist = incompleteList.stream().filter(
event -> !eventList.contains(event.getEventId())
).collect(Collectors.toList());
logger.info("定时任务待更新的XX数为:{}", toDolist.size());
if (null != toDolist && toDolist.size() > 0) {
//存放处理结果
List<Map<String, String>> list = new ArrayList<>();
//调用API
List<CompletableFuture<Map<String, String>>> futures = toDolist.stream().map(event -> CompletableFuture.supplyAsync(
() -> {
Map<String, String> resultMap = new HashMap<String, String>() {
};
try {
String result = doHttpPost(event.getEventId());
logger.info("定时同步完成,任务编号eventId:{},返回结果:{}", event.getEventId(), result);
resultMap.put(event.getEventId(), result);
list.add(resultMap);
return resultMap;
} catch (Exception e) {
logger.error("定时同步失败,任务编号eventId:{};异常信息:{}", event.getEventId(), e);
resultMap.put(event.getEventId(), "定时同步失败:" + e);
} finally {
return resultMap;
}
}
, executor)
).collect(Collectors.toList());
//如果以后有调用结果存库需求,可把resultList存库
List resultList = futures.stream().map(CompletableFuture::join).collect(Collectors.toList());
logger.info("此次定时更新全部已完成");
} else {
logger.info("定时任务没有需要同步的任务");
}
}
}
/**
* 发起httpPost请求
*
* @return 请求响应信息 可能为 null
*/
private String doHttpPost(String eventId) throws Exception {
EmrReqByEvent emrReqByEvent = EmrReqByEvent.build().setEventId(eventId).setBackFill(BackFill_YES);
String ip = InetAddress.getLocalHost().getHostAddress();
emrUrl = "http://" + ip + ":" + port + "/emr/api/medicalrecord/completion";
return super.post(emrUrl, defaultToken, emrReqByEvent, String.class).asDataIfSuccess();
}
public void destroy() {
if (sendFuture != null) {
logger.info("关闭定时功能");
sendFuture.cancel(true);
}
}
}