Try out chunking
This commit is contained in:
@@ -2,7 +2,10 @@ package com.cfdeployer.controller;
|
||||
|
||||
import com.cfdeployer.model.CfDeployRequest;
|
||||
import com.cfdeployer.model.CfDeployResponse;
|
||||
import com.cfdeployer.model.ChunkUploadRequest;
|
||||
import com.cfdeployer.model.ChunkUploadResponse;
|
||||
import com.cfdeployer.service.CfCliService;
|
||||
import com.cfdeployer.service.ChunkedUploadService;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -22,6 +25,7 @@ public class CfDeployController {
|
||||
private static final Logger log = LoggerFactory.getLogger(CfDeployController.class);
|
||||
|
||||
private final CfCliService cfCliService;
|
||||
private final ChunkedUploadService chunkedUploadService;
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
@PostMapping(value = "/deploy", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@@ -118,6 +122,126 @@ public class CfDeployController {
|
||||
}
|
||||
}
|
||||
|
||||
// Chunked upload endpoints
|
||||
@PostMapping("/upload/init")
|
||||
public ResponseEntity<ChunkUploadResponse> initUpload(@RequestBody String requestJson) {
|
||||
try {
|
||||
log.info("Initializing chunked upload session");
|
||||
|
||||
// Validate the request JSON
|
||||
CfDeployRequest request = objectMapper.readValue(requestJson, CfDeployRequest.class);
|
||||
log.info("Creating upload session for app: {}", request.getAppName());
|
||||
|
||||
String sessionId = chunkedUploadService.createUploadSession(requestJson);
|
||||
|
||||
return ResponseEntity.ok(ChunkUploadResponse.builder()
|
||||
.success(true)
|
||||
.uploadSessionId(sessionId)
|
||||
.message("Upload session created successfully")
|
||||
.build());
|
||||
} catch (Exception e) {
|
||||
log.error("Error initializing upload session", e);
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
|
||||
.body(ChunkUploadResponse.failure("Failed to initialize upload: " + e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/upload/chunk")
|
||||
public ResponseEntity<ChunkUploadResponse> uploadChunk(
|
||||
@RequestParam("uploadSessionId") String uploadSessionId,
|
||||
@RequestParam("fileType") String fileType,
|
||||
@RequestParam("chunkIndex") Integer chunkIndex,
|
||||
@RequestParam("totalChunks") Integer totalChunks,
|
||||
@RequestParam(value = "fileName", required = false) String fileName,
|
||||
@RequestPart("chunk") MultipartFile chunk) {
|
||||
try {
|
||||
log.debug("Receiving chunk {}/{} for session: {}, fileType: {}",
|
||||
chunkIndex + 1, totalChunks, uploadSessionId, fileType);
|
||||
|
||||
// Validate file type
|
||||
if (!fileType.equals("jarFile") && !fileType.equals("manifest")) {
|
||||
throw new IllegalArgumentException("Invalid file type. Must be 'jarFile' or 'manifest'");
|
||||
}
|
||||
|
||||
chunkedUploadService.uploadChunk(uploadSessionId, fileType, fileName,
|
||||
chunkIndex, totalChunks, chunk);
|
||||
|
||||
var session = chunkedUploadService.getSession(uploadSessionId);
|
||||
var fileState = session.getFileStates().get(fileType);
|
||||
|
||||
return ResponseEntity.ok(ChunkUploadResponse.success(
|
||||
uploadSessionId, fileType, chunkIndex, totalChunks,
|
||||
fileState.getReceivedChunkCount()));
|
||||
} catch (Exception e) {
|
||||
log.error("Error uploading chunk", e);
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
|
||||
.body(ChunkUploadResponse.failure("Failed to upload chunk: " + e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/upload/finalize")
|
||||
public ResponseEntity<CfDeployResponse> finalizeUpload(@RequestParam("uploadSessionId") String uploadSessionId) {
|
||||
try {
|
||||
log.info("Finalizing upload for session: {}", uploadSessionId);
|
||||
|
||||
if (!chunkedUploadService.isSessionReady(uploadSessionId)) {
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
|
||||
.body(CfDeployResponse.failure("Upload incomplete. Not all file chunks received.", null));
|
||||
}
|
||||
|
||||
var session = chunkedUploadService.getSession(uploadSessionId);
|
||||
if (session == null) {
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND)
|
||||
.body(CfDeployResponse.failure("Upload session not found or expired", null));
|
||||
}
|
||||
|
||||
CfDeployRequest request = objectMapper.readValue(session.getRequestJson(), CfDeployRequest.class);
|
||||
log.info("Starting deployment for app: {} from session: {}",
|
||||
request.getAppName(), uploadSessionId);
|
||||
|
||||
// Get file paths from session
|
||||
var jarState = session.getFileStates().get("jarFile");
|
||||
var manifestState = session.getFileStates().get("manifest");
|
||||
|
||||
CfDeployResponse response = cfCliService.deployApplicationFromPaths(
|
||||
request,
|
||||
jarState.getTargetPath(),
|
||||
manifestState.getTargetPath());
|
||||
|
||||
// Clean up session after deployment
|
||||
chunkedUploadService.deleteSession(uploadSessionId);
|
||||
|
||||
if (Boolean.TRUE.equals(response.getSuccess())) {
|
||||
return ResponseEntity.ok(response);
|
||||
} else {
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Error finalizing upload", e);
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
.body(CfDeployResponse.failure(
|
||||
"Failed to finalize deployment: " + e.getMessage(),
|
||||
e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/upload/status/{uploadSessionId}")
|
||||
public ResponseEntity<?> getUploadStatus(@PathVariable String uploadSessionId) {
|
||||
try {
|
||||
var session = chunkedUploadService.getSession(uploadSessionId);
|
||||
if (session == null) {
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND)
|
||||
.body("Upload session not found or expired");
|
||||
}
|
||||
|
||||
return ResponseEntity.ok(session.getFileStates());
|
||||
} catch (Exception e) {
|
||||
log.error("Error getting upload status", e);
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
.body("Failed to get upload status: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void validateFiles(MultipartFile jarFile, MultipartFile manifest) {
|
||||
if (jarFile.isEmpty()) {
|
||||
throw new IllegalArgumentException("JAR file is empty");
|
||||
|
||||
Reference in New Issue
Block a user