|
@@ -8,8 +8,10 @@ import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|
|
import org.springframework.context.annotation.Configuration;
|
|
import org.springframework.context.annotation.Configuration;
|
|
|
|
|
+import org.springframework.context.annotation.Bean;
|
|
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
|
|
import org.springframework.scheduling.annotation.Scheduled;
|
|
import org.springframework.scheduling.annotation.Scheduled;
|
|
|
|
|
+import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
|
|
|
|
|
|
|
import java.util.Map;
|
|
import java.util.Map;
|
|
|
import java.util.Set;
|
|
import java.util.Set;
|
|
@@ -18,7 +20,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|
|
/**
|
|
/**
|
|
|
* 补发起工时审批定时(bug 1 修复)
|
|
* 补发起工时审批定时(bug 1 修复)
|
|
|
* <p>
|
|
* <p>
|
|
|
- * 每天 05:20、12:55 触发;先让 04:20、12:20 回写兜底消化已完成审批,再扫描最近 7 个自然日发生修改的汇总记录,
|
|
|
|
|
|
|
+ * 每天 07:00、16:00 触发;先让 04:20、12:20 回写兜底消化已完成审批,再扫描最近 7 个自然日发生修改的汇总记录,
|
|
|
* 按实际业务 (month, userId) 去重,
|
|
* 按实际业务 (month, userId) 去重,
|
|
|
* 走 ReSubmitApprovalService.resubmit 逻辑:queryProcess(RUNNING) 有则 update / 无则 create。
|
|
* 走 ReSubmitApprovalService.resubmit 逻辑:queryProcess(RUNNING) 有则 update / 无则 create。
|
|
|
* <p>
|
|
* <p>
|
|
@@ -45,12 +47,28 @@ public class ReSubmitApprovalTimer {
|
|
|
@Autowired
|
|
@Autowired
|
|
|
private MonthClosingService monthClosingService;
|
|
private MonthClosingService monthClosingService;
|
|
|
|
|
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ private ThreadPoolTaskScheduler resubmitTaskScheduler;
|
|
|
|
|
+
|
|
|
private static final AtomicBoolean RUNNING = new AtomicBoolean(false);
|
|
private static final AtomicBoolean RUNNING = new AtomicBoolean(false);
|
|
|
|
|
+ private static final AtomicBoolean DISPATCHED = new AtomicBoolean(false);
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 长补发任务使用独立调度线程,避免占用人员同步及其他短任务的默认调度线程。
|
|
|
|
|
+ */
|
|
|
|
|
+ @Bean(name = "resubmitTaskScheduler")
|
|
|
|
|
+ public ThreadPoolTaskScheduler resubmitTaskScheduler() {
|
|
|
|
|
+ ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
|
|
|
|
|
+ scheduler.setPoolSize(1);
|
|
|
|
|
+ scheduler.setThreadNamePrefix("resubmit-scheduler-");
|
|
|
|
|
+ scheduler.setWaitForTasksToCompleteOnShutdown(true);
|
|
|
|
|
+ scheduler.setAwaitTerminationSeconds(30);
|
|
|
|
|
+ return scheduler;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 每天凌晨 05:20 兜底补发起
|
|
|
|
|
|
|
+ * 每天 07:00 兜底补发起
|
|
|
*/
|
|
*/
|
|
|
- @Scheduled(cron = "0 20 5 * * ?")
|
|
|
|
|
public void scanAndReSubmit() {
|
|
public void scanAndReSubmit() {
|
|
|
if (!RUNNING.compareAndSet(false, true)) {
|
|
if (!RUNNING.compareAndSet(false, true)) {
|
|
|
log.warn("[补发起兜底] 上次执行未结束,跳过本次触发");
|
|
log.warn("[补发起兜底] 上次执行未结束,跳过本次触发");
|
|
@@ -99,12 +117,43 @@ public class ReSubmitApprovalTimer {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * prd 每天中午 12:55 再执行一次补发兜底,与 12:45 应报工时增量任务错开。
|
|
|
|
|
|
|
+ * prd 每天 16:00 再执行一次补发兜底,与中午时段的应报工时任务错开。
|
|
|
* 封账月份仍由 {@link #scanAndReSubmit()} 内的实时封账校验统一跳过。
|
|
* 封账月份仍由 {@link #scanAndReSubmit()} 内的实时封账校验统一跳过。
|
|
|
*/
|
|
*/
|
|
|
- @Scheduled(cron = "0 55 12 * * ?")
|
|
|
|
|
public void scanAndReSubmitAtNoon() {
|
|
public void scanAndReSubmitAtNoon() {
|
|
|
scanAndReSubmit();
|
|
scanAndReSubmit();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 默认调度线程只负责投递,实际长任务在线程池中执行,避免阻塞其他定时任务。
|
|
|
|
|
+ */
|
|
|
|
|
+ @Scheduled(cron = "0 0 7 * * ?")
|
|
|
|
|
+ public void scheduledMorningResubmit() {
|
|
|
|
|
+ dispatchResubmitTask();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Scheduled(cron = "0 0 16 * * ?")
|
|
|
|
|
+ public void scheduledAfternoonResubmit() {
|
|
|
|
|
+ dispatchResubmitTask();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void dispatchResubmitTask() {
|
|
|
|
|
+ if (!DISPATCHED.compareAndSet(false, true)) {
|
|
|
|
|
+ log.warn("[补发起兜底] 长任务已在执行或排队,跳过本次投递");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ try {
|
|
|
|
|
+ resubmitTaskScheduler.execute(() -> {
|
|
|
|
|
+ try {
|
|
|
|
|
+ scanAndReSubmit();
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ DISPATCHED.set(false);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ } catch (RuntimeException ex) {
|
|
|
|
|
+ DISPATCHED.set(false);
|
|
|
|
|
+ log.error("[补发起兜底] 长任务投递失败", ex);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
}
|
|
}
|