Skip to content

Commit

Permalink
[NOD-933] feat: add API for retrieve report from cold storage
Browse files Browse the repository at this point in the history
  • Loading branch information
andrea-deri committed Jun 6, 2024
1 parent 36f1276 commit df75cb5
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,39 @@ public ResponseEntity<Resource> extractReportFromHotStorageByMonth(
DataReport dataReport = statisticsService.extractReportFromHotStorage(year, month, day);

HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=VerifyKO-Report-" + year + month + (day == null ? "X" : day) + ".json");
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=VerifyKO_HotStorage_Report_" + year + "-" + month + "-" + (day == null ? "X" : day) + ".json");

String content = gsonMapper.toJson(dataReport);
ByteArrayResource resource = new ByteArrayResource(content.getBytes());
return ResponseEntity.ok()
.headers(headers)
.contentLength(content.length())
.contentType(MediaType.parseMediaType("application/octet-stream"))
.body(resource);
}

@GetMapping(value = "/reports/cold", produces = {MediaType.APPLICATION_JSON_VALUE})
@Operation(summary = "Export Verify KO report from Cold Storage",
description = "The API execute the export of a report about Verify KO events from cold-storage stored for the passed date or month.",
security = {@SecurityRequirement(name = "ApiKey")},
tags = {"Statistics"})
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Export extracted with success.", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = Void.class))),
@ApiResponse(responseCode = "400", description = "If passed date is invalid.", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = ProblemJson.class))),
@ApiResponse(responseCode = "500", description = "If an error occurred during execution.", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = ProblemJson.class)))})
@OpenAPITableMetadata(external = false, cacheable = true)
public ResponseEntity<Resource> extractReportFromColdStorageByMonth(
@Parameter(description = "The year on which the report extraction will be executed.", example = "2020", required = true)
@RequestParam Integer year,
@Parameter(description = "The month on which the report extraction will be executed.", example = "1", required = true)
@RequestParam Integer month,
@Parameter(description = "The day on which the report extraction will be executed, from yesterday.")
@RequestParam(required = false) Integer day) {

DataReport dataReport = statisticsService.extractReportFromColdStorage(year, month, day);

HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=VerifyKO_ColdStorage_Report_" + year + "-" + month + "-" + (day == null ? "X" : day) + ".json");

String content = gsonMapper.toJson(dataReport);
ByteArrayResource resource = new ByteArrayResource(content.getBytes());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@ public class ColdStorageVerifyKO extends TableServiceEntity {
private String diagnosticId;
private Long eventTimestamp;

//@Transient
//private Map<String, Object> eventFromBlob;

@Override
public void readEntity(final HashMap<String, EntityProperty> properties, final OperationContext opContext) throws StorageException {
super.readEntity(properties, opContext);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,19 @@
public class DataReport implements Serializable {
List<DailyDataReport> days;
private long total;
private Map<String, Long> fault;
private Map<String, Long> status;

public DataReport() {
this.fault = new HashMap<>();
this.status = new HashMap<>();
this.days = new LinkedList<>();
}

public void addDailyReport(DailyDataReport dailyDataReport) {
this.days.add(dailyDataReport);
}

public void addFault(String fault, Long value) {
this.fault.put(fault, this.fault.getOrDefault(fault, 0L) + value);
public void addStatus(String status, Long value) {
this.status.put(status, this.status.getOrDefault(status, 0L) + value);
}

public void addToTotal(long value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@

import java.net.URISyntaxException;
import java.security.InvalidKeyException;
import java.util.HashSet;
import java.util.Set;
import java.util.Spliterator;
import java.util.*;
import java.util.stream.StreamSupport;

@Service
Expand Down Expand Up @@ -41,6 +39,19 @@ public Set<String> getIDsByDate(String partitionKey, Long dateLowerBound, Long d
return ids;
}

public List<ColdStorageVerifyKO> getByDate(String partitionKey, Long dateLowerBound, Long dateUpperBound) {
List<ColdStorageVerifyKO> entities = new LinkedList<>();
String queryWhereClausePartitionKey = TableQuery.generateFilterCondition("PartitionKey", TableQuery.QueryComparisons.EQUAL, partitionKey);
String queryWhereClauseDateTimeLowerBound = TableQuery.generateFilterCondition("timestamp", TableQuery.QueryComparisons.GREATER_THAN_OR_EQUAL, dateLowerBound);
String queryWhereClauseDateTimeUpperBound = TableQuery.generateFilterCondition("timestamp", TableQuery.QueryComparisons.LESS_THAN_OR_EQUAL, dateUpperBound);
String queryWhereClauseDateTime = TableQuery.combineFilters(queryWhereClauseDateTimeLowerBound, TableQuery.Operators.AND, queryWhereClauseDateTimeUpperBound);
String queryWhereClause = TableQuery.combineFilters(queryWhereClausePartitionKey, TableQuery.Operators.AND, queryWhereClauseDateTime);
TableQuery<ColdStorageVerifyKO> query = TableQuery.from(ColdStorageVerifyKO.class).where(queryWhereClause);
Iterable<ColdStorageVerifyKO> result = table.execute(query);
result.forEach(entities::add);
return entities;
}

public ColdStorageVerifyKO findById(String rowKey, String partitionKey) {
String rowKeyWhereClause = TableQuery.generateFilterCondition("RowKey", TableQuery.QueryComparisons.EQUAL, rowKey);
String partitionKeyWhereClause = TableQuery.generateFilterCondition("PartitionKey", TableQuery.QueryComparisons.EQUAL, partitionKey);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package it.gov.pagopa.nodoverifykoaux.service;

import it.gov.pagopa.nodoverifykoaux.entity.ColdStorageVerifyKO;
import it.gov.pagopa.nodoverifykoaux.entity.HotStorageVerifyKO;
import it.gov.pagopa.nodoverifykoaux.exception.AppError;
import it.gov.pagopa.nodoverifykoaux.exception.AppException;
import it.gov.pagopa.nodoverifykoaux.model.statistics.DailyDataReport;
import it.gov.pagopa.nodoverifykoaux.model.statistics.DataReport;
import it.gov.pagopa.nodoverifykoaux.repository.DataStorageRepository;
import it.gov.pagopa.nodoverifykoaux.repository.TableStorageRepository;
import it.gov.pagopa.nodoverifykoaux.util.DateValidator;
import lombok.extern.slf4j.Slf4j;
import org.modelmapper.ModelMapper;
Expand All @@ -22,16 +24,20 @@ public class StatisticsService {

private final DataStorageRepository hotStorageRepo;

private final TableStorageRepository coldStorageRepo;

private final DateValidator dateValidator;

private final ModelMapper mapper;

private final int reportMinutesBatchSize;

public StatisticsService(DataStorageRepository hotStorageRepo,
TableStorageRepository coldStorageRepo,
ModelMapper mapper,
@Value("${verifyko.report.minutes-time-frame}") Integer reportMinutesTimeFrame) {
this.hotStorageRepo = hotStorageRepo;
this.coldStorageRepo = coldStorageRepo;
this.dateValidator = new DateValidator("yyyy-MM-ddZ");
this.mapper = mapper;
this.reportMinutesBatchSize = reportMinutesTimeFrame;
Expand Down Expand Up @@ -80,7 +86,7 @@ public DataReport extractReportFromHotStorage(Integer year, Integer month, Integ
long counter = 0;
for (Map.Entry<String, Long> entry : dayReport.getFault().entrySet()) {
long number = entry.getValue();
dataReport.addFault(entry.getKey(), number);
dataReport.addStatus(entry.getKey(), number);
counter += number;
}
dataReport.addToTotal(counter);
Expand All @@ -89,6 +95,60 @@ public DataReport extractReportFromHotStorage(Integer year, Integer month, Integ
return dataReport;
}


public DataReport extractReportFromColdStorage(Integer year, Integer month, Integer singleDay) {

// Execute checks on date and convert it in required format
if (!dateValidator.isValid(year, month, singleDay)) {
throw new AppException(AppError.BAD_REQUEST_INVALID_DATE_FOR_REPORT, year, month, singleDay == null ? "XX" : singleDay);
}

DataReport dataReport = new DataReport();

List<String> days = dateValidator.getDaysOfMonth(year, month, singleDay);
for (String day : days) {

log.info(String.format("Extracting report data from day [%s].", day));
DailyDataReport dailyDataReport = new DailyDataReport(day);

String stringedDate = day.replace("-0", "").replace("-", "").replace("+0000", "");

Date dateLowerBound = dateValidator.getDate(day);
long batchCounter = 1;
while (!isComputationEnded(day, dateLowerBound)) {

Date dateUpperBound = dateValidator.getDate(day, this.reportMinutesBatchSize * batchCounter);
Long dateLowerBoundTimestamp = dateLowerBound.getTime() / 1000;
Long dateUpperBoundTimestamp = dateUpperBound.getTime() / 1000;

// Retrieving all events batched by defined timestamp section
List<ColdStorageVerifyKO> events = coldStorageRepo.getByDate(stringedDate, dateLowerBoundTimestamp, dateUpperBoundTimestamp);

// Incrementing statistics counters
events.forEach(event -> dailyDataReport.addFault("RECONCILED"));

// Update batch counter and date bounds
dateLowerBound = dateUpperBound;
batchCounter++;
}

dataReport.addDailyReport(dailyDataReport);
}

for (DailyDataReport dayReport : dataReport.getDays()) {
long counter = 0;
for (Map.Entry<String, Long> entry : dayReport.getFault().entrySet()) {
long number = entry.getValue();
dataReport.addStatus(entry.getKey(), number);
counter += number;
}
dataReport.addToTotal(counter);
}

return dataReport;
}


private boolean isComputationEnded(String analyzedDate, Date lowerBoundDate) {
return !analyzedDate.substring(0, 10).equals(this.dateValidator.getDateAsString(lowerBoundDate).substring(0, 10));
}
Expand Down

0 comments on commit df75cb5

Please sign in to comment.