Skip to content

Commit

Permalink
feat: Merge pull request #242 from pagopa/release-dev
Browse files Browse the repository at this point in the history
feat: Release dev
  • Loading branch information
antonioT90 authored Dec 21, 2023
2 parents d6b30d7 + 2f681a3 commit f533abb
Show file tree
Hide file tree
Showing 23 changed files with 218 additions and 81 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<groupId>it.gov.pagopa</groupId>
<artifactId>idpay-admissibility-assessor</artifactId>
<name>idpay-admissibility-assessor</name>
<version>1.2.3</version>
<version>1.3.0</version>

<properties>
<java.version>17</java.version>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package it.gov.pagopa.admissibility.config;

import it.gov.pagopa.admissibility.utils.OnboardingConstants;
import it.gov.pagopa.common.web.dto.ErrorDTO;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AdmissibilityErrorManagerConfig {

@Bean
ErrorDTO defaultErrorDTO() {
return new ErrorDTO(
OnboardingConstants.ExceptionCode.GENERIC_ERROR,
"A generic error occurred"
);
}

@Bean
ErrorDTO tooManyRequestsErrorDTO() {
return new ErrorDTO(OnboardingConstants.ExceptionCode.TOO_MANY_REQUESTS, "Too Many Requests");
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package it.gov.pagopa.admissibility.connector.repository;

import it.gov.pagopa.admissibility.model.DroolsRule;
import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
import it.gov.pagopa.common.reactive.mongo.ReactiveMongoRepositoryExt;

/**
* it will handle the persistence of {@link it.gov.pagopa.admissibility.model.DroolsRule} entity*/
public interface DroolsRuleRepository extends ReactiveMongoRepository<DroolsRule, String> {
public interface DroolsRuleRepository extends ReactiveMongoRepositoryExt<DroolsRule, String> {
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package it.gov.pagopa.admissibility.connector.repository;

import it.gov.pagopa.admissibility.model.InitiativeCounters;
import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
import it.gov.pagopa.common.reactive.mongo.ReactiveMongoRepositoryExt;

/**
* it will handle the persistence of {@link InitiativeCounters} entity*/
public interface InitiativeCountersRepository extends ReactiveMongoRepository<InitiativeCounters, String>, InitiativeCountersReservationOpsRepository {
public interface InitiativeCountersRepository extends ReactiveMongoRepositoryExt<InitiativeCounters, String>, InitiativeCountersReservationOpsRepository {
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package it.gov.pagopa.admissibility.controller;

import it.gov.pagopa.admissibility.dto.onboarding.InitiativeStatusDTO;
import it.gov.pagopa.common.web.exception.ClientExceptionNoBody;
import it.gov.pagopa.admissibility.service.InitiativeStatusService;
import it.gov.pagopa.admissibility.utils.OnboardingConstants;
import it.gov.pagopa.common.web.exception.ClientExceptionWithBody;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RestController;
Expand All @@ -21,6 +22,6 @@ public AdmissibilityControllerImpl(InitiativeStatusService initiativeStatusServi
@Override
public Mono<InitiativeStatusDTO> getInitiativeStatus(String initiativeId) {
return initiativeStatusService.getInitiativeStatusAndBudgetAvailable(initiativeId)
.switchIfEmpty(Mono.error(new ClientExceptionNoBody(HttpStatus.NOT_FOUND, "Cannot find initiative having id " + initiativeId)));
.switchIfEmpty(Mono.error(new ClientExceptionWithBody(HttpStatus.NOT_FOUND, OnboardingConstants.ExceptionCode.INITIATIVE_NOT_FOUND, "The initiative with id %s does not exist".formatted(initiativeId))));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

import java.time.LocalDateTime;

@Slf4j
@Data
@AllArgsConstructor
Expand All @@ -23,4 +25,5 @@ public class DroolsRule {
private String rule;
private String ruleVersion;
private InitiativeConfig initiativeConfig;
private LocalDateTime updateDate;
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;

import java.time.LocalDateTime;
import java.util.stream.Collectors;

@Service
Expand Down Expand Up @@ -49,6 +50,7 @@ public DroolsRule apply(Initiative2BuildDTO initiative) {
out.setId(initiative.getInitiativeId());
out.setName(initiative.getInitiativeName());
out.setRuleVersion("20230404");
out.setUpdateDate(LocalDateTime.now());

out.setRule("""
package %s;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,21 @@ private Mono<?> execAndLogTiming(String deleteFlowName, String initiativeId, Mon
}

private Mono<Void> deleteDroolsRule(String initiativeId) {
return droolsRuleRepository.deleteById(initiativeId)
.doOnSuccess(d -> {
log.info("[DELETE_INITIATIVE] Deleted initiative {} from collection: beneficiary_rule", initiativeId);
return droolsRuleRepository.removeById(initiativeId)
.doOnNext(d -> {
log.info("[DELETE_INITIATIVE] Deleted {} initiative {} from collection: beneficiary_rule", d.getDeletedCount(), initiativeId);
auditUtilities.logDeletedDroolsRule(initiativeId);
})
.then();
}

private Mono<Void> deleteInitiativeCounters(String initiativeId) {
return initiativeCountersRepository.deleteById(initiativeId)
.doOnSuccess(i -> {
log.info("[DELETE_INITIATIVE] Deleted initiative {} from collection: initiative_counters", initiativeId);
return initiativeCountersRepository.removeById(initiativeId)
.doOnNext(i -> {
log.info("[DELETE_INITIATIVE] Deleted {} initiative {} from collection: initiative_counters", i.getDeletedCount(), initiativeId);
auditUtilities.logDeletedInitiativeCounters(initiativeId);
});
})
.then();
}

private Mono<Void> deleteOnboardingFamilies(String initiativeId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ private void acceptNewKieBase(KieBase newKieBase) {
preLoadKieBase(newKieBase);
this.kieBase = newKieBase;
this.kieInitiatives = readKieInitiatives(newKieBase);
log.info("[BENEFICIARY_RULE_CONTAINER_LOAD] Rule engine rules loaded: {}", kieInitiatives);
}

private Set<String> readKieInitiatives(KieBase kieBase) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,40 +41,45 @@ public RuleEngineServiceImpl(OnboardingContextHolderService onboardingContextHol
public EvaluationDTO applyRules(OnboardingDTO onboardingRequest, InitiativeConfig initiative) {
log.trace("[ONBOARDING_REQUEST] [RULE_ENGINE] evaluating rules of user {} into initiative {}", onboardingRequest.getUserId(), onboardingRequest.getInitiativeId());

StatelessKieSession statelessKieSession = onboardingContextHolderService.getBeneficiaryRulesKieBase().newStatelessKieSession();

OnboardingDroolsDTO req = onboarding2OnboardingDroolsMapper.apply(onboardingRequest);

@SuppressWarnings("unchecked")
List<Command<?>> cmds = Arrays.asList(
CommandFactory.newInsert(req),
CommandFactory.newInsert(criteriaCodeService),
new AgendaGroupSetFocusCommand(req.getInitiativeId())
);
if(checkIfKieBaseShouldBeInvolved(initiative)) {
if (checkIfKieBaseContainerIsReady(initiative)) {
StatelessKieSession statelessKieSession = onboardingContextHolderService.getBeneficiaryRulesKieBase().newStatelessKieSession();

long before = System.currentTimeMillis();
statelessKieSession.execute(CommandFactory.newBatchExecution(cmds));
@SuppressWarnings("unchecked")
List<Command<?>> cmds = Arrays.asList(
CommandFactory.newInsert(req),
CommandFactory.newInsert(criteriaCodeService),
new AgendaGroupSetFocusCommand(req.getInitiativeId())
);

checkIfContainerWasReady(req, initiative);
long before = System.currentTimeMillis();
statelessKieSession.execute(CommandFactory.newBatchExecution(cmds));

PerformanceLogger.logTiming("ONBOARDING_RULE_ENGINE", before, "resulted into rejections %s".formatted(req.getOnboardingRejectionReasons()));
PerformanceLogger.logTiming("ONBOARDING_RULE_ENGINE", before, "resulted into rejections %s".formatted(req.getOnboardingRejectionReasons()));
} else {
req.getOnboardingRejectionReasons().add(new OnboardingRejectionReason(
OnboardingRejectionReason.OnboardingRejectionReasonType.TECHNICAL_ERROR,
OnboardingConstants.REJECTION_REASON_RULE_ENGINE_NOT_READY,
null, null, null
));
}
} else {
log.info("[ONBOARDING_REQUEST][RULE_ENGINE] Selected not drools involved initiative: {}", initiative.getInitiativeId());
}

log.trace("[ONBOARDING_REQUEST] [RULE_ENGINE] Send message prepared: {}", req);

return onboarding2EvaluationMapper.apply(req, initiative, req.getOnboardingRejectionReasons());
}

private void checkIfContainerWasReady(OnboardingDroolsDTO req, InitiativeConfig initiative) {
if (req.getOnboardingRejectionReasons().isEmpty() && // there is not rejection reason
!CollectionUtils.isEmpty(initiative.getAutomatedCriteria()) && // the drools container is supposed to be involved
!onboardingContextHolderService.getBeneficiaryRulesKieInitiativeIds() // the initiative was not inside the container drools
.contains(initiative.getInitiativeId())
) {
req.getOnboardingRejectionReasons().add(new OnboardingRejectionReason(
OnboardingRejectionReason.OnboardingRejectionReasonType.TECHNICAL_ERROR,
OnboardingConstants.REJECTION_REASON_RULE_ENGINE_NOT_READY,
null, null, null
));
}
private boolean checkIfKieBaseShouldBeInvolved(InitiativeConfig initiative) {
return !CollectionUtils.isEmpty(initiative.getAutomatedCriteria()); // the drools container is supposed to not be involved
}

private boolean checkIfKieBaseContainerIsReady(InitiativeConfig initiative) {
return onboardingContextHolderService.getBeneficiaryRulesKieInitiativeIds() // the initiative is inside the container drools
.contains(initiative.getInitiativeId());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,13 @@ private OnboardingConstants(){}
//region global sequence id
public static final String ANPR_E002_INVOKE = "ANPR_E002_INVOKE";
//endregion

public static final class ExceptionCode {
private ExceptionCode(){}

public static final String TOO_MANY_REQUESTS = "ADMISSIBILITY_TOO_MANY_REQUESTS";
public static final String GENERIC_ERROR = "ADMISSIBILITY_GENERIC_ERROR";

public static final String INITIATIVE_NOT_FOUND = "ADMISSIBILITY_INITIATIVE_NOT_FOUND";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package it.gov.pagopa.common.reactive.mongo;

import com.mongodb.client.result.DeleteResult;
import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
import org.springframework.data.repository.NoRepositoryBean;
import reactor.core.publisher.Mono;

@NoRepositoryBean
public interface ReactiveMongoRepositoryExt<T, ID> extends ReactiveMongoRepository<T, ID> {
Mono<DeleteResult> removeById(ID id);
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
package it.gov.pagopa.common.reactive.mongo;

import com.mongodb.client.result.DeleteResult;
import lombok.NonNull;
import org.springframework.data.mongodb.core.ReactiveMongoOperations;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
import org.springframework.data.mongodb.repository.support.SimpleReactiveMongoRepository;
import org.springframework.util.Assert;
import reactor.core.publisher.Mono;

import java.io.Serializable;

public class ReactiveMongoRepositoryImpl<E, I extends Serializable> extends SimpleReactiveMongoRepository<E, I> {
import static org.springframework.data.mongodb.core.query.Criteria.where;

public class ReactiveMongoRepositoryImpl<E, I extends Serializable> extends SimpleReactiveMongoRepository<E, I> implements ReactiveMongoRepositoryExt<E, I> {

private final ReactiveMongoOperations mongoOperations;
private final MongoEntityInformation<E, I> entityInformation;
Expand All @@ -29,4 +33,22 @@ public ReactiveMongoRepositoryImpl(MongoEntityInformation<E, I> entityInformatio
entityInformation.getJavaType(), entityInformation.getCollectionName()).singleOrEmpty();
}

@Override
public Mono<DeleteResult> removeById(I id) {
Assert.notNull(id, "The given id must not be null");

return mongoOperations
.remove(getIdQuery(id), entityInformation.getJavaType(), entityInformation.getCollectionName());
}

@SuppressWarnings("squid:S2177") // suppressing overriding private super method
private Query getIdQuery(Object id) {
return new Query(getIdCriteria(id));
}

@SuppressWarnings("squid:S2177") // suppressing overriding private super method
private Criteria getIdCriteria(Object id) {
return where(entityInformation.getIdAttribute()).is(id);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,22 @@
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.lang.Nullable;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.server.ServerWebExchange;

import java.util.Optional;


@RestControllerAdvice
@Slf4j
public class ErrorManager {
private static final ErrorDTO defaultErrorDTO;
static {
defaultErrorDTO =new ErrorDTO("Error", "Something gone wrong");
private final ErrorDTO defaultErrorDTO;

public ErrorManager(@Nullable ErrorDTO defaultErrorDTO) {
this.defaultErrorDTO = Optional.ofNullable(defaultErrorDTO)
.orElse(new ErrorDTO("Error", "Something gone wrong"));
}
@ExceptionHandler(RuntimeException.class)
protected ResponseEntity<ErrorDTO> handleException(RuntimeException error, ServerWebExchange exchange) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,27 @@
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.ResponseEntity.BodyBuilder;
import org.springframework.lang.Nullable;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.server.ServerWebExchange;

import java.util.Optional;

@RestControllerAdvice
@Slf4j
@Order(Ordered.HIGHEST_PRECEDENCE)
public class MongoExceptionHandler {

private final ErrorManager errorManager;

public MongoExceptionHandler(ErrorManager errorManager) {
private final ErrorDTO tooManyRequestsErrorDTO;

public MongoExceptionHandler(ErrorManager errorManager, @Nullable ErrorDTO tooManyRequestsErrorDTO) {
this.errorManager = errorManager;

this.tooManyRequestsErrorDTO = Optional.ofNullable(tooManyRequestsErrorDTO)
.orElse(new ErrorDTO("TOO_MANY_REQUESTS", "Too Many Requests"));
}

@ExceptionHandler(DataAccessException.class)
Expand Down Expand Up @@ -66,7 +74,7 @@ private ResponseEntity<ErrorDTO> getErrorDTOResponseEntity(Exception ex,
}

return bodyBuilder
.body(new ErrorDTO("TOO_MANY_REQUESTS", "TOO_MANY_REQUESTS"));
.body(tooManyRequestsErrorDTO);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,6 @@ void test() {
checkRepositories();
checkErrorsPublished(notValidMessages, maxWaitingMs, errorUseCases);

Mockito.verify(droolsRuleRepositorySpy).findAll();

System.out.printf("""
************************
Time spent to send %d (%d + %d) messages (from start): %d millis
Expand Down Expand Up @@ -188,7 +186,7 @@ protected Pattern getErrorUseCaseIdPatternMatch() {
errorUseCases.add(Pair.of(
() -> {
Mockito.doThrow(new MongoException("Command error dummy"))
.when(droolsRuleRepositorySpy).deleteById(errorInitiativeId);
.when(droolsRuleRepositorySpy).removeById(errorInitiativeId);
return commandOperationErrorString;
},
errorMessage -> checkErrorMessageHeaders(errorMessage, "[ADMISSIBILITY_COMMANDS] An error occurred evaluating commands", commandOperationErrorString)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ private void checkResult(DroolsRule result, Initiative2BuildDTO dto) {
.isLogoPresent(Boolean.TRUE)
.beneficiaryType(InitiativeGeneralDTO.BeneficiaryTypeEnum.PF)
.build());

expected.setUpdateDate(result.getUpdateDate());
expected.setRuleVersion("20230404");

Assertions.assertEquals(expected, result);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
Expand Down Expand Up @@ -61,7 +62,8 @@ void configureMocks() {
.automatedCriteriaCodes(List.of("CODE"))
.initiativeBudget(i.getGeneral().getBudget())
.beneficiaryInitiativeBudget(i.getGeneral().getBeneficiaryBudget())
.build());
.build(),
LocalDateTime.now());
});
Mockito.when(droolsRuleRepositoryMock.save(Mockito.any())).thenAnswer(invocation -> Mono.just(invocation.getArgument(0)));
Mockito.when(kieContainerBuilderServiceMock.buildAll()).thenReturn(Mono.just(newKieBaseBuiltMock));
Expand Down
Loading

0 comments on commit f533abb

Please sign in to comment.