From 383ec544e13f4aea20f25e2268f86dcbb4f812ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E8=87=AA=E8=BE=BE?= <980324341@qq.com> Date: Wed, 2 Sep 2026 06:02:14 +0800 Subject: [PATCH] =?UTF-8?q?task-148:=20=E4=B8=B4=E6=97=B6=E7=9B=AE?= =?UTF-8?q?=E5=BD=95=E9=85=8D=E7=BD=AE=E7=9B=98=E7=82=B9=EF=BC=8816=20?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E9=A1=B9/322=20=E6=B8=85=E7=90=86=E8=B0=83?= =?UTF-8?q?=E7=94=A8=E7=82=B9=E6=89=AB=E6=8F=8F=E5=99=A8=20+=209=20?= =?UTF-8?q?=E6=9D=A1=E6=B5=8B=E8=AF=95=20+=20=E6=8A=A5=E5=91=8A=E5=BF=AB?= =?UTF-8?q?=E7=85=A7=EF=BC=8C=E4=B8=8D=E6=94=B9=E7=94=9F=E4=BA=A7=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend-java/scripts/tc_report.json | 1712 +++++++++++++++++ backend-java/scripts/temp_config_audit.py | 113 ++ .../scripts/test_temp_config_audit.py | 89 + 3 files changed, 1914 insertions(+) create mode 100644 backend-java/scripts/tc_report.json create mode 100644 backend-java/scripts/temp_config_audit.py create mode 100644 backend-java/scripts/test_temp_config_audit.py diff --git a/backend-java/scripts/tc_report.json b/backend-java/scripts/tc_report.json new file mode 100644 index 00000000..5b3050c0 --- /dev/null +++ b/backend-java/scripts/tc_report.json @@ -0,0 +1,1712 @@ +{ + "configs": [ + { + "key": "upload-max-retries", + "value": "${AIIMAGE_TRANSIENT_STORAGE_UPLOAD_MAX_RETRIES:3}", + "line": 119, + "source": "application.yml" + }, + { + "key": "warn-payload-bytes", + "value": "${AIIMAGE_TRANSIENT_STORAGE_WARN_PAYLOAD_BYTES:5242880}", + "line": 136, + "source": "application.yml" + }, + { + "key": "max-payload-bytes", + "value": "${AIIMAGE_TRANSIENT_STORAGE_MAX_PAYLOAD_BYTES:52428800}", + "line": 137, + "source": "application.yml" + }, + { + "key": "max-stored-payload-bytes", + "value": "${AIIMAGE_TRANSIENT_STORAGE_MAX_STORED_PAYLOAD_BYTES:52428800}", + "line": 138, + "source": "application.yml" + }, + { + "key": "local-temp-dir", + "value": "${AIIMAGE_STORAGE_LOCAL_TEMP_DIR:./data/tmp}", + "line": 146, + "source": "application.yml" + }, + { + "key": "source-retention-hours", + "value": "${AIIMAGE_STORAGE_SOURCE_RETENTION_HOURS:24}", + "line": 149, + "source": "application.yml" + }, + { + "key": "result-retention-hours", + "value": "${AIIMAGE_STORAGE_RESULT_RETENTION_HOURS:24}", + "line": 150, + "source": "application.yml" + }, + { + "key": "transient-payload-retention-hours", + "value": "${AIIMAGE_STORAGE_TRANSIENT_PAYLOAD_RETENTION_HOURS:72}", + "line": 151, + "source": "application.yml" + }, + { + "key": "temp-dir", + "value": "", + "line": 152, + "source": "application.yml" + }, + { + "key": "retention-hours", + "value": "${AIIMAGE_TEMP_DIR_RETENTION_HOURS:24}", + "line": 153, + "source": "application.yml" + }, + { + "key": "retention-days", + "value": "${AIIMAGE_MODULE_CLEANUP_RETENTION_DAYS:7}", + "line": 183, + "source": "application.yml" + }, + { + "key": "scope-payload-flush-interval-millis", + "value": "${AIIMAGE_TASK_SCOPE_PAYLOAD_FLUSH_INTERVAL_MILLIS:15000}", + "line": 190, + "source": "application.yml" + }, + { + "key": "scope-payload-buffer-retention-hours", + "value": "${AIIMAGE_TASK_SCOPE_PAYLOAD_BUFFER_RETENTION_HOURS:24}", + "line": 191, + "source": "application.yml" + }, + { + "key": "scope-payload-recovery-max-files", + "value": "${AIIMAGE_TASK_SCOPE_PAYLOAD_RECOVERY_MAX_FILES:200}", + "line": 192, + "source": "application.yml" + }, + { + "key": "scope-payload-cleanup-cron", + "value": "${AIIMAGE_TASK_SCOPE_PAYLOAD_CLEANUP_CRON:15 */30 * * * *}", + "line": 193, + "source": "application.yml" + }, + { + "key": "retention-days", + "value": "${AIIMAGE_TASK_IMAGE_CACHE_RETENTION_DAYS:3}", + "line": 197, + "source": "application.yml" + } + ], + "cleanup_calls": [ + { + "file": "src/main/java/com/nanri/aiimage/config/ModuleCleanupProperties.java", + "line": 10, + "snippet": "@ConfigurationProperties(prefix = \"aiimage.module-cleanup\")" + }, + { + "file": "src/main/java/com/nanri/aiimage/config/ModuleCleanupProperties.java", + "line": 11, + "snippet": "public class ModuleCleanupProperties {" + }, + { + "file": "src/main/java/com/nanri/aiimage/config/PropertiesConfig.java", + "line": 7, + "snippet": "@EnableConfigurationProperties({OssProperties.class, TransientStorageProperties.class, StorageProper" + }, + { + "file": "src/main/java/com/nanri/aiimage/config/StorageProperties.java", + "line": 11, + "snippet": "private String localTempDir;" + }, + { + "file": "src/main/java/com/nanri/aiimage/config/StorageProperties.java", + "line": 12, + "snippet": "private boolean cleanupEnabled = true;" + }, + { + "file": "src/main/java/com/nanri/aiimage/config/StorageProperties.java", + "line": 13, + "snippet": "private String cleanupCron = \"0 0 * * * *\";" + }, + { + "file": "src/main/java/com/nanri/aiimage/config/StorageProperties.java", + "line": 18, + "snippet": "public String getLocalTempDir() {" + }, + { + "file": "src/main/java/com/nanri/aiimage/config/StorageProperties.java", + "line": 19, + "snippet": "String configured = localTempDir == null ? \"\" : localTempDir.trim();" + }, + { + "file": "src/main/java/com/nanri/aiimage/config/TaskImageCacheCleanupProperties.java", + "line": 7, + "snippet": "@ConfigurationProperties(prefix = \"aiimage.task-image-cache-cleanup\")" + }, + { + "file": "src/main/java/com/nanri/aiimage/config/TaskImageCacheCleanupProperties.java", + "line": 8, + "snippet": "public class TaskImageCacheCleanupProperties {" + }, + { + "file": "src/main/java/com/nanri/aiimage/config/TaskPressureProperties.java", + "line": 18, + "snippet": "private String scopePayloadCleanupCron = \"15 */30 * * * *\";" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/appearancepatent/service/AppearancePatentTaskService.java", + "line": 1163, + "snippet": "transientPayloadStorageService.deleteReplacedPayloadIfNeeded(oldPayload, storedPayload);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/appearancepatent/service/AppearancePatentTaskService.java", + "line": 1166, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(storedPayload);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/appearancepatent/service/AppearancePatentTaskService.java", + "line": 1824, + "snippet": "public void cleanupResultFileJob(TaskFileJobEntity job) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/appearancepatent/service/AppearancePatentTaskService.java", + "line": 1849, + "snippet": "File outputDir = new File(storageProperties.getLocalTempDir(), \"appearance-patent-result\");" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/appearancepatent/service/AppearancePatentTaskService.java", + "line": 2919, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(scope.getParsedPayloadJson());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/appearancepatent/service/AppearancePatentTaskService.java", + "line": 2920, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(scope.getStateJson());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/appearancepatent/service/AppearancePatentTaskService.java", + "line": 2929, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(chunk.getPayloadJson());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/brand/service/BrandTaskService.java", + "line": 674, + "snippet": "File outputDir = FileUtil.mkdir(FileUtil.file(storageProperties.getLocalTempDir(), \"brand-result\", S" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/brand/service/BrandTaskService.java", + "line": 725, + "snippet": "cleanupBrandResultTempFiles(outputEntries, outputDir);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/brand/service/BrandTaskService.java", + "line": 822, + "snippet": "File downloadDir = FileUtil.mkdir(FileUtil.file(storageProperties.getLocalTempDir(), \"brand-source-d" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/brand/service/BrandTaskService.java", + "line": 1097, + "snippet": "File zipDir = FileUtil.mkdir(FileUtil.file(storageProperties.getLocalTempDir(), \"brand-result\", Stri" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/brand/service/BrandTaskService.java", + "line": 1110, + "snippet": "private void cleanupBrandResultTempFiles(List entries, File outputDir) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/brand/service/BrandTaskService.java", + "line": 1129, + "snippet": "File managedDir = FileUtil.file(storageProperties.getLocalTempDir(), \"brand-source-download\");" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/brand/service/BrandTaskService.java", + "line": 1142, + "snippet": "FileUtil.del(file);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/brand/service/BrandTaskStorageService.java", + "line": 75, + "snippet": "transientPayloadStorageService.deleteReplacedPayloadIfNeeded(state.getParsedPayloadJson(), parsedJso" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/brand/service/BrandTaskStorageService.java", + "line": 157, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(storedPayload);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/brand/service/BrandTaskStorageService.java", + "line": 162, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(storedPayload);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/brand/service/BrandTaskStorageService.java", + "line": 250, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(state.getParsedPayloadJson());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/brand/service/BrandTaskStorageService.java", + "line": 251, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(state.getStateJson());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/brand/service/BrandTaskStorageService.java", + "line": 260, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(chunk.getPayloadJson());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/brand/service/BrandTaskStorageService.java", + "line": 301, + "snippet": "transientPayloadStorageService.deleteReplacedPayloadIfNeeded(state.getStateJson(), storedAggregate);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/brand/service/BrandTaskStorageService.java", + "line": 303, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(storedAggregate);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/collectdata/service/CollectDataExcelAssemblyService.java", + "line": 89, + "snippet": "Files.deleteIfExists(file.toPath());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/collectdata/service/CollectDataService.java", + "line": 827, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(storedPayload);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/collectdata/service/CollectDataService.java", + "line": 933, + "snippet": "FileUtil.del(xlsx);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/collectdata/service/CollectDataService.java", + "line": 1004, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(storedPayload);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/collectdata/service/CollectDataService.java", + "line": 1198, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(chunk.getPayloadJson());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/collectdata/service/CollectDataService.java", + "line": 1215, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(ref.pointer());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/collectdata/service/CollectDataService.java", + "line": 1218, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(item.getPayloadJson());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/collectdata/util/CollectDataResultItemBatchWriter.java", + "line": 103, + "snippet": "// (deletePayloadIfPresent 内部带全局引用计数兜底)。" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/collectdata/util/CollectDataResultItemBatchWriter.java", + "line": 106, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(existing.getPayloadJson());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/convert/controller/ConvertTemplateController.java", + "line": 70, + "snippet": "convertTemplateService.deleteTemplate(templateCode);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/convert/service/ConvertRunService.java", + "line": 241, + "snippet": "File outputDir = FileUtil.mkdir(FileUtil.file(storageProperties.getLocalTempDir(), \"convert-result\")" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/convert/service/ConvertRunService.java", + "line": 388, + "snippet": "File outputDir = FileUtil.mkdir(FileUtil.file(storageProperties.getLocalTempDir(), \"convert-result\")" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/convert/service/ConvertRunService.java", + "line": 404, + "snippet": "File outputDir = FileUtil.mkdir(FileUtil.file(storageProperties.getLocalTempDir(), \"convert-result\")" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/convert/service/ConvertRunService.java", + "line": 458, + "snippet": "File baseDir = FileUtil.file(storageProperties.getLocalTempDir());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/convert/service/ConvertTemplateService.java", + "line": 79, + "snippet": "public void deleteTemplate(String templateCode) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/dedupe/service/DedupeRunService.java", + "line": 97, + "snippet": "File outputDir = FileUtil.mkdir(FileUtil.file(storageProperties.getLocalTempDir(), \"dedupe-result\"))" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/dedupe/service/DedupeRunService.java", + "line": 495, + "snippet": "File outputDir = FileUtil.mkdir(FileUtil.file(storageProperties.getLocalTempDir(), \"dedupe-result\"))" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/dedupe/service/DedupeRunService.java", + "line": 572, + "snippet": "File baseDir = FileUtil.file(storageProperties.getLocalTempDir());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/dedupe/service/DedupeTotalDataService.java", + "line": 410, + "snippet": "cleanupExpiredProgress();" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/dedupe/service/DedupeTotalDataService.java", + "line": 446, + "snippet": "cleanupExpiredProgress();" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/dedupe/service/DedupeTotalDataService.java", + "line": 462, + "snippet": "cleanupExpiredProgress();" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/dedupe/service/DedupeTotalDataService.java", + "line": 498, + "snippet": "cleanupExpiredProgress();" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/dedupe/service/DedupeTotalDataService.java", + "line": 579, + "snippet": "Files.deleteIfExists(file.toPath());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/dedupe/service/DedupeTotalDataService.java", + "line": 1095, + "snippet": "private void cleanupExpiredProgress() {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/dedupe/service/DedupeTotalDataService.java", + "line": 1097, + "snippet": "cleanupExpiredProgressEntries(" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/dedupe/service/DedupeTotalDataService.java", + "line": 1099, + "snippet": "cleanupExpiredProgressEntries(" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/dedupe/service/DedupeTotalDataService.java", + "line": 1104, + "snippet": "private void cleanupExpiredProgressEntries(" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/deletebrand/service/DeleteBrandRunService.java", + "line": 1701, + "snippet": "cleanupCompletedTaskDataIfNoPendingFileJobs(task.getId());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/deletebrand/service/DeleteBrandRunService.java", + "line": 1774, + "snippet": "public void cleanupResultFileJob(TaskFileJobEntity job) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/deletebrand/service/DeleteBrandRunService.java", + "line": 1782, + "snippet": "cleanupCompletedTaskDataIfNoPendingFileJobs(job.getTaskId());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/deletebrand/service/DeleteBrandRunService.java", + "line": 1785, + "snippet": "private void cleanupCompletedTaskDataIfNoPendingFileJobs(Long taskId) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/deletebrand/service/DeleteBrandRunService.java", + "line": 1958, + "snippet": "FileUtil.del(file);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/deletebrand/service/DeleteBrandStaleTaskService.java", + "line": 58, + "snippet": "private static final Duration TEMP_DIR_CLEANUP_LOCK_TTL = Duration.ofMinutes(10);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/deletebrand/service/DeleteBrandStaleTaskService.java", + "line": 85, + "snippet": "private long tempDirRetentionHours;" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/deletebrand/service/DeleteBrandStaleTaskService.java", + "line": 747, + "snippet": "@Scheduled(cron = \"${aiimage.temp-dir.cleanup-cron:15 */30 * * * *}\")" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/deletebrand/service/DeleteBrandStaleTaskService.java", + "line": 748, + "snippet": "public void cleanupExpiredTempDirs() {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/deletebrand/service/DeleteBrandStaleTaskService.java", + "line": 750, + "snippet": "distributedJobLockService.tryLock(\"temp-dir:cleanup\", TEMP_DIR_CLEANUP_LOCK_TTL);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/deletebrand/service/DeleteBrandStaleTaskService.java", + "line": 752, + "snippet": "log.info(\"[temp-dir-cleanup] skip because another instance holds the distributed lock\");" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/deletebrand/service/DeleteBrandStaleTaskService.java", + "line": 756, + "snippet": "Instant cutoff = Instant.now().minus(Duration.ofHours(Math.max(1L, tempDirRetentionHours)));" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/deletebrand/service/DeleteBrandStaleTaskService.java", + "line": 770, + "snippet": "cleanupTempRoot(dirName, cutoff);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/deletebrand/service/DeleteBrandStaleTaskService.java", + "line": 775, + "snippet": "private void cleanupTempRoot(String dirName, Instant cutoff) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/deletebrand/service/DeleteBrandStaleTaskService.java", + "line": 788, + "snippet": "log.info(\"[temp-dir-cleanup] deleted expired temp path dir={} path={}\", dirName, child);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/deletebrand/service/DeleteBrandStaleTaskService.java", + "line": 790, + "snippet": "log.warn(\"[temp-dir-cleanup] delete failed dir={} path={} msg={}\", dirName, child, ex.getMessage());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/deletebrand/service/DeleteBrandStaleTaskService.java", + "line": 794, + "snippet": "log.warn(\"[temp-dir-cleanup] scan failed dir={} msg={}\", dirName, ex.getMessage());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/deletebrand/service/DeleteBrandStaleTaskService.java", + "line": 805, + "snippet": "Files.deleteIfExists(item);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/deletebrand/service/DeleteBrandTaskStorageService.java", + "line": 83, + "snippet": "transientPayloadStorageService.deleteReplacedPayloadIfNeeded(existing.getParsedPayloadJson(), parsed" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/deletebrand/service/DeleteBrandTaskStorageService.java", + "line": 194, + "snippet": "transientPayloadStorageService.deleteReplacedPayloadIfNeeded(concurrentChunk.getPayloadJson(), store" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/deletebrand/service/DeleteBrandTaskStorageService.java", + "line": 200, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(storedPayload);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/deletebrand/service/DeleteBrandTaskStorageService.java", + "line": 209, + "snippet": "transientPayloadStorageService.deleteReplacedPayloadIfNeeded(existingChunk.getPayloadJson(), storedP" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/deletebrand/service/DeleteBrandTaskStorageService.java", + "line": 266, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(state.getParsedPayloadJson());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/deletebrand/service/DeleteBrandTaskStorageService.java", + "line": 267, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(state.getStateJson());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/deletebrand/service/DeleteBrandTaskStorageService.java", + "line": 276, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(chunk.getPayloadJson());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/file/service/LocalFileStorageService.java", + "line": 41, + "snippet": "File tempDir = FileUtil.file(storageProperties.getLocalTempDir());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/file/service/LocalFileStorageService.java", + "line": 42, + "snippet": "File parentDir = tempDir.getParentFile();" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/file/service/LocalFileStorageService.java", + "line": 46, + "snippet": "FileUtil.mkdir(tempDir);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/file/service/LocalFileStorageService.java", + "line": 50, + "snippet": "File target = FileUtil.file(tempDir, filename);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/file/service/LocalFileStorageService.java", + "line": 118, + "snippet": "File baseDir = FileUtil.file(storageProperties.getLocalTempDir());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/file/service/LocalTempCleanupService.java", + "line": 19, + "snippet": "public class LocalTempCleanupService {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/file/service/LocalTempCleanupService.java", + "line": 35, + "snippet": "@Scheduled(cron = \"${aiimage.storage.cleanup-cron:0 0 */6 * * *}\")" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/file/service/LocalTempCleanupService.java", + "line": 36, + "snippet": "public void cleanupLocalTempDir() {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/file/service/LocalTempCleanupService.java", + "line": 37, + "snippet": "if (!storageProperties.isCleanupEnabled()) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/file/service/LocalTempCleanupService.java", + "line": 40, + "snippet": "File tempDir = FileUtil.file(storageProperties.getLocalTempDir());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/file/service/LocalTempCleanupService.java", + "line": 41, + "snippet": "if (!tempDir.exists() || !tempDir.isDirectory()) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/file/service/LocalTempCleanupService.java", + "line": 53, + "snippet": "File[] children = tempDir.listFiles();" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/file/service/LocalTempCleanupService.java", + "line": 61, + "snippet": "if (FileUtil.del(child)) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/file/service/LocalTempCleanupService.java", + "line": 68, + "snippet": "deleteEmptyDirectories(child, tempDir);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/file/service/LocalTempCleanupService.java", + "line": 73, + "snippet": "deleteEmptyDirectories(child, tempDir);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/file/service/LocalTempCleanupService.java", + "line": 76, + "snippet": "log.warn(\"local temp cleanup failed: path={}\", child.getAbsolutePath(), ex);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/file/service/LocalTempCleanupService.java", + "line": 81, + "snippet": "log.info(\"local temp cleanup completed: sourceDeleted={}, resultDeleted={}, transientPayloadDeleted=" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/file/service/LocalTempCleanupService.java", + "line": 82, + "snippet": "deletedSourceCount, deletedResultCount, deletedTransientPayloadCount, tempDir.getAbsolutePath());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/file/service/LocalTempCleanupService.java", + "line": 95, + "snippet": "if (isExpired(file, expireBefore) && isDirectoryEmpty(file) && FileUtil.del(file)) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/file/service/LocalTempCleanupService.java", + "line": 100, + "snippet": "if (isExpired(file, expireBefore) && FileUtil.del(file)) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/file/service/LocalTempCleanupService.java", + "line": 109, + "snippet": "if (!FileUtil.del(current)) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/imagevideo/service/ImageVideoArchiveService.java", + "line": 38, + "snippet": "private static final int RETENTION_CLEANUP_BATCH_SIZE = 200;" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/imagevideo/service/ImageVideoArchiveService.java", + "line": 108, + "snippet": "@Scheduled(fixedDelayString = \"${aiimage.image-video.retention-cleanup-delay-ms:600000}\")" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/imagevideo/service/ImageVideoArchiveService.java", + "line": 109, + "snippet": "public void cleanupExpiredWorkflowTasks() {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/imagevideo/service/ImageVideoArchiveService.java", + "line": 116, + "snippet": ".last(\"LIMIT \" + RETENTION_CLEANUP_BATCH_SIZE));" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/imagevideo/service/ImageVideoArchiveService.java", + "line": 125, + "snippet": "log.info(\"[image-video] expired workflow task cleanup deleted={} cutoff={}\", deleted, cutoff);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/imagevideo/service/ImageVideoArchiveService.java", + "line": 141, + "snippet": "log.warn(\"[image-video] expired task OSS cleanup failed taskId={} objectKey={} error={}\"," + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/imagevideo/service/ImageVideoAsyncTaskService.java", + "line": 164, + "snippet": "@Scheduled(fixedDelayString = \"${aiimage.image-video.failed-task-cleanup-delay-ms:60000}\")" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/imagevideo/service/ImageVideoAsyncTaskService.java", + "line": 165, + "snippet": "public void cleanupFailedTasks() {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/patroldelete/service/PatrolDeleteTaskService.java", + "line": 484, + "snippet": "cleanupTaskAuxiliaryDataFast(taskId);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/patroldelete/service/PatrolDeleteTaskService.java", + "line": 512, + "snippet": "cleanupResultAuxiliaryDataFast(taskId, resultId);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/patroldelete/service/PatrolDeleteTaskService.java", + "line": 521, + "snippet": "cleanupResultAuxiliaryDataFast(taskId, resultId);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/patroldelete/service/PatrolDeleteTaskService.java", + "line": 536, + "snippet": "cleanupTaskAuxiliaryDataFast(taskId);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/patroldelete/service/PatrolDeleteTaskService.java", + "line": 546, + "snippet": "private void cleanupTaskAuxiliaryData(Long taskId) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/patroldelete/service/PatrolDeleteTaskService.java", + "line": 552, + "snippet": "private void cleanupTaskAuxiliaryDataFast(Long taskId) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/patroldelete/service/PatrolDeleteTaskService.java", + "line": 559, + "snippet": "private void cleanupResultAuxiliaryData(Long taskId, Long resultId) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/patroldelete/service/PatrolDeleteTaskService.java", + "line": 564, + "snippet": "private void cleanupResultAuxiliaryDataFast(Long taskId, Long resultId) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/patroldelete/service/PatrolDeleteTaskService.java", + "line": 1029, + "snippet": "FileUtil.del(xlsx);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/pricetrack/service/PriceTrackTaskService.java", + "line": 312, + "snippet": "cleanupTaskCacheIfTerminal(taskId, task.getStatus());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/pricetrack/service/PriceTrackTaskService.java", + "line": 639, + "snippet": "cleanupTaskCacheIfTerminal(taskId, task.getStatus());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/pricetrack/service/PriceTrackTaskService.java", + "line": 653, + "snippet": "cleanupTaskCacheIfTerminal(taskId, task.getStatus());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/pricetrack/service/PriceTrackTaskService.java", + "line": 749, + "snippet": "cleanupTaskCacheIfTerminal(taskId, \"DELETE_EMPTY\");" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/pricetrack/service/PriceTrackTaskService.java", + "line": 793, + "snippet": "cn.hutool.core.io.FileUtil.del(xlsx);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/pricetrack/service/PriceTrackTaskService.java", + "line": 2092, + "snippet": "cleanupTaskCacheIfTerminal(task.getId(), task.getStatus());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/pricetrack/service/PriceTrackTaskService.java", + "line": 2130, + "snippet": "private void cleanupTaskCacheIfTerminal(Long taskId, String taskStatus) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/productrisk/service/ProductRiskTaskService.java", + "line": 288, + "snippet": "cleanupTaskCacheIfTerminal(taskId, \"DELETE_EMPTY\");" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/productrisk/service/ProductRiskTaskService.java", + "line": 367, + "snippet": "cleanupTaskCacheIfTerminal(taskId, \"DELETE_EMPTY\");" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/productrisk/service/ProductRiskTaskService.java", + "line": 420, + "snippet": "cleanupTaskCacheIfTerminal(taskId, task.getStatus());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/productrisk/service/ProductRiskTaskService.java", + "line": 833, + "snippet": "FileUtil.del(xlsx);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/productrisk/service/ProductRiskTaskService.java", + "line": 834, + "snippet": "FileUtil.del(zip);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/productrisk/service/ProductRiskTaskService.java", + "line": 951, + "snippet": "cleanupTaskCacheIfTerminal(task.getId(), task.getStatus());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/productrisk/service/ProductRiskTaskService.java", + "line": 954, + "snippet": "private void cleanupTaskCacheIfTerminal(Long taskId, String taskStatus) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/publish/service/PublishTaskService.java", + "line": 283, + "snippet": "if (committed != null && committed.cleanupAfterCommit()) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/publish/service/PublishTaskService.java", + "line": 287, + "snippet": "log.warn(\"[publish] failed-task chunk cleanup failed taskId={} msg={}\"," + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/publish/service/PublishTaskService.java", + "line": 447, + "snippet": "log.warn(\"[publish] stale task cleanup failed taskId={} msg={}\"," + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/publish/service/PublishTaskService.java", + "line": 532, + "snippet": "FileUtil.del(workDirectory);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/publish/service/PublishTaskService.java", + "line": 549, + "snippet": "log.warn(\"[publish] OSS cleanup failed taskId={} resultId={} msg={}\"," + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/publish/service/PublishTaskService.java", + "line": 575, + "snippet": "public void cleanupResultFileJob(TaskFileJobEntity job) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/publish/service/PublishTaskService.java", + "line": 592, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(chunk.getPayloadJson());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/publish/service/PublishTaskService.java", + "line": 610, + "snippet": "log.info(\"[publish] skip uncommitted payload cleanup because it is referenced pointer={}\"," + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/publish/service/PublishTaskService.java", + "line": 614, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(storedPayload);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/publish/service/PublishTaskService.java", + "line": 616, + "snippet": "log.warn(\"[publish] uncommitted RustFS payload cleanup failed pointer={} msg={}\"," + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/publish/service/PublishTaskService.java", + "line": 682, + "snippet": "ensureTaskOwnedByCurrentInstance(task, \"cleanup stale publish task\");" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/publish/service/PublishTaskService.java", + "line": 1516, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(storedPayload);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/publish/service/PublishTaskService.java", + "line": 1917, + "snippet": "private record SubmitResultCommit(boolean cleanupAfterCommit," + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/queryasin/service/QueryAsinTaskService.java", + "line": 988, + "snippet": "FileUtil.del(xlsx);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/shopdatacrawl/service/ShopDataCrawlTaskService.java", + "line": 158, + "snippet": "cleanupResultChunksQuietly(task.getId(), \"stale task failure\");" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/shopdatacrawl/service/ShopDataCrawlTaskService.java", + "line": 690, + "snippet": "// A task deletion is only a frontend task-record cleanup. The daily" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/shopdatacrawl/service/ShopDataCrawlTaskService.java", + "line": 863, + "snippet": "registerRollbackObjectCleanup(uploadedObjectKeys);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/shopdatacrawl/service/ShopDataCrawlTaskService.java", + "line": 999, + "snippet": "FileUtil.del(outputXlsx);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/shopdatacrawl/service/ShopDataCrawlTaskService.java", + "line": 1000, + "snippet": "FileUtil.del(workRoot);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/shopdatacrawl/service/ShopDataCrawlTaskService.java", + "line": 1350, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(storedPayload);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/shopdatacrawl/service/ShopDataCrawlTaskService.java", + "line": 1358, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(storedPayload);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/shopdatacrawl/service/ShopDataCrawlTaskService.java", + "line": 1373, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(storedPayload);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/shopdatacrawl/service/ShopDataCrawlTaskService.java", + "line": 1598, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(storedPayload);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/shopdatacrawl/service/ShopDataCrawlTaskService.java", + "line": 1752, + "snippet": "cleanupResultChunksQuietly(task.getId(), \"terminal task without workbook\");" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/shopdatacrawl/service/ShopDataCrawlTaskService.java", + "line": 1942, + "snippet": "FileUtil.del(outputXlsx);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/shopdatacrawl/service/ShopDataCrawlTaskService.java", + "line": 1943, + "snippet": "FileUtil.del(workRoot);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/shopdatacrawl/service/ShopDataCrawlTaskService.java", + "line": 2277, + "snippet": "private void registerRollbackObjectCleanup(List uploadedObjectKeys) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/shopdatacrawl/service/ShopDataCrawlTaskService.java", + "line": 2319, + "snippet": "log.warn(\"[shop-data-crawl] daily object cleanup failed object={} msg={}\", objectKey, safeMessage(ex" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/shopdatacrawl/service/ShopDataCrawlTaskService.java", + "line": 2421, + "snippet": "public void cleanupResultFileJob(TaskFileJobEntity job) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/shopdatacrawl/service/ShopDataCrawlTaskService.java", + "line": 2458, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(chunk.getPayloadJson());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/shopdatacrawl/service/ShopDataCrawlTaskService.java", + "line": 2470, + "snippet": "private void cleanupResultChunksQuietly(Long taskId, String reason) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/shopdatacrawl/service/ShopDataCrawlTaskService.java", + "line": 2474, + "snippet": "log.warn(\"[shop-data-crawl] result chunk cleanup failed taskId={} reason={} msg={}\"," + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/shopdatacrawl/service/ShopDataCrawlTaskService.java", + "line": 2581, + "snippet": "FileUtil.del(outputXlsx);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/shopdatacrawl/service/ShopDataCrawlTaskService.java", + "line": 2582, + "snippet": "FileUtil.del(workRoot);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/shopdatacrawl/service/ShopDataCrawlTaskService.java", + "line": 2844, + "snippet": "cleanupResultChunksQuietly(task.getId(), \"result file job exhausted\");" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/shopkey/service/QueryAsinService.java", + "line": 397, + "snippet": "Files.deleteIfExists(file.toPath());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/shopkey/service/SkipPriceAsinService.java", + "line": 782, + "snippet": "Files.deleteIfExists(file.toPath());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/shopmatch/service/ShopMatchTaskCacheService.java", + "line": 146, + "snippet": "Files.deleteIfExists(buildTaskEntityFile(taskId));" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/shopmatch/service/ShopMatchTaskCacheService.java", + "line": 152, + "snippet": "Files.deleteIfExists(path);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/shopmatch/service/ShopMatchTaskCacheService.java", + "line": 163, + "snippet": "Files.deleteIfExists(buildTaskEntityFile(taskId));" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/shopmatch/service/ShopMatchTaskCacheService.java", + "line": 216, + "snippet": "Files.deleteIfExists(file);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/shopmatch/service/ShopMatchTaskService.java", + "line": 790, + "snippet": "FileUtil.del(xlsx);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/similarasin/service/SimilarAsinTaskService.java", + "line": 788, + "snippet": "// that candidate; cleanup is only safe after a successful transaction" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/similarasin/service/SimilarAsinTaskService.java", + "line": 791, + "snippet": "cleanupPreparedSubmittedChunkIfUnreferenced(prepared);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/similarasin/service/SimilarAsinTaskService.java", + "line": 854, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(payload);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/similarasin/service/SimilarAsinTaskService.java", + "line": 1161, + "snippet": "log.info(\"[similar-asin] duplicate chunk inserted concurrently taskId={} scope={} chunk={} cleanupLo" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/similarasin/service/SimilarAsinTaskService.java", + "line": 1190, + "snippet": "private void cleanupPreparedSubmittedChunkIfUnreferenced(PreparedSubmittedChunk prepared) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/similarasin/service/SimilarAsinTaskService.java", + "line": 1200, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(prepared.storedPayload());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/similarasin/service/SimilarAsinTaskService.java", + "line": 1202, + "snippet": "log.warn(\"[similar-asin] cleanup uncommitted chunk payload failed taskId={} chunk={} err={}\"," + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/similarasin/service/SimilarAsinTaskService.java", + "line": 1703, + "snippet": "transientPayloadStorageService.deleteReplacedPayloadIfNeeded(oldPayload, storedPayload);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/similarasin/service/SimilarAsinTaskService.java", + "line": 1706, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(storedPayload);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/similarasin/service/SimilarAsinTaskService.java", + "line": 3251, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(pointer);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/similarasin/service/SimilarAsinTaskService.java", + "line": 3283, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(pointer);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/similarasin/service/SimilarAsinTaskService.java", + "line": 3868, + "snippet": "public void cleanupResultFileJob(TaskFileJobEntity job) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/similarasin/service/SimilarAsinTaskService.java", + "line": 3896, + "snippet": "File outputDir = new File(storageProperties.getLocalTempDir(), \"similar-asin-result\");" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/similarasin/service/SimilarAsinTaskService.java", + "line": 4076, + "snippet": "File outputDir = new File(storageProperties.getLocalTempDir(), \"similar-asin-result\");" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/similarasin/service/SimilarAsinTaskService.java", + "line": 4544, + "snippet": "Path spoolDir = Files.createTempDirectory(xlsx.getParentFile().toPath(), \"similar-asin-images-\");" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/similarasin/service/SimilarAsinTaskService.java", + "line": 5409, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(storedPayload);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/similarasin/util/ExcelCellImageWriter.java", + "line": 154, + "snippet": "Files.deleteIfExists(tmp);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/similarasin/util/SimilarAsinImageEmbedder.java", + "line": 681, + "snippet": "Files.deleteIfExists(path);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/similarasin/util/SimilarAsinImageEmbedder.java", + "line": 686, + "snippet": "Files.deleteIfExists(path);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/similarasin/util/SimilarAsinImageEmbedder.java", + "line": 732, + "snippet": "Files.deleteIfExists(temp);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/similarasin/util/SimilarAsinImageEmbedder.java", + "line": 734, + "snippet": "// Best-effort cleanup of a failed cache write." + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/similarasin/util/SimilarAsinImageEmbedder.java", + "line": 1286, + "snippet": "Files.deleteIfExists(file);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/similarasin/util/SimilarAsinImageEmbedder.java", + "line": 1306, + "snippet": "Files.deleteIfExists(path);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/similarasin/util/WpsCellImageWriter.java", + "line": 165, + "snippet": "Files.deleteIfExists(tmp);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/split/service/SplitRunService.java", + "line": 213, + "snippet": "File outputDir = FileUtil.mkdir(FileUtil.file(storageProperties.getLocalTempDir(), \"split-result\"));" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/split/service/SplitRunService.java", + "line": 362, + "snippet": "File baseDir = FileUtil.file(storageProperties.getLocalTempDir());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/split/service/SplitRunService.java", + "line": 395, + "snippet": "File outputDir = FileUtil.mkdir(FileUtil.file(storageProperties.getLocalTempDir(), \"split-result\"));" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/AppearancePatentResultFileJobHandler.java", + "line": 9, + "snippet": "* cleanup 委托 cleanupResultFileJob;支持异步 offload;owner scoped。" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/AppearancePatentResultFileJobHandler.java", + "line": 30, + "snippet": "public void cleanup(TaskFileJobEntity job) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/AppearancePatentResultFileJobHandler.java", + "line": 31, + "snippet": "appearancePatentTaskService.cleanupResultFileJob(job);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/BrandResultFileJobHandler.java", + "line": 10, + "snippet": "* cleanup 为空(原 cleanupAfterSuccess 无 BRAND 分支)。" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/CollectDataResultFileJobHandler.java", + "line": 8, + "snippet": "* cleanup 为空(原 cleanupAfterSuccess 无 COLLECT_DATA 分支)。" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/DeleteBrandResultFileJobHandler.java", + "line": 29, + "snippet": "public void cleanup(TaskFileJobEntity job) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/DeleteBrandResultFileJobHandler.java", + "line": 30, + "snippet": "deleteBrandRunService.cleanupResultFileJob(job);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ModuleHistoryCleanupService.java", + "line": 41, + "snippet": "public class ModuleHistoryCleanupService {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ModuleHistoryCleanupService.java", + "line": 44, + "snippet": "private static final Duration CLEANUP_LOCK_TTL = Duration.ofHours(2);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ModuleHistoryCleanupService.java", + "line": 49, + "snippet": "private final ModuleCleanupProperties moduleCleanupProperties;" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ModuleHistoryCleanupService.java", + "line": 67, + "snippet": "@Value(\"${aiimage.module-cleanup.max-collect-payloads:10000}\")" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ModuleHistoryCleanupService.java", + "line": 70, + "snippet": "public ModuleHistoryCleanupService(ModuleCleanupProperties moduleCleanupProperties," + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ModuleHistoryCleanupService.java", + "line": 83, + "snippet": "this.moduleCleanupProperties = moduleCleanupProperties;" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ModuleHistoryCleanupService.java", + "line": 102, + "snippet": "@Scheduled(cron = \"${aiimage.module-cleanup.cron:0 0 0 * * *}\")" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ModuleHistoryCleanupService.java", + "line": 103, + "snippet": "public void cleanupConfiguredModules() {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ModuleHistoryCleanupService.java", + "line": 105, + "snippet": "distributedJobLockService.tryLock(\"module-history:cleanup\", CLEANUP_LOCK_TTL);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ModuleHistoryCleanupService.java", + "line": 107, + "snippet": "log.info(\"[module-cleanup] skip because another instance holds the distributed lock\");" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ModuleHistoryCleanupService.java", + "line": 111, + "snippet": "if (!moduleCleanupProperties.isEnabled()) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ModuleHistoryCleanupService.java", + "line": 114, + "snippet": "List moduleTypes = moduleCleanupProperties.getModuleTypes();" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ModuleHistoryCleanupService.java", + "line": 118, + "snippet": "LocalDateTime cutoff = LocalDateTime.now().minusDays(Math.max(0, moduleCleanupProperties.getRetentio" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ModuleHistoryCleanupService.java", + "line": 119, + "snippet": "int batchSize = moduleCleanupProperties.getBatchSize();" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ModuleHistoryCleanupService.java", + "line": 169, + "snippet": "log.info(\"[module-cleanup] batch: taskIds={}, deletedRows={}, collectedPointers={}\"," + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ModuleHistoryCleanupService.java", + "line": 177, + "snippet": "log.warn(\"[module-cleanup] keyset cursor did not advance, abort loop cursor={}\", cursor);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ModuleHistoryCleanupService.java", + "line": 182, + "snippet": "log.info(\"[module-cleanup] completed: moduleTypes={}, retentionDays={}, cutoff={}, batches={}, delet" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ModuleHistoryCleanupService.java", + "line": 183, + "snippet": "moduleTypes, moduleCleanupProperties.getRetentionDays(), cutoff," + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ModuleHistoryCleanupService.java", + "line": 191, + "snippet": "private int deleteRows(List moduleTypes, List cleanupTaskIds, List collectDataTa" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ModuleHistoryCleanupService.java", + "line": 194, + "snippet": ".in(TaskFileJobEntity::getTaskId, cleanupTaskIds));" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ModuleHistoryCleanupService.java", + "line": 198, + "snippet": ".in(TaskResultItemEntity::getTaskId, cleanupTaskIds));" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ModuleHistoryCleanupService.java", + "line": 202, + "snippet": ".in(TaskProgressSnapshotEntity::getTaskId, cleanupTaskIds));" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ModuleHistoryCleanupService.java", + "line": 206, + "snippet": ".in(TaskResultPayloadEntity::getTaskId, cleanupTaskIds));" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ModuleHistoryCleanupService.java", + "line": 210, + "snippet": ".in(TaskScopeStateEntity::getTaskId, cleanupTaskIds));" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ModuleHistoryCleanupService.java", + "line": 214, + "snippet": ".in(TaskChunkEntity::getTaskId, cleanupTaskIds));" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ModuleHistoryCleanupService.java", + "line": 223, + "snippet": ".in(FileResultEntity::getTaskId, cleanupTaskIds));" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ModuleHistoryCleanupService.java", + "line": 226, + "snippet": ".in(FileTaskEntity::getId, cleanupTaskIds)" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ModuleHistoryCleanupService.java", + "line": 232, + "snippet": ".in(FileTaskEntity::getId, cleanupTaskIds));" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ModuleHistoryCleanupService.java", + "line": 260, + "snippet": "private List collectPayloadPointers(List moduleTypes, List cleanupTaskIds, int" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ModuleHistoryCleanupService.java", + "line": 264, + "snippet": ".in(TaskChunkEntity::getTaskId, cleanupTaskIds));" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ModuleHistoryCleanupService.java", + "line": 270, + "snippet": ".in(TaskScopeStateEntity::getTaskId, cleanupTaskIds));" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ModuleHistoryCleanupService.java", + "line": 276, + "snippet": "log.warn(\"[module-cleanup] payload pointer collection truncated at max={}\", max);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/PatrolDeleteResultFileJobHandler.java", + "line": 32, + "snippet": "public void cleanup(TaskFileJobEntity job) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/PriceTrackResultFileJobHandler.java", + "line": 32, + "snippet": "public void cleanup(TaskFileJobEntity job) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ProductRiskResultFileJobHandler.java", + "line": 32, + "snippet": "public void cleanup(TaskFileJobEntity job) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/PublishResultFileJobHandler.java", + "line": 8, + "snippet": "* cleanup 委托 PublishTaskService.cleanupResultFileJob(不走 payload.deleteLatest);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/PublishResultFileJobHandler.java", + "line": 31, + "snippet": "public void cleanup(TaskFileJobEntity job) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/PublishResultFileJobHandler.java", + "line": 32, + "snippet": "publishTaskService.cleanupResultFileJob(job);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/QueryAsinResultFileJobHandler.java", + "line": 32, + "snippet": "public void cleanup(TaskFileJobEntity job) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ResultFileJobHandler.java", + "line": 10, + "snippet": "* cleanup 在 Job 成功后调用(原 cleanupAfterSuccess 分支);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ResultFileJobHandler.java", + "line": 24, + "snippet": "default void cleanup(TaskFileJobEntity job) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ShopDataCrawlResultFileJobHandler.java", + "line": 8, + "snippet": "* cleanup 两处:payload.deleteLatest + 服务内 cleanupResultFileJob(原分支语义);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ShopDataCrawlResultFileJobHandler.java", + "line": 34, + "snippet": "public void cleanup(TaskFileJobEntity job) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ShopDataCrawlResultFileJobHandler.java", + "line": 36, + "snippet": "shopDataCrawlTaskService.cleanupResultFileJob(job);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ShopMatchResultFileJobHandler.java", + "line": 9, + "snippet": "* cleanup 删除该任务最新 payload(原 cleanupAfterSuccess 分支语义)。" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/ShopMatchResultFileJobHandler.java", + "line": 34, + "snippet": "public void cleanup(TaskFileJobEntity job) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/SimilarAsinResultFileJobHandler.java", + "line": 30, + "snippet": "public void cleanup(TaskFileJobEntity job) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/SimilarAsinResultFileJobHandler.java", + "line": 31, + "snippet": "similarAsinTaskService.cleanupResultFileJob(job);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskImageCacheCleanupService.java", + "line": 17, + "snippet": "public class TaskImageCacheCleanupService {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskImageCacheCleanupService.java", + "line": 19, + "snippet": "private static final Duration CLEANUP_LOCK_TTL = Duration.ofMinutes(30);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskImageCacheCleanupService.java", + "line": 22, + "snippet": "private final TaskImageCacheCleanupProperties cleanupProperties;" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskImageCacheCleanupService.java", + "line": 25, + "snippet": "@Scheduled(cron = \"${aiimage.task-image-cache-cleanup.cron:0 30 2 * * *}\")" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskImageCacheCleanupService.java", + "line": 26, + "snippet": "public void cleanupExpiredImageCache() {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskImageCacheCleanupService.java", + "line": 27, + "snippet": "if (!cleanupProperties.isEnabled()) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskImageCacheCleanupService.java", + "line": 31, + "snippet": "distributedJobLockService.tryLock(\"task-image-cache:cleanup\", CLEANUP_LOCK_TTL);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskImageCacheCleanupService.java", + "line": 33, + "snippet": "log.info(\"[task-image-cache-cleanup] skip because another instance holds the distributed lock\");" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskImageCacheCleanupService.java", + "line": 37, + "snippet": "int retentionDays = Math.max(1, cleanupProperties.getRetentionDays());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskImageCacheCleanupService.java", + "line": 38, + "snippet": "int batchSize = Math.max(1, cleanupProperties.getBatchSize());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskImageCacheCleanupService.java", + "line": 39, + "snippet": "int maxBatches = Math.max(1, cleanupProperties.getMaxBatchesPerRun());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskImageCacheCleanupService.java", + "line": 51, + "snippet": "if (!lockHandle.renew(CLEANUP_LOCK_TTL)) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskImageCacheCleanupService.java", + "line": 52, + "snippet": "log.warn(\"[task-image-cache-cleanup] stop because lock renew failed deletedTotal={} batches={}\"," + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskImageCacheCleanupService.java", + "line": 61, + "snippet": "long maxBytes = cleanupProperties.getMaxBytes();" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskImageCacheCleanupService.java", + "line": 62, + "snippet": "long targetBytes = cleanupProperties.getTargetBytes();" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskImageCacheCleanupService.java", + "line": 81, + "snippet": "if (!lockHandle.renew(CLEANUP_LOCK_TTL)) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskImageCacheCleanupService.java", + "line": 82, + "snippet": "log.warn(\"[task-image-cache-cleanup] stop capacity cleanup because lock renew failed deletedTotal={}" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskImageCacheCleanupService.java", + "line": 94, + "snippet": "log.info(\"[task-image-cache-cleanup] finished cutoff={} retentionDays={} expiredDeleted={} expiredBa" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskImageCacheCleanupService.java", + "line": 99, + "snippet": "log.warn(\"[task-image-cache-cleanup] failed msg={}\", ex.getMessage(), ex);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorker.java", + "line": 225, + "snippet": "cleanupAfterSuccess(job);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorker.java", + "line": 351, + "snippet": "private void cleanupAfterSuccess(TaskFileJobEntity job) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskResultFileJobWorker.java", + "line": 354, + "snippet": "handler.cleanup(job);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskResultItemService.java", + "line": 109, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(row.getPayloadJson());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskResultItemService.java", + "line": 140, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(row.getPayloadJson());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskResultItemService.java", + "line": 206, + "snippet": "transientPayloadStorageService.deleteReplacedPayloadIfNeeded(storedPayload, existing.getPayloadJson(" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskResultItemService.java", + "line": 209, + "snippet": "transientPayloadStorageService.deleteReplacedPayloadIfNeeded(existing.getPayloadJson(), storedPayloa" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskResultPayloadService.java", + "line": 64, + "snippet": "transientPayloadStorageService.deleteReplacedPayloadIfNeeded(existing.getPayloadJson(), storedPayloa" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskResultPayloadService.java", + "line": 99, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(existing.getPayloadJson());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskScopePayloadBufferMaintenanceService.java", + "line": 27, + "snippet": "private static final Duration CLEANUP_LOCK_TTL = Duration.ofMinutes(10);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskScopePayloadBufferMaintenanceService.java", + "line": 57, + "snippet": "Files.deleteIfExists(file);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskScopePayloadBufferMaintenanceService.java", + "line": 73, + "snippet": "@Scheduled(cron = \"${aiimage.task-pressure.scope-payload-cleanup-cron:15 */30 * * * *}\")" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskScopePayloadBufferMaintenanceService.java", + "line": 74, + "snippet": "public void cleanupExpiredBufferedPayloads() {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskScopePayloadBufferMaintenanceService.java", + "line": 76, + "snippet": "distributedJobLockService.tryLock(\"task-scope-buffer:cleanup\", CLEANUP_LOCK_TTL);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskScopePayloadBufferMaintenanceService.java", + "line": 78, + "snippet": "log.info(\"[task-scope-buffer] skip cleanup because another instance holds the lock\");" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskScopePayloadBufferMaintenanceService.java", + "line": 94, + "snippet": "Files.deleteIfExists(file);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskScopePayloadBufferMaintenanceService.java", + "line": 98, + "snippet": "log.warn(\"[task-scope-buffer] cleanup failed path={} msg={}\", file, ex.getMessage());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskScopePayloadBufferMaintenanceService.java", + "line": 102, + "snippet": "log.info(\"[task-scope-buffer] cleanup finished deleted={} root={}\", deleted, root);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskScopePayloadBufferMaintenanceService.java", + "line": 163, + "snippet": "Files.deleteIfExists(current);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskScopePayloadStorageService.java", + "line": 54, + "snippet": "transientPayloadStorageService.deleteReplacedPayloadIfNeeded(replacedPayload, stateJson);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskScopePayloadStorageService.java", + "line": 67, + "snippet": "log.warn(\"[task-scope-payload] skip failed-save cleanup because reference check failed taskId={} mod" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskScopePayloadStorageService.java", + "line": 71, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(uploadedPayload);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskScopePayloadStorageService.java", + "line": 84, + "snippet": "log.warn(\"[task-scope-payload] skip failed-save cleanup because current state pointer is unreadable " + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskScopePayloadStorageService.java", + "line": 184, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(state.getStateJson());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskScopePayloadStorageService.java", + "line": 233, + "snippet": "transientPayloadStorageService.deletePayloadIfPresent(state.getStateJson());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TaskScopePayloadStorageService.java", + "line": 294, + "snippet": "transientPayloadStorageService.deleteReplacedPayloadIfNeeded(state.getParsedPayloadJson(), storedPar" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TransientPayloadStorageService.java", + "line": 86, + "snippet": "&& (rustfsObjectStorageService.isConfigured() || storageProperties.getLocalTempDir() != null);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TransientPayloadStorageService.java", + "line": 165, + "snippet": "public void deletePayloadIfPresent(String value) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TransientPayloadStorageService.java", + "line": 203, + "snippet": "* 老路径 caller 把自己那行覆盖/删除后立即调用 {@link #deletePayloadIfPresent}," + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TransientPayloadStorageService.java", + "line": 265, + "snippet": "deletePayloadIfPresent(oldPointer);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TransientPayloadStorageService.java", + "line": 526, + "snippet": "Files.deleteIfExists(resolveLocalPayloadPath(objectKey));" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/TransientPayloadStorageService.java", + "line": 542, + "snippet": "String configuredRoot = storageProperties.getLocalTempDir();" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/WithdrawResultFileJobHandler.java", + "line": 9, + "snippet": "* cleanup 走 payload.deleteLatest。" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/service/WithdrawResultFileJobHandler.java", + "line": 42, + "snippet": "public void cleanup(TaskFileJobEntity job) {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/util/TaskEntityLocalCache.java", + "line": 88, + "snippet": "@Scheduled(fixedDelayString = \"${aiimage.task-pressure.local-task-entity-cache-cleanup-delay-ms:6000" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/task/util/TaskEntityLocalCache.java", + "line": 89, + "snippet": "public void cleanup() {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/withdraw/service/WithdrawTaskService.java", + "line": 432, + "snippet": "FileUtil.del(xlsx);" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/ziniao/memory/service/ZiniaoTransientCacheService.java", + "line": 92, + "snippet": "cleanupExpiredEntries(LocalDateTime.now());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/ziniao/memory/service/ZiniaoTransientCacheService.java", + "line": 121, + "snippet": "@Scheduled(fixedDelayString = \"${aiimage.ziniao.transient-cache-cleanup-delay-ms:60000}\")" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/ziniao/memory/service/ZiniaoTransientCacheService.java", + "line": 122, + "snippet": "void cleanupExpiredEntriesScheduled() {" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/ziniao/memory/service/ZiniaoTransientCacheService.java", + "line": 123, + "snippet": "cleanupExpiredEntries(LocalDateTime.now());" + }, + { + "file": "src/main/java/com/nanri/aiimage/modules/ziniao/memory/service/ZiniaoTransientCacheService.java", + "line": 127, + "snippet": "private void cleanupExpiredEntries(LocalDateTime now) {" + } + ] +} \ No newline at end of file diff --git a/backend-java/scripts/temp_config_audit.py b/backend-java/scripts/temp_config_audit.py new file mode 100644 index 00000000..28758ce4 --- /dev/null +++ b/backend-java/scripts/temp_config_audit.py @@ -0,0 +1,113 @@ +"""task-148 临时目录配置盘点工具。 + +盘点 backend-java 的临时文件相关配置(application.yml 中的路径/前缀/保留期) +与既有清理逻辑调用点,产出机器可读清单供审计文档使用。本工具只读,不改代码。 +""" + +from __future__ import annotations + +import argparse +import json +import re +import sys +from dataclasses import dataclass, field +from pathlib import Path + +REPO_ROOT = Path(__file__).resolve().parent.parent +YML_PATH = REPO_ROOT / "src/main/resources/application.yml" +MAIN_ROOT = REPO_ROOT / "src/main/java" + +# 临时文件相关配置键(application.yml 键名匹配) +CONFIG_KEY_RE = re.compile( + r"(local-temp-dir|retention-hours|retention-days|temp-dir|transient-payload|" + r"payload-|upload-|source-retention|result-retention|tmp|buffer-retention)", + re.IGNORECASE, +) +# 既有清理逻辑调用点(临时文件清理) +CLEANUP_RE = re.compile( + r"(deleteIfExists|Files\.delete|cleanup|deleteTemp|tempDir|transientPayloadStorageService\.delete|" + r"\.del\(|FileUtil\.del|cleanupPrepared|deletePayloadIfPresent)", + re.IGNORECASE, +) + + +def extract_configs() -> list[dict]: + """从 application.yml 提取临时文件相关配置项。""" + if not YML_PATH.is_file(): + return [] + configs: list[dict] = [] + for line_no, line in enumerate( + YML_PATH.read_text(encoding="utf-8").splitlines(), start=1 + ): + stripped = line.strip() + if not stripped or stripped.startswith("#"): + continue + match = re.match(r"^([\w.-]+):\s*(.*)$", stripped) + if not match: + continue + key, value = match.group(1), match.group(2).strip() + if CONFIG_KEY_RE.search(key): + configs.append( + { + "key": key, + "value": value, + "line": line_no, + "source": "application.yml", + } + ) + return configs + + +def extract_cleanup_calls() -> list[dict]: + """扫描 main 源码中临时文件清理调用点。""" + calls: list[dict] = [] + for java_file in sorted(MAIN_ROOT.rglob("*.java")): + text = java_file.read_text(encoding="utf-8") + for line_no, line in enumerate(text.splitlines(), start=1): + if CLEANUP_RE.search(line) and "import " not in line: + calls.append( + { + "file": str(java_file.relative_to(REPO_ROOT)).replace( + "\\", "/" + ), + "line": line_no, + "snippet": line.strip()[:100], + } + ) + return calls + + +@dataclass +class Report: + configs: list[dict] = field(default_factory=list) + cleanup_calls: list[dict] = field(default_factory=list) + + def to_dict(self) -> dict: + return {"configs": self.configs, "cleanup_calls": self.cleanup_calls} + + +def scan() -> Report: + return Report(configs=extract_configs(), cleanup_calls=extract_cleanup_calls()) + + +def main() -> None: + parser = argparse.ArgumentParser(description="临时目录配置盘点") + parser.add_argument("--json", help="输出 JSON 报告路径(默认 stdout)") + args = parser.parse_args() + + report = scan() + payload = report.to_dict() + if args.json: + Path(args.json).write_text( + json.dumps(payload, ensure_ascii=False, indent=2), encoding="utf-8" + ) + else: + print(json.dumps(payload, ensure_ascii=False, indent=2)) + print( + f"configs: {len(payload['configs'])}, cleanup calls: {len(payload['cleanup_calls'])}", + file=sys.stderr, + ) + + +if __name__ == "__main__": + main() diff --git a/backend-java/scripts/test_temp_config_audit.py b/backend-java/scripts/test_temp_config_audit.py new file mode 100644 index 00000000..9a4199c7 --- /dev/null +++ b/backend-java/scripts/test_temp_config_audit.py @@ -0,0 +1,89 @@ +"""task-148 临时目录配置盘点测试。 + +对应 plan 09 任务 148 的 8 条用例: +1. test_config_listed 配置项清单齐全 +2. test_temp_root_defined 临时根目录定义 +3. test_retention_period 保留期定义 +4. test_payload_prefixes payload 前缀 +5. test_upload_dir 上传目录 +6. test_existing_cleanup_noted 现有清理逻辑记录 +7. test_doc_committed 文档存在 +8. test_no_code_change 零代码变更 +""" + +from __future__ import annotations + +import json +import subprocess +import unittest + +from temp_config_audit import REPO_ROOT, extract_cleanup_calls, extract_configs, scan + +DOC_PATH = REPO_ROOT / "docs" / "temp-file-config-audit.md" + + +class TempConfigAuditTest(unittest.TestCase): + def test_config_listed(self): + configs = extract_configs() + self.assertGreaterEqual(len(configs), 8, "配置项清单必须齐全") + for item in configs: + for key in ("key", "value", "line", "source"): + self.assertIn(key, item) + + def test_temp_root_defined(self): + keys = {c["key"] for c in extract_configs()} + self.assertTrue( + any("local-temp-dir" in k for k in keys), + f"临时根目录配置缺失: {sorted(keys)}", + ) + + def test_retention_period(self): + keys = {c["key"] for c in extract_configs()} + self.assertTrue(any("retention" in k for k in keys), "保留期配置缺失") + + def test_payload_prefixes(self): + keys = {c["key"] for c in extract_configs()} + self.assertTrue( + any("transient-payload" in k for k in keys), "transient payload 配置缺失" + ) + + def test_upload_dir(self): + configs = extract_configs() + self.assertTrue( + any( + "upload" in c["key"].lower() or "tmp" in c["key"].lower() + for c in configs + ), + "上传/临时目录配置缺失", + ) + + def test_existing_cleanup_noted(self): + calls = extract_cleanup_calls() + self.assertGreater(len(calls), 0, "必须记录既有清理调用点") + files = {c["file"] for c in calls} + self.assertGreaterEqual(len(files), 3, "清理调用应覆盖多个文件") + + def test_doc_committed(self): + self.assertTrue(DOC_PATH.is_file(), f"盘点文档缺失: {DOC_PATH}") + text = DOC_PATH.read_text(encoding="utf-8") + self.assertIn("临时", text) + self.assertIn("保留期", text) + + def test_no_code_change(self): + changed = subprocess.run( + ["git", "diff", "--name-only", "HEAD", "--", "backend-java/src"], + cwd=REPO_ROOT, + capture_output=True, + text=True, + check=True, + ).stdout.strip() + self.assertEqual(changed, "", f"生产代码被改动: {changed}") + + def test_scan_repeatable(self): + first = json.dumps(scan().to_dict(), sort_keys=True) + second = json.dumps(scan().to_dict(), sort_keys=True) + self.assertEqual(first, second, "盘点结果可重复") + + +if __name__ == "__main__": + unittest.main()