Deleting download logs for deleted files

This commit is contained in:
Rostislav Raykov
2025-01-11 17:09:57 +02:00
parent a64bf10036
commit adda1a77b3
4 changed files with 27 additions and 18 deletions

View File

@@ -2,6 +2,7 @@ package org.rostislav.quickdrop.repository;
import org.rostislav.quickdrop.entity.DownloadLog;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import java.util.List;
@@ -14,4 +15,8 @@ public interface DownloadLogRepository extends JpaRepository<DownloadLog, Long>
long countDownloadsByFileId(String uuid);
List<DownloadLog> findByFileUuid(String fileUUID);
@Modifying
@Query("DELETE FROM DownloadLog dl WHERE dl.file.id = :id")
void deleteByFileId(Long id);
}

View File

@@ -1,6 +1,7 @@
package org.rostislav.quickdrop.service;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.transaction.Transactional;
import org.rostislav.quickdrop.entity.DownloadLog;
import org.rostislav.quickdrop.entity.FileEntity;
import org.rostislav.quickdrop.model.FileEntityView;
@@ -20,7 +21,10 @@ import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import java.io.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
@@ -148,6 +152,10 @@ public class FileService {
logger.info("File received: {}", file.getName());
String uuid = UUID.randomUUID().toString();
while (fileRepository.findByUUID(uuid).isPresent()) {
uuid = UUID.randomUUID().toString();
}
Path targetPath = Path.of(applicationSettingsService.getFileStoragePath(), uuid);
FileEntity fileEntity = populateFileEntity(file, fileUploadRequest, uuid);
@@ -215,6 +223,7 @@ public class FileService {
return true;
}
@Transactional
public boolean deleteFile(String uuid) {
Optional<FileEntity> referenceById = fileRepository.findByUUID(uuid);
if (referenceById.isEmpty()) {
@@ -223,6 +232,7 @@ public class FileService {
FileEntity fileEntity = referenceById.get();
fileRepository.delete(fileEntity);
downloadLogRepository.deleteByFileId(fileEntity.id);
return deleteFileFromFileSystem(fileEntity.uuid);
}
@@ -468,21 +478,6 @@ public class FileService {
return false;
}
private void writeFileToStream(String uuid, OutputStream outputStream) {
Path path = Path.of(applicationSettingsService.getFileStoragePath(), uuid);
try (FileInputStream inputStream = new FileInputStream(path.toFile())) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.flush();
} catch (
Exception e) {
logger.error("Error writing file to stream: {}", e.getMessage());
}
}
private void logDownload(FileEntity fileEntity, HttpServletRequest request) {
String forwardedFor = request.getHeader("X-Forwarded-For");
String realIp = request.getHeader("X-Real-IP");

View File

@@ -1,6 +1,8 @@
package org.rostislav.quickdrop.service;
import jakarta.transaction.Transactional;
import org.rostislav.quickdrop.entity.FileEntity;
import org.rostislav.quickdrop.repository.DownloadLogRepository;
import org.rostislav.quickdrop.repository.FileRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -19,13 +21,15 @@ public class ScheduleService {
private final FileRepository fileRepository;
private final FileService fileService;
private final ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
private final DownloadLogRepository downloadLogRepository;
private ScheduledFuture<?> scheduledTask;
public ScheduleService(FileRepository fileRepository, FileService fileService) {
public ScheduleService(FileRepository fileRepository, FileService fileService, DownloadLogRepository downloadLogRepository) {
this.fileRepository = fileRepository;
this.fileService = fileService;
taskScheduler.setPoolSize(1);
taskScheduler.initialize();
this.downloadLogRepository = downloadLogRepository;
}
public void updateSchedule(String cronExpression, long maxFileLifeTime) {
@@ -39,6 +43,7 @@ public class ScheduleService {
);
}
@Transactional
public void deleteOldFiles(long maxFileLifeTime) {
logger.info("Deleting old files");
LocalDate thresholdDate = LocalDate.now().minusDays(maxFileLifeTime);
@@ -48,6 +53,7 @@ public class ScheduleService {
boolean deleted = fileService.deleteFileFromFileSystem(file.uuid);
if (deleted) {
fileRepository.delete(file);
downloadLogRepository.deleteByFileId(file.id);
} else {
logger.error("Failed to delete file: {}", file);
}
@@ -55,12 +61,14 @@ public class ScheduleService {
logger.info("Deleted {} files", filesForDeletion.size());
}
@Transactional
@Scheduled(cron = "0 0 3 * * *")
public void cleanDatabaseFromDeletedFiles() {
logger.info("Cleaning database from deleted files");
fileRepository.findAll().forEach(file -> {
if (!fileService.fileExistsInFileSystem(file.uuid)) {
fileRepository.delete(file);
downloadLogRepository.deleteByFileId(file.id);
}
});
}

View File

@@ -43,7 +43,8 @@
<div class="card-body">
<div class="row">
<div class="col-md-6">
<h5>Total Downloads</h5>
<h5 class="mb-0">Total Downloads</h5>
<small class="text-muted">Doesn't count deleted files</small>
<p class="text-muted" th:text="${analytics.totalDownloads}">0</p>
</div>
<div class="col-md-6">