package cn.iocoder.yudao.module.mes.job.pro;
|
|
import cn.iocoder.yudao.module.mes.service.pro.qrexport.MesProQrExportTaskService;
|
import lombok.RequiredArgsConstructor;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
import org.springframework.context.event.EventListener;
|
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.stereotype.Component;
|
|
/**
|
* 二维码导出临时文件清理
|
* <p>
|
* 大批量导出的临时 ZIP 可达上 GB,正常下载完成后即删,本任务只兜底两类残留:
|
* <ol>
|
* <li>下载中断或生成完成后始终未下载的文件,超过保留期后删除;</li>
|
* <li>因服务重启而失去执行线程、永远停在「生成中」的任务记录。</li>
|
* </ol>
|
* 用 Spring 自带的 {@code @Scheduled} 而非 Quartz JobHandler:后者需要在管理后台手工登记任务,
|
* 漏登记就会静默不执行,而这里的清理属于「不执行就会占满磁盘」的兜底逻辑,必须开箱即跑。
|
*/
|
@Slf4j
|
@Component
|
@RequiredArgsConstructor
|
public class MesProQrExportCleanupTask {
|
|
private final MesProQrExportTaskService taskService;
|
|
/**
|
* 每 5 分钟清理一次:与默认 10 分钟的临时文件保留期匹配,避免残留文件长时间占用磁盘
|
*/
|
@Scheduled(cron = "0 */5 * * * ?")
|
public void cleanup() {
|
try {
|
int files = taskService.cleanupExpiredFiles();
|
int tasks = taskService.recycleStaleTasks();
|
if (files > 0 || tasks > 0) {
|
log.info("[cleanup][二维码导出清理完成:删除临时文件 {} 个,回收残留任务 {} 个]", files, tasks);
|
}
|
} catch (Exception e) {
|
log.error("[cleanup][二维码导出清理失败]", e);
|
}
|
}
|
|
/**
|
* 启动时立刻回收一次残留任务
|
* <p>
|
* 进程重启后运行态注册表为空,此时表中的非终态记录必定没有执行线程在推进,
|
* 立刻回收可避免它们以「生成中」的状态一直挂在界面上(否则要等到下一次定时清理)。
|
*/
|
@EventListener(ApplicationReadyEvent.class)
|
public void recycleOnStartup() {
|
try {
|
int tasks = taskService.recycleStaleTasks();
|
if (tasks > 0) {
|
log.info("[recycleOnStartup][启动回收残留二维码导出任务 {} 个]", tasks);
|
}
|
} catch (Exception e) {
|
log.error("[recycleOnStartup][启动回收二维码导出任务失败]", e);
|
}
|
}
|
|
}
|