update controller chunk endpoints
Test Workflow / test (push) Successful in 3s

This commit is contained in:
vladp
2025-12-17 22:31:30 +07:00
parent 11a7ab6a73
commit a030837d45
21 changed files with 740 additions and 163 deletions
@@ -0,0 +1,243 @@
package ru.soune.nocopy.handler;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.BindingResult;
import ru.soune.nocopy.dto.*;
import ru.soune.nocopy.dto.file.*;
import ru.soune.nocopy.entity.AuthToken;
import ru.soune.nocopy.entity.file.FileType;
import ru.soune.nocopy.entity.file.FileUploadSession;
import ru.soune.nocopy.exception.*;
import ru.soune.nocopy.handler.validator.FileUploadRequestValidator;
import ru.soune.nocopy.repository.AuthTokenRepository;
import ru.soune.nocopy.repository.FileUploadSessionRepository;
import ru.soune.nocopy.service.file.FileUploadService;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
@Slf4j
@Component
@RequiredArgsConstructor
public class FileUploadHandler implements RequestHandler {
private final FileUploadService fileUploadService;
private final AuthTokenRepository authTokenRepository;
private final FileUploadSessionRepository fileUploadSessionRepository;
private final ObjectMapper objectMapper;
private final FileUploadRequestValidator fileUploadRequestValidator;
@Override
public BaseResponse handle(BaseRequest request) {
try {
FileUploadRequest fileRequest = objectMapper.convertValue(
request.getMessageBody(), FileUploadRequest.class);
String action = fileRequest.getAction();
switch (action) {
case "init":
return handleInitUpload(request, fileRequest);
case "file_types":
return handleGetFileTypes(request);
case "chunks":
return handleGetChunkStatus(request, fileRequest);
case "cancel":
return handleCancelUpload(request, fileRequest);
case "progress":
return handleGetProgress(request, fileRequest);
case "retry":
return handleRetryUpload(request, fileRequest);
default:
ActionResponse response = ActionResponse.builder()
.action(action)
.availableActions(Arrays.asList("init", "file_types", "chunks", "cancel", "progress", "retry"))
.build();
return new BaseResponse(request.getMsgId(), MessageCode.INVALID_ACTION.getCode(),
"Invalid action: " + action, response);
}
} catch (Exception e) {
log.error("Error in FileUploadHandler", e);
return new BaseResponse(request.getMsgId(), MessageCode.FILE_UPLOAD_ERROR.getCode(),
"Handler error: " + e.getMessage(), null);
}
}
private BaseResponse handleInitUpload(BaseRequest request, FileUploadRequest fileRequest) {
try {
String token = fileRequest.getToken();
Optional<AuthToken> tokenOptional = authTokenRepository.findByToken(token);
AuthToken authToken = tokenOptional.orElseThrow(() -> new NotFoundAuthToken("Token not found"));
BindingResult bindingResult = new BeanPropertyBindingResult(fileRequest, "fileRequest");
fileUploadRequestValidator.validate(fileRequest, bindingResult);
if (bindingResult.hasErrors()) {
throw new ValidationException(bindingResult, request.getMsgId());
}
FileUploadSession session = fileUploadService.initUpload(
authToken.getUser().getId(),
fileRequest.getFileName(),
fileRequest.getFileType(),
fileRequest.getExtension(),
fileRequest.getFileSize());
InitFileResponse fileResponse = InitFileResponse.builder()
.uploadId(session.getUploadId())
.fileName(session.getFileName())
.totalChunks(session.getTotalChunks())
.chunkSize(session.getChunkSize())
.status(session.getStatus().toString())
.build();
return new BaseResponse(request.getMsgId(), MessageCode.SUCCESS.getCode(),
MessageCode.SUCCESS.getDescription(), fileResponse);
} catch (NotFoundAuthToken e) {
InitFileResponse initFileResponse = InitFileResponse.builder()
.build();
throw new NotValidFieldException("Invalid or expired token: " + fileRequest.getToken(),
new BaseResponse(request.getMsgId(), MessageCode.INVALID_TOKEN.getCode(),
MessageCode.INVALID_TOKEN.getDescription(), initFileResponse));
}
}
private BaseResponse handleGetProgress(BaseRequest request, FileUploadRequest fileRequest) {
try {
ru.soune.nocopy.dto.file.UploadProgressResponse progress =
fileUploadService.getUploadProgress(fileRequest.getUploadId());
UploadProgressResponse responseDto = UploadProgressResponse.builder()
.uploadId(progress.getUploadId())
.fileName(progress.getFileName())
.totalChunks(progress.getTotalChunks())
.uploadedChunks(progress.getUploadedChunks())
.status(progress.getStatus())
.progressPercentage(progress.getProgressPercentage())
.filePath(progress.getFilePath())
.build();
return new BaseResponse(request.getMsgId(), MessageCode.SUCCESS.getCode(),
MessageCode.SUCCESS.getDescription(), responseDto);
} catch (UploadSessionNotFoundException e) {
return new BaseResponse(request.getMsgId(), MessageCode.FILE_NOT_FOUND.getCode(),
MessageCode.FILE_NOT_FOUND.getDescription(), null);
} catch (Exception e) {
log.error("Error getting progress", e);
return new BaseResponse(request.getMsgId(), MessageCode.FILE_UPLOAD_ERROR.getCode(),
MessageCode.FILE_UPLOAD_ERROR.getDescription(), null);
}
}
private BaseResponse handleCancelUpload(BaseRequest request, FileUploadRequest fileRequest) {
try {
fileUploadService.cancelUpload(fileRequest.getUploadId());
CanceledUploadResponse response = CanceledUploadResponse.builder()
.uploadId(fileRequest.getUploadId())
.message("Upload cancelled successfully")
.build();
return new BaseResponse(request.getMsgId(), MessageCode.SUCCESS.getCode(),
"Upload cancelled successfully", response);
} catch (UploadSessionNotFoundException e) {
return new BaseResponse(request.getMsgId(), MessageCode.FILE_NOT_FOUND.getCode(),
"Upload session not found", null);
} catch (FileUploadException e) {
return new BaseResponse(request.getMsgId(), MessageCode.FILE_UPLOAD_ERROR.getCode(), e.getMessage(), null);
} catch (Exception e) {
log.error("Error cancelling upload", e);
return new BaseResponse(request.getMsgId(), MessageCode.FILE_UPLOAD_ERROR.getCode(),
"Failed to cancel upload", null);
}
}
private BaseResponse handleRetryUpload(BaseRequest request, FileUploadRequest fileRequest) {
try {
fileUploadService.retryFailedUpload(fileRequest.getUploadId());
ru.soune.nocopy.dto.file.UploadProgressResponse progress =
fileUploadService.getUploadProgress(fileRequest.getUploadId());
RetryUploadResponse response = RetryUploadResponse.builder()
.uploadId(progress.getUploadId())
.message("Upload retry initiated")
.status(progress.getStatus().toString())
.build();
return new BaseResponse(request.getMsgId(), MessageCode.SUCCESS.getCode(), "Upload retry initiated",
response);
} catch (UploadSessionNotFoundException e) {
return new BaseResponse(request.getMsgId(), MessageCode.FILE_NOT_FOUND.getCode(),
"Upload session not found", null);
} catch (FileUploadException e) {
return new BaseResponse(request.getMsgId(), MessageCode.FILE_UPLOAD_ERROR.getCode(), e.getMessage(),
null);
} catch (Exception e) {
log.error("Error retrying upload", e);
return new BaseResponse(request.getMsgId(), MessageCode.FILE_UPLOAD_ERROR.getCode(),
"Failed to retry upload", null);
}
}
private BaseResponse handleGetChunkStatus(BaseRequest request, FileUploadRequest fileRequest) {
try {
FileUploadSession session = fileUploadSessionRepository.findById(fileRequest.getUploadId())
.orElseThrow(() -> new UploadSessionNotFoundException(fileRequest.getUploadId()));
Map<String, Boolean> chunkStatus = new HashMap<>();
for (int i = 0; i < session.getTotalChunks(); i++) {
chunkStatus.put("chunk_" + i, session.getChunkPaths().containsKey(i));
}
ChunkStatusResponse response = ChunkStatusResponse.builder()
.uploadId(fileRequest.getUploadId())
.totalChunks(session.getTotalChunks())
.uploadedChunks(session.getChunksUploaded())
.missingChunks(session.getTotalChunks() - session.getChunksUploaded())
.chunkStatus(chunkStatus)
.build();
return new BaseResponse(request.getMsgId(), MessageCode.SUCCESS.getCode(),
MessageCode.SUCCESS.getDescription(), response);
} catch (UploadSessionNotFoundException e) {
return new BaseResponse(request.getMsgId(), MessageCode.FILE_NOT_FOUND.getCode(),
"Upload session not found", null);
} catch (Exception e) {
log.error("Error getting chunk status", e);
return new BaseResponse(request.getMsgId(),
MessageCode.FILE_UPLOAD_ERROR.getCode(), "Failed to get chunk status",
null);
}
}
private BaseResponse handleGetFileTypes(BaseRequest request) {
try {
FileTypesResponse response = FileTypesResponse.builder()
.fileTypes(Arrays.asList(FileType.values()))
.count(FileType.values().length)
.build();
return new BaseResponse(request.getMsgId(), MessageCode.SUCCESS.getCode(),
MessageCode.SUCCESS.getDescription(), response);
} catch (Exception e) {
log.error("Error getting file types", e);
return new BaseResponse(request.getMsgId(), MessageCode.FILE_UPLOAD_ERROR.getCode(),
"Failed to get file types", null);
}
}
}