diff --git a/apps/institution-send-mail-scheduler/Dockerfile b/apps/institution-send-mail-scheduler/Dockerfile
new file mode 100644
index 0000000..22b22da
--- /dev/null
+++ b/apps/institution-send-mail-scheduler/Dockerfile
@@ -0,0 +1,53 @@
+# syntax=docker/dockerfile:1.6@sha256:ac85f380a63b13dfcefa89046420e1781752bab202122f8f50032edf31be0021
+FROM maven:3-eclipse-temurin-17@sha256:0d328fa6843bb26b60cf44d69833f241ffe96218fb29fa19df7a6603863eaae7 AS builder
+
+WORKDIR /src
+COPY --link pom.xml .
+
+WORKDIR /src/test-coverage
+COPY --link ./test-coverage/pom.xml .
+
+WORKDIR /src/apps
+COPY --link ./apps/pom.xml .
+
+WORKDIR /src/apps/institution-send-mail-scheduler
+COPY --link ./apps/institution-send-mail-scheduler/pom.xml .
+COPY ./apps/institution-send-mail-scheduler/src/main/ ./src/main/
+
+WORKDIR /src
+
+RUN echo "\n" \
+ "\n" \
+ "\n" \
+ "\${repositoryId}\n" \
+ "\${repoLogin}\n" \
+ "\${repoPwd}\n" \
+ "\n" \
+ "\n" \
+ "\n" > settings.xml
+
+ARG REPO_ONBOARDING
+ARG REPO_USERNAME
+ARG REPO_PASSWORD
+
+RUN mvn --global-settings settings.xml --projects :institution-send-mail-scheduler -DrepositoryId=${REPO_ONBOARDING} -DrepoLogin=${REPO_USERNAME} -DrepoPwd=${REPO_PASSWORD} --also-make clean package -DskipTests
+
+FROM openjdk:17-jdk@sha256:528707081fdb9562eb819128a9f85ae7fe000e2fbaeaf9f87662e7b3f38cb7d8 AS runtime
+
+ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en'
+ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
+
+WORKDIR /app
+
+COPY --from=builder /src/apps/institution-send-mail-scheduler/target/quarkus-app/lib/ ./lib/
+COPY --from=builder /src/apps/institution-send-mail-scheduler/target/quarkus-app/*.jar ./
+COPY --from=builder /src/apps/institution-send-mail-scheduler/target/quarkus-app/app/ ./app/
+COPY --from=builder /src/apps/institution-send-mail-scheduler/target/quarkus-app/quarkus/ ./quarkus/
+
+ADD https://github.com/microsoft/ApplicationInsights-Java/releases/download/3.2.11/applicationinsights-agent-3.2.11.jar ./applicationinsights-agent.jar
+RUN chmod 755 ./applicationinsights-agent.jar
+
+EXPOSE 8080
+USER 1001
+
+ENTRYPOINT ["sh", "-c", "java $JAVA_OPTIONS -jar /app/quarkus-run.jar"]
diff --git a/apps/institution-send-mail-scheduler/pom.xml b/apps/institution-send-mail-scheduler/pom.xml
index 1708b6c..7520c90 100644
--- a/apps/institution-send-mail-scheduler/pom.xml
+++ b/apps/institution-send-mail-scheduler/pom.xml
@@ -24,7 +24,7 @@
3.11.3
true
3.1.2
- 0.1.16
+ 0.1.14
2.4.2
@@ -129,6 +129,11 @@
4.13.1
test
+
+ com.azure
+ azure-storage-blob
+ 12.14.0
+
diff --git a/apps/institution-send-mail-scheduler/src/main/java/it/pagopa/selfcare/institution/config/InstitutionSendMailConfig.java b/apps/institution-send-mail-scheduler/src/main/java/it/pagopa/selfcare/institution/config/InstitutionSendMailConfig.java
index 1af3092..cbf2e3d 100644
--- a/apps/institution-send-mail-scheduler/src/main/java/it/pagopa/selfcare/institution/config/InstitutionSendMailConfig.java
+++ b/apps/institution-send-mail-scheduler/src/main/java/it/pagopa/selfcare/institution/config/InstitutionSendMailConfig.java
@@ -6,28 +6,17 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
-import io.quarkus.runtime.StartupEvent;
-import io.vertx.core.impl.logging.Logger;
-import io.vertx.core.impl.logging.LoggerFactory;
import io.vertx.core.json.jackson.DatabindCodec;
import it.pagopa.selfcare.azurestorage.AzureBlobClient;
import it.pagopa.selfcare.azurestorage.AzureBlobClientDefault;
-import it.pagopa.selfcare.institution.repository.PecNotificationsRepository;
import it.pagopa.selfcare.product.service.ProductService;
import it.pagopa.selfcare.product.service.ProductServiceDefault;
import jakarta.enterprise.context.ApplicationScoped;
-import jakarta.enterprise.event.Observes;
import jakarta.enterprise.inject.Produces;
@ApplicationScoped
public class InstitutionSendMailConfig {
- private static final Logger log = LoggerFactory.getLogger(InstitutionSendMailConfig.class);
-
- void onStart(@Observes StartupEvent ev, PecNotificationsRepository repository) {
- log.info(String.format("Database %s is starting...", repository.mongoDatabase().getName()));
- }
-
@Produces
public ObjectMapper objectMapper(){
ObjectMapper mapper = DatabindCodec.mapper();
diff --git a/apps/institution-send-mail-scheduler/src/main/java/it/pagopa/selfcare/institution/entity/PecNotification.java b/apps/institution-send-mail-scheduler/src/main/java/it/pagopa/selfcare/institution/entity/PecNotification.java
index 54210a9..4386fad 100644
--- a/apps/institution-send-mail-scheduler/src/main/java/it/pagopa/selfcare/institution/entity/PecNotification.java
+++ b/apps/institution-send-mail-scheduler/src/main/java/it/pagopa/selfcare/institution/entity/PecNotification.java
@@ -1,48 +1,22 @@
package it.pagopa.selfcare.institution.entity;
import io.quarkus.mongodb.panache.common.MongoEntity;
-import lombok.Getter;
-import org.bson.codecs.pojo.annotations.BsonId;
+import io.quarkus.mongodb.panache.reactive.ReactivePanacheMongoEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.FieldNameConstants;
import org.bson.types.ObjectId;
-@Getter
-@MongoEntity(collection="pecNotification")
-public class PecNotification {
- @BsonId
+@EqualsAndHashCode(callSuper = true)
+@Data
+@FieldNameConstants(asEnum = true)
+@MongoEntity(collection="PecNotification")
+public class PecNotification extends ReactivePanacheMongoEntity{
+
private ObjectId id;
private Integer moduleDayOfTheEpoch;
private String productId;
private String institutionId;
private String institutionMail;
-
- public void setInstitutionMail(String institutionMail) {
- this.institutionMail = institutionMail;
- }
-
- public void setId(ObjectId id) {
- this.id = id;
- }
-
- public void setModuleDayOfTheEpoch(Integer moduleDayOfTheEpoch) {
- this.moduleDayOfTheEpoch = moduleDayOfTheEpoch;
- }
-
- public void setProductId(String productId) {
- this.productId = productId;
- }
-
- public void setInstitutionId(String institutionId) {
- this.institutionId = institutionId;
- }
-
- @Override
- public String toString() {
- return "PecNotification{" +
- "id=" + id +
- ", moduleDayOfTheEpoch=" + moduleDayOfTheEpoch +
- ", productId='" + productId + '\'' +
- ", institutionId='" + institutionId + '\'' +
- ", institutionMail='" + institutionMail + '\'' +
- '}';
- }
+ private String createdAt;
}
diff --git a/apps/institution-send-mail-scheduler/src/main/java/it/pagopa/selfcare/institution/repository/PecNotificationsRepository.java b/apps/institution-send-mail-scheduler/src/main/java/it/pagopa/selfcare/institution/repository/PecNotificationsRepository.java
deleted file mode 100644
index fe85fe7..0000000
--- a/apps/institution-send-mail-scheduler/src/main/java/it/pagopa/selfcare/institution/repository/PecNotificationsRepository.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package it.pagopa.selfcare.institution.repository;
-
-import io.quarkus.mongodb.panache.PanacheMongoRepositoryBase;
-import it.pagopa.selfcare.institution.entity.PecNotification;
-import jakarta.enterprise.context.ApplicationScoped;
-
-@ApplicationScoped
-public class PecNotificationsRepository implements PanacheMongoRepositoryBase {
-}
diff --git a/apps/institution-send-mail-scheduler/src/main/java/it/pagopa/selfcare/institution/service/InstitutionSendMailScheduledServiceImpl.java b/apps/institution-send-mail-scheduler/src/main/java/it/pagopa/selfcare/institution/service/InstitutionSendMailScheduledServiceImpl.java
index e762bce..3ffd5de 100644
--- a/apps/institution-send-mail-scheduler/src/main/java/it/pagopa/selfcare/institution/service/InstitutionSendMailScheduledServiceImpl.java
+++ b/apps/institution-send-mail-scheduler/src/main/java/it/pagopa/selfcare/institution/service/InstitutionSendMailScheduledServiceImpl.java
@@ -1,12 +1,11 @@
package it.pagopa.selfcare.institution.service;
-import io.quarkus.mongodb.panache.PanacheQuery;
+import io.quarkus.mongodb.panache.reactive.ReactivePanacheMongoEntityBase;
import io.smallrye.mutiny.Multi;
import io.smallrye.mutiny.Uni;
import io.vertx.core.impl.logging.Logger;
import io.vertx.core.impl.logging.LoggerFactory;
import it.pagopa.selfcare.institution.entity.PecNotification;
-import it.pagopa.selfcare.institution.repository.PecNotificationsRepository;
import it.pagopa.selfcare.product.entity.Product;
import it.pagopa.selfcare.product.service.ProductService;
import jakarta.enterprise.context.ApplicationScoped;
@@ -24,7 +23,6 @@ public class InstitutionSendMailScheduledServiceImpl implements InstitutionSendM
private static final Logger log = LoggerFactory.getLogger(InstitutionSendMailScheduledServiceImpl.class);
private static final String PRODUCT_PLACEHOLDER = "nome_prodotto";
- private final PecNotificationsRepository pecNotificationsRepository;
private final MailServiceImpl mailService;
private final String templateMail;
private final ProductService productService;
@@ -32,14 +30,12 @@ public class InstitutionSendMailScheduledServiceImpl implements InstitutionSendM
private final Integer sendingFrequency;
private final Integer querySize;
- public InstitutionSendMailScheduledServiceImpl(PecNotificationsRepository pecNotificationsRepository,
- MailServiceImpl mailService,
+ public InstitutionSendMailScheduledServiceImpl(MailServiceImpl mailService,
@ConfigProperty(name = "institution-send-mail.notification-path") String templateMail,
@ConfigProperty(name = "institution-send-mail.notification-sending-frequency") Integer sendingFrequency,
@ConfigProperty(name = "institution-send-mail.notification-start-date") String startDate,
ProductService productService,
@ConfigProperty(name = "institution-send-mail.notification-query-size") Integer querySize) {
- this.pecNotificationsRepository = pecNotificationsRepository;
this.mailService = mailService;
this.templateMail = templateMail;
this.productService = productService;
@@ -57,24 +53,33 @@ public Uni retrieveInstitutionFromPecNotificationAndSendMail() {
public Uni retrieveFilteredAndPaginatedPecNotification(Long moduleDayOfTheEpoch, int page, int size) {
log.info("Retrieving page " + page + " of PecNotification");
- PanacheQuery query = pecNotificationsRepository.find("moduleDayOfTheEpoch", moduleDayOfTheEpoch)
+
+ var pecNotificationPage = PecNotification.find(PecNotification.Fields.moduleDayOfTheEpoch.name(), moduleDayOfTheEpoch)
.page(page, size);
- if(query.hasNextPage()) {
- return retrievePecNotificationListAndSendMail(query)
- .onItem().transformToUni(unused -> retrieveFilteredAndPaginatedPecNotification(moduleDayOfTheEpoch, page + 1, size))
- .replaceWith(0);
- }else{
- return retrievePecNotificationListAndSendMail(query)
- .replaceWith(0);
- }
+
+ return Uni.combine().all()
+ .unis(pecNotificationPage.hasNextPage(), pecNotificationPage.list())
+ .asTuple()
+ .onItem().transformToUni(tuple -> {
+ if(tuple.getItem1()) {
+ return retrievePecNotificationListAndSendMail(tuple.getItem2())
+ .onItem().transformToUni(unused -> retrieveFilteredAndPaginatedPecNotification(moduleDayOfTheEpoch, page + 1, size))
+ .replaceWith(0);
+ }else{
+ return retrievePecNotificationListAndSendMail(tuple.getItem2())
+ .replaceWith(0);
+ }
+ })
+ .onFailure().invoke(throwable -> log.error("Error during send scheduled mail", throwable));
+
}
- private Uni retrievePecNotificationListAndSendMail(PanacheQuery query) {
- return Multi.createFrom().iterable(query.list())
+ private Uni retrievePecNotificationListAndSendMail(List query) {
+ return Multi.createFrom().iterable(query)
+ .onItem().transform(entityBase -> (PecNotification) entityBase)
.onItem().transformToUniAndMerge(this::constructAndSendMail)
.onFailure().invoke(throwable -> log.error("Error during send scheduled mail", throwable))
.collect().asList()
- .onItem().invoke(list -> log.info("Mail sent to institutions"))
.replaceWith(Uni.createFrom().voidItem());
}
@@ -82,6 +87,7 @@ private Uni constructAndSendMail(PecNotification pecNotification) {
Product product = productService.getProduct(pecNotification.getProductId());
Map mailParameters = retrieveMailParameters(product.getTitle());
mailService.sendMailWithFile(List.of(pecNotification.getInstitutionMail()), templateMail, mailParameters, null, null);
+ log.info("Mail sent to institutions");
return Uni.createFrom().voidItem();
}
diff --git a/apps/institution-send-mail-scheduler/src/main/resources/application.properties b/apps/institution-send-mail-scheduler/src/main/resources/application.properties
index 86707b8..0c327d9 100644
--- a/apps/institution-send-mail-scheduler/src/main/resources/application.properties
+++ b/apps/institution-send-mail-scheduler/src/main/resources/application.properties
@@ -1,15 +1,16 @@
-quarkus.mongodb.database=pecNotification
-
+institution-send-mail.connection-string = ${MONGODB-CONNECTION-STRING:http://localhost:8080}
+quarkus.mongodb.connection-string = ${MONGODB-CONNECTION-STRING}
+quarkus.mongodb.database = selcMsCore
## MAIL
institution-send-mail.sender-mail = ${MAIL_SENDER_ADDRESS:test@test.it}
## In PROD env must be false for sending real mail
-institution-send-mail.destination-mail = ${MAIL_DESTINATION_TEST:true}
+institution-send-mail.destination-mail = ${MAIL_DESTINATION_TEST:false}
## If MAIL_DESTINATION_TEST is true, app send mail to this address
institution-send-mail.destination-mail-test-address = ${MAIL_DESTINATION_TEST_ADDRESS:test@test.it}
institution-send-mail.notification-path= ${MAIL_TEMPLATE_NOTIFICATION_PATH:test.json}
-institution-send-mail.notification-query-size = 1000
+institution-send-mail.notification-query-size = 1
institution-send-mail.notification-sending-frequency = 30
institution-send-mail.notification-start-date = 2024-01-01
diff --git a/apps/institution-send-mail-scheduler/src/test/java/it/pagopa/selfcare/institution/service/InstitutionSendMailScheduledServiceImplTest.java b/apps/institution-send-mail-scheduler/src/test/java/it/pagopa/selfcare/institution/service/InstitutionSendMailScheduledServiceImplTest.java
index 5073503..821eaa3 100644
--- a/apps/institution-send-mail-scheduler/src/test/java/it/pagopa/selfcare/institution/service/InstitutionSendMailScheduledServiceImplTest.java
+++ b/apps/institution-send-mail-scheduler/src/test/java/it/pagopa/selfcare/institution/service/InstitutionSendMailScheduledServiceImplTest.java
@@ -1,12 +1,13 @@
package it.pagopa.selfcare.institution.service;
-import io.quarkus.mongodb.panache.PanacheQuery;
+import io.quarkus.mongodb.panache.reactive.ReactivePanacheMongoEntityBase;
+import io.quarkus.mongodb.panache.reactive.ReactivePanacheQuery;
+import io.quarkus.panache.mock.PanacheMock;
import io.quarkus.test.InjectMock;
import io.quarkus.test.junit.QuarkusTest;
import io.smallrye.mutiny.Uni;
import io.smallrye.mutiny.helpers.test.UniAssertSubscriber;
import it.pagopa.selfcare.institution.entity.PecNotification;
-import it.pagopa.selfcare.institution.repository.PecNotificationsRepository;
import it.pagopa.selfcare.product.entity.Product;
import it.pagopa.selfcare.product.service.ProductService;
import jakarta.inject.Inject;
@@ -22,9 +23,6 @@
@QuarkusTest
class InstitutionSendMailScheduledServiceImplTest {
- @InjectMock
- PecNotificationsRepository pecNotificationsRepository;
-
@InjectMock
MailServiceImpl mailService;
@@ -37,15 +35,20 @@ class InstitutionSendMailScheduledServiceImplTest {
@Test
void shouldSendMailToAllPecNotificationsForCurrentModuleDay() {
List notifications = getPecNotifications();
- PanacheQuery query = Mockito.mock(PanacheQuery.class);
- PanacheQuery query2 = Mockito.mock(PanacheQuery.class);
- when(pecNotificationsRepository.find(any(), any(Object.class))).thenReturn(query);
- when(query.hasNextPage()).thenReturn(true);
- when(query2.hasNextPage()).thenReturn(false);
- when(query.page(0, 500)).thenReturn(query);
- when(query.page(1, 500)).thenReturn(query2);
- when(query.list()).thenReturn(List.of(notifications.get(0), notifications.get(1)));
- when(query2.list()).thenReturn(List.of(notifications.get(2), notifications.get(3)));
+ PanacheMock.mock(PecNotification.class);
+ ReactivePanacheQuery query = Mockito.mock(ReactivePanacheQuery.class);
+ when(PecNotification.find(any(), any(Object.class)))
+ .thenReturn(query);
+ when(query.page(0, 1000)).thenReturn(query);
+
+ ReactivePanacheQuery query2 = Mockito.mock(ReactivePanacheQuery.class);
+
+
+ when(query.page(1, 1000)).thenReturn(query2);
+ when(query.hasNextPage()).thenReturn(Uni.createFrom().item(true));
+ when(query2.hasNextPage()).thenReturn(Uni.createFrom().item(false));
+ when(query.list()).thenReturn(Uni.createFrom().item(List.of(notifications.get(0), notifications.get(1))));
+ when(query2.list()).thenReturn(Uni.createFrom().item(List.of(notifications.get(2), notifications.get(3))));
Product product = new Product();
product.setTitle("prod-io");
when(productService.getProduct("product-id")).thenReturn(product);
@@ -54,7 +57,7 @@ void shouldSendMailToAllPecNotificationsForCurrentModuleDay() {
UniAssertSubscriber subscriber = result.subscribe().withSubscriber(UniAssertSubscriber.create());
subscriber.assertItem(0).assertCompleted();
Mockito.verify(mailService, Mockito.times(4))
- .sendMailWithFile(Mockito.anyList(), Mockito.anyString(), Mockito.anyMap(), Mockito.anyString(), Mockito.isNull());
+ .sendMailWithFile(Mockito.anyList(), Mockito.anyString(), Mockito.anyMap(), Mockito.isNull(), Mockito.isNull());
}
private static List getPecNotifications() {
@@ -84,33 +87,35 @@ void shouldLogErrorAndContinueOnMailSendFailure() {
notification1.setProductId("product-id");
notification1.setInstitutionMail("test@test.it");
notification1.setModuleDayOfTheEpoch(1);
- PanacheQuery query = Mockito.mock(PanacheQuery.class);
- when(pecNotificationsRepository.find(any(), any(Object.class))).thenReturn(query);
- when(query.page(Mockito.anyInt(), Mockito.anyInt())).thenReturn(query);
- when(query.hasNextPage()).thenReturn(true);
- when(query.list()).thenReturn(List.of(notification1));
+ PanacheMock.mock(PecNotification.class);
+ ReactivePanacheQuery query = Mockito.mock(ReactivePanacheQuery.class);
+ when(PecNotification.find(any(), any(Object.class)))
+ .thenReturn(query);
+ when(query.page(0, 1000)).thenReturn(query);
+ when(query.hasNextPage()).thenReturn(Uni.createFrom().item(false));
+ when(query.list()).thenReturn(Uni.createFrom().item(List.of(notification1)));
Product product = new Product();
product.setTitle("prod-io");
when(productService.getProduct("product-id")).thenReturn(product);
- Mockito.doThrow(new RuntimeException("Mail send failed")).when(mailService).sendMailWithFile(Mockito.anyList(), Mockito.anyString(), Mockito.anyMap(), Mockito.anyString(), Mockito.isNull());
+ Mockito.doThrow(new RuntimeException("Mail send failed")).when(mailService).sendMailWithFile(Mockito.anyList(), Mockito.anyString(), Mockito.anyMap(), Mockito.isNull(), Mockito.isNull());
// Execute
Uni result = service.retrieveInstitutionFromPecNotificationAndSendMail();
UniAssertSubscriber subscriber = result.subscribe().withSubscriber(UniAssertSubscriber.create());
// Verify
- Mockito.verify(mailService).sendMailWithFile(Mockito.anyList(), Mockito.anyString(), Mockito.anyMap(), Mockito.anyString(), Mockito.isNull());
subscriber.assertFailedWith(RuntimeException.class, "Mail send failed");
}
@Test
void shouldHandleNoPecNotificationsForCurrentModuleDay() {
- // Setup mocks
- PanacheQuery query = Mockito.mock(PanacheQuery.class);
- when(pecNotificationsRepository.find(any(), any(Object.class))).thenReturn(query);
- when(query.page(Mockito.anyInt(), Mockito.anyInt())).thenReturn(query);
- when(query.hasNextPage()).thenReturn(false);
- when(query.list()).thenReturn(Collections.emptyList());
+ PanacheMock.mock(PecNotification.class);
+ ReactivePanacheQuery query = Mockito.mock(ReactivePanacheQuery.class);
+ when(PecNotification.find(any(), any(Object.class)))
+ .thenReturn(query);
+ when(query.page(0, 1000)).thenReturn(query);
+ when(query.hasNextPage()).thenReturn(Uni.createFrom().item(false));
+ when(query.list()).thenReturn(Uni.createFrom().item(Collections.emptyList()));
// Execute
Uni result = service.retrieveInstitutionFromPecNotificationAndSendMail();
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..330f52f
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,15 @@
+version: '3.8'
+
+services:
+
+ user-ms:
+ image: user-ms:latest
+ container_name: user-ms
+ restart: on-failure
+ build:
+ context: .
+ dockerfile: ./apps/institution-send-mail-scheduler/Dockerfile
+ ports:
+ - "8080:8080"
+ environment:
+ - JWT_TOKEN_PUBLIC_KEY=asdf