Skip to content

Commit

Permalink
Merge branch 'main' into retry-session-id-delete
Browse files Browse the repository at this point in the history
  • Loading branch information
cap-ang authored Nov 13, 2024
2 parents 071b36f + 2e4cd25 commit deb8d19
Show file tree
Hide file tree
Showing 14 changed files with 107 additions and 28 deletions.
4 changes: 2 additions & 2 deletions helm/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ apiVersion: v2
name: pagopa-wisp-converter
description: A service that permits to handle nodoInviaRPT and nodoInviaCarrelloRPT request from WISP, interfacing them with GPD system
type: application
version: 0.272.0
appVersion: 0.4.28-4-retry-session-id-delete
version: 0.273.0
appVersion: 0.4.30
dependencies:
- name: microservice-chart
version: 3.0.0
Expand Down
2 changes: 1 addition & 1 deletion helm/values-dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ microservice-chart: &microservice-chart
fullnameOverride: ""
image:
repository: ghcr.io/pagopa/pagopa-wisp-converter
tag: "0.4.28-4-retry-session-id-delete"
tag: "0.4.30"
pullPolicy: Always
livenessProbe:
httpGet:
Expand Down
2 changes: 1 addition & 1 deletion helm/values-prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ microservice-chart: &microservice-chart
fullnameOverride: ""
image:
repository: ghcr.io/pagopa/pagopa-wisp-converter
tag: "0.4.28-4-retry-session-id-delete"
tag: "0.4.30"
pullPolicy: Always
livenessProbe:
httpGet:
Expand Down
2 changes: 1 addition & 1 deletion helm/values-uat.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ microservice-chart: &microservice-chart
fullnameOverride: ""
image:
repository: ghcr.io/pagopa/pagopa-wisp-converter
tag: "0.4.28-4-retry-session-id-delete"
tag: "0.4.30"
pullPolicy: Always
livenessProbe:
httpGet:
Expand Down
56 changes: 52 additions & 4 deletions openapi/openapi.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion openapi/openapi_redirect.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"openapi": "3.0.1",
"info": {
"title": "WISP-Converter-redirect",
"version": "0.4.28-4-retry-session-id-delete"
"version": "0.4.30"
},
"servers": [
{
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

<groupId>it.gov.pagopa</groupId>
<artifactId>wisp-converter</artifactId>
<version>0.4.28-4-retry-session-id-delete</version>
<version>0.4.30</version>
<name>pagoPA WISP Converter</name>
<description>A service that permits to handle nodoInviaRPT and nodoInviaCarrelloRPT request from WISP, converting them in NMU payments.</description>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,7 @@
import org.springframework.web.ErrorResponse;
import org.springframework.web.bind.annotation.*;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import java.io.IOException;
import java.io.StringReader;
Expand Down Expand Up @@ -144,21 +142,19 @@ public void receiptOk(@RequestBody ReceiptRequest request) throws IOException {
}

private String getReceiptRequestInfoToLog(String xml) {
String args = "n/a";
String args = "";
try {
if (StringUtils.isNotEmpty(xml)) {
// fix for sonar issue XML external entity in user-controlled data
saxParserFactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
saxParserFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
saxParserFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);

saxParserFactory.newSAXParser().parse(new InputSource(new StringReader(xml)), receiptRequestHandler);

PaSendRTV2Request result = receiptRequestHandler.getPaSendRTV2Request();
args = "noticeNumber=" + result.getNoticeNumber() + ", fiscalCode=" + result.getFiscalCode() + ", creditorReferenceId=" + result.getCreditorReferenceId();
}
} catch (SAXException | IOException | ParserConfigurationException e) {
return args;
} catch (Exception e) {
args = "n/a";
}
return args;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,12 @@ public ResponseEntity<RecoveryReceiptReportResponse> recoverReceiptToBeReSentByP
}
}

