task-164: 清理失败不阻断契约(单文件失败其余继续、失败路径可见、不上抛、下轮重试、引用跳过不计失败)+ 8 条测试

This commit is contained in:
2026-09-02 07:35:57 +08:00
parent 7a43ed6c43
commit 34f614ea32
2 changed files with 183 additions and 0 deletions
@@ -0,0 +1,61 @@
package com.nanri.aiimage.modules.file.service;
import org.springframework.stereotype.Service;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
/**
* 批量清理执行器(task-164)。
*
* 单个文件清理失败(删除函数返回 false/抛异常/引用判定失败)不影响其他文件;
* 失败可见(failedPaths 与失败计数);不上抛;下次调用可重试失败项。
*/
@Service
public class BatchFileCleaner {
public record BatchCleanResult(int cleanedCount, int failedCount, List<String> failedPaths) {
public boolean hasFailures() {
return failedCount > 0;
}
}
/**
* @param files 候选文件
* @param deleteFn 删除函数(返回 true 表示删除成功)
* @param isReferenced 引用判定(true → 跳过,不算失败)
*/
public BatchCleanResult cleanBatch(List<File> files, Function<File, Boolean> deleteFn,
Predicate<String> isReferenced) {
int cleaned = 0;
int failed = 0;
List<String> failedPaths = new ArrayList<>();
if (files == null || files.isEmpty()) {
return new BatchCleanResult(0, 0, failedPaths);
}
for (File file : files) {
if (file == null) {
continue;
}
try {
if (isReferenced != null && isReferenced.test(file.getName())) {
continue;
}
if (deleteFn != null && Boolean.TRUE.equals(deleteFn.apply(file))) {
cleaned++;
} else {
failed++;
failedPaths.add(file.getAbsolutePath());
}
} catch (Exception ex) {
failed++;
failedPaths.add(file.getAbsolutePath());
}
}
return new BatchCleanResult(cleaned, failed, List.copyOf(failedPaths));
}
}