package ru.soune.nocopy.service.file; import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import java.io.IOException; import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; @Slf4j @Component @RequiredArgsConstructor public class FileCleanupService { @Value("${file.storage.base-path}") private String basePath; @Value("${file.storage.temp-ttl-hours}") private int tempTtlHours; @Scheduled(cron = "0 0 3 * * *") public void cleanupExpiredFiles() { log.info("Starting cleanup of expired temporary files"); Path tempDir = Paths.get(basePath, "temp"); if (!Files.exists(tempDir)) { return; } try { Files.walkFileTree(tempDir, new SimpleFileVisitor() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { LocalDateTime fileTime = LocalDateTime.ofInstant( Instant.ofEpochMilli(attrs.lastModifiedTime().toMillis()), ZoneId.systemDefault() ); LocalDateTime cutoffTime = LocalDateTime.now() .minusHours(tempTtlHours); if (fileTime.isBefore(cutoffTime)) { Files.delete(file); log.debug("Deleted expired file: {}", file); } return FileVisitResult.CONTINUE; } @Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { if (exc == null) { if (Files.list(dir).count() == 0 && !dir.equals(tempDir)) { Files.delete(dir); log.debug("Deleted empty directory: {}", dir); } } return FileVisitResult.CONTINUE; } }); log.info("Cleanup completed successfully"); } catch (IOException e) { log.error("Error during cleanup", e); } } }