@Operation(summary = "Execute reconciliation for OK receipts by sessionId.", description = "Execute reconciliation of all receipts related to the sessionIds of the request", security = {@SecurityRequirement(name = "ApiKey")}, tags = {"Recovery"})
@Operation(summary = "Execute reconciliation for OK receipts by sessionId.", description = "Execute reconciliation of all OK receipts related to the sessionIds of the request", security = {@SecurityRequirement(name = "ApiKey")}, tags = {"Recovery"})
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Reconciliation scheduled")
})
@PostMapping(value = "/sessionIds/ok")
public ResponseEntity<RecoveryReceiptReportResponse> recoverReceiptToBeReSentBySessionId(@RequestBody RecoveryReceiptBySessionIdRequest request) {
public ResponseEntity<RecoveryReceiptReportResponse> recoverOkReceiptToBeReSentBySessionId(@RequestBody RecoveryReceiptBySessionIdRequest request) {
try {
log.debug("Invoking API operation recoverReceiptToBeReSentBySessionId - args: {}", sanitizeInput(request.toString()));
return ResponseEntity.ok(recoveryService.recoverReceiptOkToBeReSentBySessionIds(request));
Expand All @@ -150,4 +150,24 @@ public ResponseEntity<RecoveryReceiptReportResponse> recoverReceiptToBeReSentByS
throw ex;
}
}

@Operation(summary = "Execute reconciliation for KO receipts by sessionId.", description = "Execute reconciliation of all KO receipts related to the sessionIds of the request", security = {@SecurityRequirement(name = "ApiKey")}, tags = {"Recovery"})
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Reconciliation scheduled")
})
@PostMapping(value = "/sessionIds/ko")
public ResponseEntity<Void> recoverKoReceiptToBeReSentBySessionId(@RequestBody RecoveryReceiptBySessionIdRequest request) {
try {
log.debug("Invoking API operation recoverReceiptToBeReSentBySessionId - args: {}", sanitizeInput(request.toString()));
recoveryService.recoverReceiptKoToBeReSentBySessionIds(request);
return ResponseEntity.ok().build();
} catch (Exception ex) {
String operationId = MDC.get(Constants.MDC_OPERATION_ID);
log.error(String.format("GenericException: operation-id=[%s]", operationId != null ? operationId : "n/a"), ex);
AppException appException = new AppException(ex, AppErrorCodeMessageEnum.ERROR, ex.getMessage());
ErrorResponse errorResponse = errorUtil.forAppException(appException);
log.error("Failed API operation recoverReceiptToBeReSentBySessionId - error: {}", errorResponse);
throw ex;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public enum InternalStepStatus {
RT_SEND_RESCHEDULING_FAILURE,
RT_SEND_RESCHEDULING_REACHED_MAX_RETRIES,
RT_SEND_RESCHEDULING_SUCCESS,
RT_RECONCILIATION_PROCESS,
RT_START_RECONCILIATION_PROCESS,
RT_END_RECONCILIATION_PROCESS,
RT_DEAD_LETTER_SAVED,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;

@Component
@Slf4j
Expand All @@ -40,15 +41,19 @@ public RecoveryScheduler(RecoveryService recoveryService) {
@Scheduled(cron = "${cron.job.schedule.recovery.receipt-ko.trigger}")
@Async
public void recoverReceiptKOCronJob() {
ZonedDateTime dateFrom = ZonedDateTime.now(ZoneOffset.UTC).minusHours(fromHoursAgo);
ZonedDateTime dateTo = ZonedDateTime.now(ZoneOffset.UTC).minusHours(untilHoursAgo);
ZonedDateTime dateFrom = ZonedDateTime.now(ZoneOffset.UTC).minusHours(fromHoursAgo).truncatedTo(ChronoUnit.HOURS);
ZonedDateTime dateTo = ZonedDateTime.now(ZoneOffset.UTC).minusHours(untilHoursAgo).truncatedTo(ChronoUnit.HOURS);
log.info("[WISP-Recovery][Scheduled][Start] Reconciliation Cron: recoverReceiptKOCronJob running at {}, for recover stale RPT from {} to {}",
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now()), dateFrom, dateTo);

int missingRTRecovered = this.recoveryService.recoverReceiptKOByDate(dateFrom, dateTo).getPayments().size();
// recover RPT without redirect
int missingRedirectRecovered = this.recoveryService.recoverMissingRedirect(dateFrom, dateTo);

log.info("[WISP-Recovery][Scheduled][Stop] Reconciliation Cron: recoverReceiptKOCronJob {} receipt-ko sent", missingRedirectRecovered + missingRTRecovered);
// recover receipt-rt in state redirect or sending with rt equals to null
int missingRTRecovered = this.recoveryService.recoverReceiptKOByDate(dateFrom, dateTo).getPayments().size();

log.info("[WISP-Recovery][Scheduled][Stop] Reconciliation Cron: recoverReceiptKOCronJob {} receipt-ko sent," +
" missingRedirect: {}, missingRTRecovered: {}", missingRedirectRecovered + missingRTRecovered, missingRedirectRecovered, missingRTRecovered);
this.threadOfExecution = Thread.currentThread();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public void lockIdempotencyKey(String idempotencyKey, ReceiptTypeEnum receiptTyp
IdempotencyKeyEntity idempotencyKeyEntity;

// try to retrieve idempotency key entity from the storage and check if exists
// In this case, no findBy with partition key is set because the search could refers to different days
// In this case, no findBy with partition key is set because the search could refer to different days
Optional<IdempotencyKeyEntity> optIdempotencyKeyEntity = idempotencyKeyRepository.findById(idempotencyKey);
if (optIdempotencyKeyEntity.isPresent()) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public void addRe(ReEventDto reEventDto) {
ReEventEntity reEventEntity = reEventMapper.toReEventEntity(reEventDto);
reEventRepository.save(reEventEntity);
} catch (Exception e) {
throw new AppException(AppErrorCodeMessageEnum.PERSISTENCE_SAVING_RE_ERROR, e);
log.error("[RE-429][sessionId:{}] Exception: {}", reEventDto.getSessionId(), AppErrorCodeMessageEnum.PERSISTENCE_SAVING_RE_ERROR.getDetail());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

@Service
Expand All @@ -69,6 +68,7 @@ public class RecoveryService {

private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
private static final String DATE_FORMAT_DAY = "yyyy-MM-dd";
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern(DATE_FORMAT);
private static final List<String> blockedReceiptStatus = List.of(
ReceiptStatusEnum.NOT_SENT.name(),
ReceiptStatusEnum.REDIRECT.name(),
Expand Down Expand Up @@ -134,7 +134,8 @@ public RecoveryReceiptResponse recoverReceiptKOByCI(String creditorInstitution,
// Recover by dates (cron)
public RecoveryReceiptResponse recoverReceiptKOByDate(ZonedDateTime dateFrom, ZonedDateTime dateTo) {
// Query database for blocked Receipt in given timestamp
List<RTEntity> rtEntities = rtRepository.findByMidReceiptStatusInAndTimestampBetween(dateFrom.toString(), dateTo.toString());
List<RTEntity> rtEntities = rtRepository.findByMidReceiptStatusInAndTimestampBetween(
dateFrom.format(DATE_TIME_FORMATTER), dateTo.format(DATE_TIME_FORMATTER));
// For each entity call send receipt KO
rtEntities.forEach(rtEntity -> callSendReceiptKO(rtEntity.getDomainId(), rtEntity.getIuv(), rtEntity.getCcp(), rtEntity.getSessionId()));
return this.extractRecoveryReceiptResponse(rtEntities);
Expand Down Expand Up @@ -313,6 +314,14 @@ public RecoveryReceiptReportResponse recoverReceiptOkToBeReSentBySessionIds(Reco
}
}

@Transactional
public void recoverReceiptKoToBeReSentBySessionIds(RecoveryReceiptBySessionIdRequest request) {
// TODO inject MDC
for (String sessionId : request.getSessionIds()) {
CompletableFuture.runAsync(() -> receiptService.sendRTKoFromSessionId(sessionId, InternalStepStatus.RT_RECONCILIATION_PROCESS));
}
}

public RecoveryReceiptReportResponse recoverReceiptToBeReSentByPartition(RecoveryReceiptByPartitionRequest request) {

List<String> receiptsIds = request.getPartitionKeys().stream()
Expand Down

0 comments on commit deb8d19

Please sign in to comment.