liu
5 小时以前 6c0fd2cb801554f7999d14e45a94ef0f0d0dfb8d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
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);
        }
    }
 
}