diff --git a/pom.xml b/pom.xml index d78d8039..ab0d74b6 100644 --- a/pom.xml +++ b/pom.xml @@ -26,6 +26,7 @@ 29.2 true true + 2.29.52 @@ -137,6 +138,21 @@ spatial4j 0.8 + + software.amazon.awssdk + batch + ${aws.sdk.version} + + + software.amazon.awssdk + auth + ${aws.sdk.version} + + + software.amazon.awssdk + ses + ${aws.sdk.version} + diff --git a/server/pom.xml b/server/pom.xml index 8520de2f..62536ca4 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -23,12 +23,14 @@ software.amazon.awssdk batch - 2.29.52 software.amazon.awssdk auth - 2.29.52 + + + software.amazon.awssdk + ses org.springframework.boot diff --git a/server/src/main/java/au/org/aodn/ogcapi/server/core/service/ElasticSearch.java b/server/src/main/java/au/org/aodn/ogcapi/server/core/service/ElasticSearch.java index 0b62bd3b..bfed7eb1 100644 --- a/server/src/main/java/au/org/aodn/ogcapi/server/core/service/ElasticSearch.java +++ b/server/src/main/java/au/org/aodn/ogcapi/server/core/service/ElasticSearch.java @@ -26,6 +26,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.util.StopWatch; import java.io.IOException; import java.math.BigDecimal; @@ -560,6 +561,8 @@ public ElasticSearchBase.SearchResult searchFeatureSummary(String }; try { + var queryTimer = new StopWatch(); + queryTimer.start("query timer"); ElasticSearchBase.SearchResult result = new ElasticSearchBase.SearchResult<>(); result.setCollections(new ArrayList<>()); @@ -569,6 +572,10 @@ public ElasticSearchBase.SearchResult searchFeatureSummary(String ); Iterable response = pageableAggregation(builderSupplier, CompositeBucket.class, arguments, null); + queryTimer.stop(); + log.info(queryTimer.prettyPrint()); + var analyzingTimer = new StopWatch(); + analyzingTimer.start("analyzing timer"); for (CompositeBucket node : response) { if (node != null) { StacItemModel. StacItemModelBuilder model = StacItemModel.builder(); @@ -601,6 +608,8 @@ public ElasticSearchBase.SearchResult searchFeatureSummary(String result.getCollections().add(model.build()); } } + analyzingTimer.stop(); + log.info(analyzingTimer.prettyPrint()); return result; } catch (Exception e) { diff --git a/server/src/main/java/au/org/aodn/ogcapi/server/processes/RestApi.java b/server/src/main/java/au/org/aodn/ogcapi/server/processes/RestApi.java index 2bca5343..7da4067a 100644 --- a/server/src/main/java/au/org/aodn/ogcapi/server/processes/RestApi.java +++ b/server/src/main/java/au/org/aodn/ogcapi/server/processes/RestApi.java @@ -32,26 +32,31 @@ public class RestApi implements ProcessesApi { // because the produces value in the interface declaration includes "/_" which may // cause exception thrown sometimes. So i re-declared the produces value here @RequestMapping(value = "/processes/{processID}/execution", - produces = { "application/json", "text/html" }, - consumes = { "application/json" }, + produces = {"application/json", "text/html"}, + consumes = {"application/json"}, method = RequestMethod.POST) public ResponseEntity execute( - @Parameter(in = ParameterIn.PATH, required=true, schema=@Schema()) + @Parameter(in = ParameterIn.PATH, required = true, schema = @Schema()) @PathVariable("processID") String processID, - @Parameter(in = ParameterIn.DEFAULT, description = "Mandatory execute request JSON", required=true, schema=@Schema()) + @Parameter(in = ParameterIn.DEFAULT, description = "Mandatory execute request JSON", required = true, schema = @Schema()) @Valid - @RequestBody Execute body){ + @RequestBody Execute body) { if (processID.equals(ProcessIdEnum.DOWNLOAD_DATASET.getValue())) { + try { - var response = restServices.downloadData( - (String) body.getInputs().get(DatasetDownloadEnums.Condition.UUID.getValue()), - (String) body.getInputs().get(DatasetDownloadEnums.Condition.START_DATE.getValue()), - (String) body.getInputs().get(DatasetDownloadEnums.Condition.END_DATE.getValue()), - body.getInputs().get(DatasetDownloadEnums.Condition.MULTI_POLYGON.getValue()), - (String) body.getInputs().get(DatasetDownloadEnums.Condition.RECIPIENT.getValue()) - ); + + var uuid = (String) body.getInputs().get(DatasetDownloadEnums.Condition.UUID.getValue()); + var startDate = (String) body.getInputs().get(DatasetDownloadEnums.Condition.START_DATE.getValue()); + var endDate = (String) body.getInputs().get(DatasetDownloadEnums.Condition.END_DATE.getValue()); + var multiPolygon = body.getInputs().get(DatasetDownloadEnums.Condition.MULTI_POLYGON.getValue()); + var recipient = (String) body.getInputs().get(DatasetDownloadEnums.Condition.RECIPIENT.getValue()); + + // move the notify user email from data-access-service to here to make the first email faster + restServices.notifyUser(recipient, uuid, startDate, endDate); + + var response = restServices.downloadData(uuid, startDate, endDate, multiPolygon, recipient); var value = new InlineValue(response.getBody()); var status = new InlineValue(Integer.toString(HttpStatus.OK.value())); diff --git a/server/src/main/java/au/org/aodn/ogcapi/server/processes/RestServices.java b/server/src/main/java/au/org/aodn/ogcapi/server/processes/RestServices.java index dcabb34a..b22ed860 100644 --- a/server/src/main/java/au/org/aodn/ogcapi/server/processes/RestServices.java +++ b/server/src/main/java/au/org/aodn/ogcapi/server/processes/RestServices.java @@ -8,6 +8,8 @@ import software.amazon.awssdk.services.batch.BatchClient; import software.amazon.awssdk.services.batch.model.SubmitJobRequest; import software.amazon.awssdk.services.batch.model.SubmitJobResponse; +import software.amazon.awssdk.services.ses.SesClient; +import software.amazon.awssdk.services.ses.model.*; import java.util.HashMap; import java.util.Map; @@ -23,6 +25,30 @@ public RestServices(BatchClient batchClient, ObjectMapper objectMapper) { this.objectMapper = objectMapper; } + public void notifyUser(String recipient, String uuid, String startDate, String endDate) { + + try(SesClient ses = SesClient.builder().build()) { + var subject = Content.builder().data("Start processing data file whose uuid is: " + uuid).build(); + var content = Content.builder().data(generateStartedEmailContent(startDate, endDate)).build(); + + var body = Body.builder().text(content).build(); + var message = Message.builder() + .subject(subject) + .body(body) + .build(); + + SendEmailRequest request = SendEmailRequest.builder() + .message(message) + .source(recipient) + .build(); + + ses.sendEmail(request); + + } catch (SesException e) { + log.error("Error sending email: {}", e.getMessage()); + } + } + public ResponseEntity downloadData( String id, String startDate, @@ -31,21 +57,21 @@ public ResponseEntity downloadData( String recipient ) throws JsonProcessingException { - Map parameters = new HashMap<>(); - parameters.put(DatasetDownloadEnums.Condition.UUID.getValue(), id); - parameters.put(DatasetDownloadEnums.Condition.START_DATE.getValue(), startDate); - parameters.put(DatasetDownloadEnums.Condition.END_DATE.getValue(), endDate); - parameters.put(DatasetDownloadEnums.Condition.MULTI_POLYGON.getValue(), objectMapper.writeValueAsString(polygons)); - parameters.put(DatasetDownloadEnums.Condition.RECIPIENT.getValue(), recipient); - - - String jobId = submitJob( - "generating-data-file-for-" + recipient.replaceAll("[^a-zA-Z0-9-_]", "-"), - DatasetDownloadEnums.JobQueue.GENERATING_CSV_DATA_FILE.getValue(), - DatasetDownloadEnums.JobDefinition.GENERATE_CSV_DATA_FILE.getValue(), - parameters); - log.info("Job submitted with ID: " + jobId); - return ResponseEntity.ok("Job submitted with ID: " + jobId); + Map parameters = new HashMap<>(); + parameters.put(DatasetDownloadEnums.Condition.UUID.getValue(), id); + parameters.put(DatasetDownloadEnums.Condition.START_DATE.getValue(), startDate); + parameters.put(DatasetDownloadEnums.Condition.END_DATE.getValue(), endDate); + parameters.put(DatasetDownloadEnums.Condition.MULTI_POLYGON.getValue(), objectMapper.writeValueAsString(polygons)); + parameters.put(DatasetDownloadEnums.Condition.RECIPIENT.getValue(), recipient); + + + String jobId = submitJob( + "generating-data-file-for-" + recipient.replaceAll("[^a-zA-Z0-9-_]", "-"), + DatasetDownloadEnums.JobQueue.GENERATING_CSV_DATA_FILE.getValue(), + DatasetDownloadEnums.JobDefinition.GENERATE_CSV_DATA_FILE.getValue(), + parameters); + log.info("Job submitted with ID: " + jobId); + return ResponseEntity.ok("Job submitted with ID: " + jobId); } private String submitJob(String jobName, String jobQueue, String jobDefinition, Map parameters) { @@ -60,4 +86,11 @@ private String submitJob(String jobName, String jobQueue, String jobDefinition, SubmitJobResponse submitJobResponse = batchClient.submitJob(submitJobRequest); return submitJobResponse.jobId(); } + + private String generateStartedEmailContent(String startDate, String endDate) { + return "Your request has been received. Date range: Start Date: " + + startDate + ", End Date: " + endDate + ". Please wait for the result. " + + "'After the process is completed, you will receive an email '" + + "with the download link."; + } }