Skip to content

Commit

Permalink
MCP-2110 PDF Generate + Fetch Queue (#871)
Browse files Browse the repository at this point in the history
* PDF Generate + Fetch

* update queue

* immediate pdf

Co-authored-by: Afsin Ustundag <[email protected]>
Co-authored-by: dimitri-amida <[email protected]>
  • Loading branch information
3 people authored Jan 13, 2023
1 parent 8967f5d commit 152c8af
Show file tree
Hide file tree
Showing 9 changed files with 115 additions and 24 deletions.
35 changes: 35 additions & 0 deletions api/src/main/java/gov/va/vro/api/resources/VroResource.java
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,41 @@ ResponseEntity<GeneratePdfResponse> generatePdf(
ResponseEntity<Object> fetchPdf(@PathVariable String claimSubmissionId)
throws MethodArgumentNotValidException, ClaimProcessingException;

@Operation(
summary = "Immediate PDF",
description =
"This endpoint generates the Evidence PDF for a specific patient and a diagnostic "
+ "code. The endpoint will return the PDF but is also available from the "
+ "'GET evidence-pdf' endpoint using claim submission id.")
@PostMapping("/immediate-pdf")
@ApiResponses(
value = {
@ApiResponse(responseCode = "200", description = "Successful Request"),
@ApiResponse(
responseCode = "400",
description = "Bad Request",
content = @Content(schema = @Schema(hidden = true))),
@ApiResponse(
responseCode = "401",
description = "Unauthorized",
content = @Content(schema = @Schema(hidden = true))),
@ApiResponse(
responseCode = "500",
description = "PDF Generator Server Error",
content = @Content(schema = @Schema(hidden = true)))
})
@Timed(value = "evidence-pdf")
@Tag(name = "Pdf Generation")
ResponseEntity<Object> immediatePdf(
@Parameter(
description = "metadata for immediatePdf",
required = true,
schema = @Schema(implementation = GeneratePdfRequest.class))
@Valid
@RequestBody
GeneratePdfRequest request)
throws MethodArgumentNotValidException, ClaimProcessingException;

@Operation(
summary = "Provides health data assessment",
description =
Expand Down
68 changes: 48 additions & 20 deletions controller/src/main/java/gov/va/vro/controller/VroController.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,34 @@ public class VroController implements VroResource {

private final ObjectMapper objectMapper = new ObjectMapper();

public ResponseEntity fetchProcess(String claimSubmissionId, String response)
throws ClaimProcessingException {
try {
FetchPdfResponse pdfResponse = objectMapper.readValue(response, FetchPdfResponse.class);
log.info("RESPONSE from fetchPdf returned status: {}", pdfResponse.getStatus());
if (pdfResponse.hasContent()) {
byte[] decoder = Base64.getDecoder().decode(pdfResponse.getPdfData());
try (InputStream is = new ByteArrayInputStream(decoder)) {
InputStreamResource resource = new InputStreamResource(is);
String diagnosis = StringUtils.capitalize(pdfResponse.getDiagnosis());
HttpHeaders headers = getHttpHeaders(diagnosis);
return new ResponseEntity<>(resource, headers, HttpStatus.OK);
}
} else {
if (pdfResponse.getStatus().equals("NOT_FOUND")) {
return new ResponseEntity<>(pdfResponse, HttpStatus.NOT_FOUND);
} else if (pdfResponse.getStatus().equals("ERROR")) {
log.info("RESPONSE from generatePdf returned error reason: {}", pdfResponse.getReason());
return new ResponseEntity<>(pdfResponse, HttpStatus.INTERNAL_SERVER_ERROR);
}
return new ResponseEntity<>(pdfResponse, HttpStatus.OK);
}
} catch (Exception ex) {
log.error("Error in fetch pdf", ex);
throw new ClaimProcessingException(claimSubmissionId, HttpStatus.INTERNAL_SERVER_ERROR, ex);
}
}

@Override
public ResponseEntity<GeneratePdfResponse> generatePdf(GeneratePdfRequest request)
throws ClaimProcessingException {
Expand Down Expand Up @@ -73,32 +101,32 @@ public ResponseEntity<Object> fetchPdf(String claimSubmissionId) throws ClaimPro
log.info("Fetching pdf for claim: {}", claimSubmissionId);
try {
String response = camelEntrance.fetchPdf(claimSubmissionId);
FetchPdfResponse pdfResponse = objectMapper.readValue(response, FetchPdfResponse.class);
log.info("RESPONSE from fetchPdf returned status: {}", pdfResponse.getStatus());
if (pdfResponse.hasContent()) {
byte[] decoder = Base64.getDecoder().decode(pdfResponse.getPdfData());
try (InputStream is = new ByteArrayInputStream(decoder)) {
InputStreamResource resource = new InputStreamResource(is);
String diagnosis = StringUtils.capitalize(pdfResponse.getDiagnosis());
HttpHeaders headers = getHttpHeaders(diagnosis);
return new ResponseEntity<>(resource, headers, HttpStatus.OK);
}

} else {
if (pdfResponse.getStatus().equals("NOT_FOUND")) {
return new ResponseEntity<>(pdfResponse, HttpStatus.NOT_FOUND);
} else if (pdfResponse.getStatus().equals("ERROR")) {
log.info("RESPONSE from generatePdf returned error reason: {}", pdfResponse.getReason());
return new ResponseEntity<>(pdfResponse, HttpStatus.INTERNAL_SERVER_ERROR);
}
return new ResponseEntity<>(pdfResponse, HttpStatus.OK);
}
return fetchProcess(claimSubmissionId, response);
} catch (Exception ex) {
log.error("Error in fetch pdf", ex);
throw new ClaimProcessingException(claimSubmissionId, HttpStatus.INTERNAL_SERVER_ERROR, ex);
}
}

@Override
public ResponseEntity<Object> immediatePdf(GeneratePdfRequest request)
throws ClaimProcessingException {
log.info(
"Generating pdf for claim: {} and diagnostic code {}",
request.getClaimSubmissionId(),
request.getDiagnosticCode());
try {
GeneratePdfPayload model = generatePdfRequestMapper.toModel(request);
log.info(model.toString());
String response = camelEntrance.immediatePdf(model);
return fetchProcess(request.getClaimSubmissionId(), response);
} catch (Exception ex) {
log.error("Error in generate fetch pdf", ex);
throw new ClaimProcessingException(
request.getClaimSubmissionId(), HttpStatus.INTERNAL_SERVER_ERROR, ex);
}
}

@Override
public ResponseEntity<FullHealthDataAssessmentResponse> postFullHealthAssessment(
HealthDataAssessmentRequest claim) throws ClaimProcessingException {
Expand Down
2 changes: 1 addition & 1 deletion service-python/pdfgenerator/src/lib/helper_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def pdf_helper_all(data):
return data


def toc_helper_all(toc_file_path, data):
def toc_helper_all(toc_file_path, data): # pragma: no cover
file_data = None

with open(toc_file_path, 'r') as file:
Expand Down
15 changes: 14 additions & 1 deletion service-python/pdfgenerator/src/lib/queues.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
EXCHANGE = queue_config["exchange_name"]
GENERATE_QUEUE = queue_config["generate_queue_name"]
FETCH_QUEUE = queue_config["fetch_queue_name"]
GENERATE_FETCH_QUEUE = queue_config["generate_fetch_queue_name"]


def on_generate_callback(channel, method, properties, body):
Expand All @@ -35,7 +36,14 @@ def on_generate_callback(channel, method, properties, body):
pdf = pdf_generator.generate_pdf_from_string(template_name, template, variables)
redis_client.save_hash_data(f"{claim_id}-pdf", mapping={"contents": base64.b64encode(pdf).decode("ascii"), "diagnosis": codes[diagnosis_code]})
logging.info(f"Claim {claim_id}: Saved PDF")
response = {"claimSubmissionId": claim_id, "status": "COMPLETE"}
# Check if the routing key is for a generate or generate and fetch
if method.routing_key == "generate-pdf":
response = {"claimSubmissionId": claim_id, "status": "COMPLETE"}
else:
pdf = redis_client.get_hash_data(f"{claim_id}-pdf", "contents")
diagnosis_name = redis_client.get_hash_data(f"{claim_id}-pdf", "diagnosis")
logging.info("Fetched PDF")
response = {"claimSubmissionId": claim_id, "status": "COMPLETE", "diagnosis": str(diagnosis_name.decode("ascii")), "pdfData": str(pdf.decode("ascii"))}
except Exception as e:
logging.error(e, exc_info=True)
response = {"claimSubmissionId": claim_id, "status": "ERROR", "reason": str(e)}
Expand Down Expand Up @@ -72,5 +80,10 @@ def queue_setup(channel):
channel.queue_declare(queue=FETCH_QUEUE, durable=True, auto_delete=True)
channel.queue_bind(queue=FETCH_QUEUE, exchange=EXCHANGE)
channel.basic_consume(queue=FETCH_QUEUE, on_message_callback=on_fetch_callback, auto_ack=True)
# Generate Fetch PDF Queue
channel.queue_declare(queue=GENERATE_FETCH_QUEUE, durable=True, auto_delete=True)
channel.queue_bind(queue=GENERATE_FETCH_QUEUE, exchange=EXCHANGE)
channel.basic_consume(queue=GENERATE_FETCH_QUEUE, on_message_callback=on_generate_callback, auto_ack=True)
logging.info(f" [*] Waiting for data for queue: {GENERATE_QUEUE}. To exit press CTRL+C")
logging.info(f" [*] Waiting for data for queue: {FETCH_QUEUE}. To exit press CTRL+C")
logging.info(f" [*] Waiting for data for queue: {GENERATE_FETCH_QUEUE}. To exit press CTRL+C")
1 change: 1 addition & 0 deletions service-python/pdfgenerator/src/lib/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"exchange_name": "pdf-generator",
"generate_queue_name": "generate-pdf",
"fetch_queue_name": "fetch-pdf",
"generate_fetch_queue_name": "generate-fetch-pdf",
}

codes = {
Expand Down
3 changes: 1 addition & 2 deletions service-python/tests/pdfgenerator/test_pdf_queues.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
from unittest.mock import Mock

import pytest

from pdfgenerator.src.lib import queues


@pytest.mark.parametrize(
"service_queue_name", ["fetch-pdf"]
"service_queue_name", ["generate-fetch-pdf"]
)
def test_queue_setup(service_queue_name):
"""Test if the proper queue gets generated."""
Expand Down
1 change: 1 addition & 0 deletions service-python/tests/pdfgenerator/test_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"exchange_name": "",
"generate_queue_name": "",
"fetch_queue_name": "",
"generate_fetch_queue_name": "",
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ public String fetchPdf(String claimSubmissionId) {
PrimaryRoutes.ENDPOINT_FETCH_PDF, claimSubmissionId, String.class);
}

public String immediatePdf(GeneratePdfPayload resource) {
return producerTemplate.requestBody(
PrimaryRoutes.ENDPOINT_GENERATE_FETCH_PDF, resource, String.class);
}

/**
* Notify automated claim.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@ public class PrimaryRoutes extends RouteBuilder {
public static final String ENDPOINT_SUBMIT_CLAIM_FULL = "direct:claim-submit-full";
public static final String ENDPOINT_GENERATE_PDF = "direct:generate-pdf";
public static final String ENDPOINT_FETCH_PDF = "direct:fetch-pdf";
public static final String ENDPOINT_GENERATE_FETCH_PDF = "direct:generate-fetch-pdf";

private static final String PDF_EXCHANGE = "pdf-generator";
private static final String GENERATE_PDF_QUEUE = "generate-pdf";
private static final String FETCH_PDF_QUEUE = "fetch-pdf";
private static final String GENERATE_FETCH_PDF_QUEUE = "generate-fetch-pdf";

// Base names for wiretap endpoints
public static final String INCOMING_CLAIM_WIRETAP = "claim-submitted";
Expand All @@ -40,6 +42,7 @@ public void configure() {
configureRouteClaimSubmitForFull();
configureRouteGeneratePdf();
configureRouteFetchPdf();
configureRouteimmediatePdf();
}

private void configureRouteClaimSubmit() {
Expand Down Expand Up @@ -81,6 +84,12 @@ private void configureRouteFetchPdf() {
from(ENDPOINT_FETCH_PDF).routeId("fetch-pdf").to(pdfRoute(FETCH_PDF_QUEUE));
}

private void configureRouteimmediatePdf() {
from(ENDPOINT_GENERATE_FETCH_PDF)
.routeId("generate-fetch-pdf")
.to(pdfRoute(GENERATE_FETCH_PDF_QUEUE));
}

private String pdfRoute(String queueName) {
return String.format("rabbitmq:%s?routingKey=%s&queue=%s", PDF_EXCHANGE, queueName, queueName);
}
Expand Down

0 comments on commit 152c8af

Please sign in to comment.