Time out attempt

This commit is contained in:
pratik
2025-10-22 09:16:31 -05:00
parent b81ab51100
commit 34567cd813
2 changed files with 84 additions and 17 deletions

View File

@@ -2,10 +2,12 @@ package com.cfdeployer;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication @SpringBootApplication
@EnableScheduling @EnableScheduling
@EnableAsync
public class CfDeployerApplication { public class CfDeployerApplication {
public static void main(String[] args) { public static void main(String[] args) {

View File

@@ -4,6 +4,8 @@ import com.cfdeployer.model.CfDeployRequest;
import com.cfdeployer.model.CfDeployResponse; import com.cfdeployer.model.CfDeployResponse;
import com.cfdeployer.model.ChunkUploadRequest; import com.cfdeployer.model.ChunkUploadRequest;
import com.cfdeployer.model.ChunkUploadResponse; import com.cfdeployer.model.ChunkUploadResponse;
import com.cfdeployer.model.DeploymentStatus;
import com.cfdeployer.service.AsyncDeploymentService;
import com.cfdeployer.service.CfCliService; import com.cfdeployer.service.CfCliService;
import com.cfdeployer.service.ChunkedUploadService; import com.cfdeployer.service.ChunkedUploadService;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
@@ -26,6 +28,7 @@ public class CfDeployController {
private final CfCliService cfCliService; private final CfCliService cfCliService;
private final ChunkedUploadService chunkedUploadService; private final ChunkedUploadService chunkedUploadService;
private final AsyncDeploymentService asyncDeploymentService;
private final ObjectMapper objectMapper; private final ObjectMapper objectMapper;
@PostMapping(value = "/deploy", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) @PostMapping(value = "/deploy", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@@ -180,19 +183,29 @@ public class CfDeployController {
} }
@PostMapping("/upload/finalize") @PostMapping("/upload/finalize")
public ResponseEntity<CfDeployResponse> finalizeUpload(@RequestParam("uploadSessionId") String uploadSessionId) { public ResponseEntity<DeploymentStatus> finalizeUpload(
@RequestParam("uploadSessionId") String uploadSessionId,
@RequestParam(value = "async", defaultValue = "true") boolean async) {
try { try {
log.info("Finalizing upload for session: {}", uploadSessionId); log.info("Finalizing upload for session: {} (async={})", uploadSessionId, async);
if (!chunkedUploadService.isSessionReady(uploadSessionId)) { if (!chunkedUploadService.isSessionReady(uploadSessionId)) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST) return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(CfDeployResponse.failure("Upload incomplete. Not all file chunks received.", null)); .body(DeploymentStatus.builder()
.uploadSessionId(uploadSessionId)
.status(DeploymentStatus.Status.FAILED)
.message("Upload incomplete. Not all file chunks received.")
.build());
} }
var session = chunkedUploadService.getSession(uploadSessionId); var session = chunkedUploadService.getSession(uploadSessionId);
if (session == null) { if (session == null) {
return ResponseEntity.status(HttpStatus.NOT_FOUND) return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(CfDeployResponse.failure("Upload session not found or expired", null)); .body(DeploymentStatus.builder()
.uploadSessionId(uploadSessionId)
.status(DeploymentStatus.Status.FAILED)
.message("Upload session not found or expired")
.build());
} }
CfDeployRequest request = objectMapper.readValue(session.getRequestJson(), CfDeployRequest.class); CfDeployRequest request = objectMapper.readValue(session.getRequestJson(), CfDeployRequest.class);
@@ -203,25 +216,77 @@ public class CfDeployController {
var jarState = session.getFileStates().get("jarFile"); var jarState = session.getFileStates().get("jarFile");
var manifestState = session.getFileStates().get("manifest"); var manifestState = session.getFileStates().get("manifest");
CfDeployResponse response = cfCliService.deployApplicationFromPaths( if (async) {
request, // Start async deployment - returns immediately
jarState.getTargetPath(), asyncDeploymentService.deployAsync(uploadSessionId, request,
manifestState.getTargetPath()); jarState.getTargetPath(), manifestState.getTargetPath());
// Clean up session after deployment return ResponseEntity.accepted().body(DeploymentStatus.builder()
chunkedUploadService.deleteSession(uploadSessionId); .uploadSessionId(uploadSessionId)
.status(DeploymentStatus.Status.IN_PROGRESS)
if (Boolean.TRUE.equals(response.getSuccess())) { .message("Deployment started. Use /deployment/status endpoint to check progress.")
return ResponseEntity.ok(response); .progress(0)
.build());
} else { } else {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response); // Synchronous deployment - waits for completion (may timeout!)
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(DeploymentStatus.builder()
.uploadSessionId(uploadSessionId)
.status(DeploymentStatus.Status.COMPLETED)
.message(response.getMessage())
.output(response.getOutput())
.progress(100)
.build());
} else {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(DeploymentStatus.builder()
.uploadSessionId(uploadSessionId)
.status(DeploymentStatus.Status.FAILED)
.message(response.getMessage())
.error(response.getError())
.build());
}
} }
} catch (Exception e) { } catch (Exception e) {
log.error("Error finalizing upload", e); log.error("Error finalizing upload", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(CfDeployResponse.failure( .body(DeploymentStatus.builder()
"Failed to finalize deployment: " + e.getMessage(), .uploadSessionId(uploadSessionId)
e.toString())); .status(DeploymentStatus.Status.FAILED)
.message("Failed to finalize deployment: " + e.getMessage())
.error(e.toString())
.build());
}
}
@GetMapping("/deployment/status/{uploadSessionId}")
public ResponseEntity<DeploymentStatus> getDeploymentStatus(@PathVariable String uploadSessionId) {
try {
DeploymentStatus status = asyncDeploymentService.getDeploymentStatus(uploadSessionId);
// Clean up session and deployment status if completed or failed
if (status.getStatus() == DeploymentStatus.Status.COMPLETED ||
status.getStatus() == DeploymentStatus.Status.FAILED) {
chunkedUploadService.deleteSession(uploadSessionId);
}
return ResponseEntity.ok(status);
} catch (Exception e) {
log.error("Error getting deployment status", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(DeploymentStatus.builder()
.uploadSessionId(uploadSessionId)
.status(DeploymentStatus.Status.FAILED)
.message("Failed to get deployment status: " + e.getMessage())
.build());
} }
} }