From 7d7a5478f975fbe7a99ef0db54e067d857f19aba Mon Sep 17 00:00:00 2001 From: Guillaume Duval <117720964+g-duval@users.noreply.github.com> Date: Wed, 15 Jan 2025 23:31:07 +0100 Subject: [PATCH] [RHCLOUD-37252] Update new aggregation logic (#3233) Co-authored-by: Gwenneg Lepage --- .../db/EmailAggregationRepository.java | 14 ++- .../DailyEventAggregationJobTest.java | 20 +---- .../db/EmailAggregationRepositoryTest.java | 29 ++----- .../helpers/ResourceHelpers.java | 87 +++++++++++++++++++ 4 files changed, 106 insertions(+), 44 deletions(-) diff --git a/aggregator/src/main/java/com/redhat/cloud/notifications/db/EmailAggregationRepository.java b/aggregator/src/main/java/com/redhat/cloud/notifications/db/EmailAggregationRepository.java index a4fe524654..6f7c6c272a 100644 --- a/aggregator/src/main/java/com/redhat/cloud/notifications/db/EmailAggregationRepository.java +++ b/aggregator/src/main/java/com/redhat/cloud/notifications/db/EmailAggregationRepository.java @@ -53,9 +53,19 @@ public List getApplicationsWithPendingAggregationAccordingOr LocalDateTime currentTimeTwoDaysAgo = now.minusDays(2); String query = "SELECT DISTINCT ev.orgId, ev.bundleId, ev.applicationId, acp.lastRun, bu.name, ap.name FROM Event ev " + "join Application ap on ev.applicationId = ap.id join Bundle bu on ev.bundleId = bu.id " + - "join AggregationOrgConfig acp on ev.orgId = acp.orgId " + - "WHERE EXISTS (SELECT 1 FROM EventTypeEmailSubscription es where ev.orgId = es.id.orgId and es.id.subscriptionType='DAILY' and es.subscribed = true) " + + "join AggregationOrgConfig acp on ev.orgId = acp.orgId WHERE " + + + // check than a aggregation template exists for the event application + "EXISTS (SELECT 1 FROM AggregationEmailTemplate WHERE application.id = ev.applicationId and subscriptionType = 'DAILY') " + + // After prod validation phase, the previous AggregationEmailTemplate check should be remove in favor of: + // check than at least one user of the org subscribed for daily digest with this event type + //"EXISTS (SELECT 1 FROM EventTypeEmailSubscription es where ev.orgId = es.id.orgId and es.id.subscriptionType='DAILY' and es.eventType = ev.eventType and es.subscribed is true) " + warning: need an new index on EventTypeEmailSubscription before being enabled + + // check for linked email integration linked to this event type (to honor legacy mechanism) + "AND EXISTS (SELECT 1 FROM Endpoint ep, EndpointEventType eet where ev.orgId = ep.orgId and ep.compositeType.type = 'EMAIL_SUBSCRIPTION' and eet.eventType = ev.eventType and eet.endpoint = ep) " + + // filter on new events since the latest run of this org aggregation, and not older than two days "AND ev.created > acp.lastRun AND ev.created > :twoDaysAgo AND ev.created <= :now " + + // filter on org scheduled execution time "AND :nowTime = acp.scheduledExecutionTime"; Query hqlQuery = entityManager.createQuery(query) .setParameter("nowTime", now.toLocalTime()) diff --git a/aggregator/src/test/java/com/redhat/cloud/notifications/DailyEventAggregationJobTest.java b/aggregator/src/test/java/com/redhat/cloud/notifications/DailyEventAggregationJobTest.java index 13568be0c8..3100c644d7 100644 --- a/aggregator/src/test/java/com/redhat/cloud/notifications/DailyEventAggregationJobTest.java +++ b/aggregator/src/test/java/com/redhat/cloud/notifications/DailyEventAggregationJobTest.java @@ -11,8 +11,6 @@ import com.redhat.cloud.notifications.models.AggregationOrgConfig; import com.redhat.cloud.notifications.models.Application; import com.redhat.cloud.notifications.models.EventAggregationCriteria; -import com.redhat.cloud.notifications.models.EventType; -import com.redhat.cloud.notifications.models.SubscriptionType; import io.prometheus.client.CollectorRegistry; import io.prometheus.client.Gauge; import io.quarkus.test.common.QuarkusTestResource; @@ -33,7 +31,6 @@ import java.time.ZoneOffset; import java.util.ArrayList; import java.util.List; -import java.util.UUID; import java.util.concurrent.ThreadLocalRandom; import static com.redhat.cloud.notifications.models.SubscriptionType.DAILY; @@ -432,20 +429,7 @@ private com.redhat.cloud.notifications.models.Event addEventEmailAggregation(Str } private com.redhat.cloud.notifications.models.Event addEventEmailAggregation(String orgId, String bundleName, String applicationName, String policyId, String inventoryId, LocalDateTime created) { - Application application = resourceHelpers.findOrCreateApplication(bundleName, applicationName); - EventType eventType = resourceHelpers.findOrCreateEventType(application.getId(), "event_type_test"); - resourceHelpers.findOrCreateEventTypeEmailSubscription(orgId, "obiwan", eventType, SubscriptionType.DAILY); - - com.redhat.cloud.notifications.models.Event event = new com.redhat.cloud.notifications.models.Event(); - event.setId(UUID.randomUUID()); - event.setOrgId(orgId); - eventType.setApplication(application); - event.setEventType(eventType); - event.setPayload( - TestHelpers.generatePayloadContent(orgId, bundleName, applicationName, policyId, inventoryId).toString() - ); - event.setCreated(created); - - return resourceHelpers.createEvent(event); + final String payload = TestHelpers.generatePayloadContent(orgId, bundleName, applicationName, policyId, inventoryId).toString(); + return resourceHelpers.addEventEmailAggregation(orgId, bundleName, applicationName, created, payload); } } diff --git a/aggregator/src/test/java/com/redhat/cloud/notifications/db/EmailAggregationRepositoryTest.java b/aggregator/src/test/java/com/redhat/cloud/notifications/db/EmailAggregationRepositoryTest.java index 44c63f38da..b910105132 100644 --- a/aggregator/src/test/java/com/redhat/cloud/notifications/db/EmailAggregationRepositoryTest.java +++ b/aggregator/src/test/java/com/redhat/cloud/notifications/db/EmailAggregationRepositoryTest.java @@ -10,8 +10,6 @@ import com.redhat.cloud.notifications.models.EmailAggregationKey; import com.redhat.cloud.notifications.models.Event; import com.redhat.cloud.notifications.models.EventAggregationCriteria; -import com.redhat.cloud.notifications.models.EventType; -import com.redhat.cloud.notifications.models.SubscriptionType; import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusTest; import io.vertx.core.json.JsonObject; @@ -23,7 +21,6 @@ import java.time.ZoneId; import java.time.ZoneOffset; import java.util.List; -import java.util.UUID; import java.util.stream.Collectors; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -101,11 +98,11 @@ private void addEmailAggregation(String orgId, String bundleName, String applica @Test void testApplicationsWithPendingAggregationAccordingOrgPref() { configureTimePref(dailyEmailAggregationJob.computeScheduleExecutionTime()); - Event event1 = addEventEmailAggregation(ORG_ID, BUNDLE_NAME, APP_NAME, PAYLOAD1, dailyEmailAggregationJob.computeScheduleExecutionTime().minusMinutes(5)); - Event event2 = addEventEmailAggregation(ORG_ID, BUNDLE_NAME, APP_NAME, PAYLOAD2, dailyEmailAggregationJob.computeScheduleExecutionTime().minusMinutes(5)); - addEventEmailAggregation("other-org-id", BUNDLE_NAME, APP_NAME, PAYLOAD2, dailyEmailAggregationJob.computeScheduleExecutionTime().minusMinutes(5)); - addEventEmailAggregation(ORG_ID, "other-bundle", APP_NAME, PAYLOAD2, dailyEmailAggregationJob.computeScheduleExecutionTime().minusMinutes(5)); - addEventEmailAggregation(ORG_ID, BUNDLE_NAME, "other-app", PAYLOAD2, dailyEmailAggregationJob.computeScheduleExecutionTime().minusMinutes(5)); + Event event1 = resourceHelpers.addEventEmailAggregation(ORG_ID, BUNDLE_NAME, APP_NAME, dailyEmailAggregationJob.computeScheduleExecutionTime().minusMinutes(5), PAYLOAD1.toString()); + Event event2 = resourceHelpers.addEventEmailAggregation(ORG_ID, BUNDLE_NAME, APP_NAME, dailyEmailAggregationJob.computeScheduleExecutionTime().minusMinutes(5), PAYLOAD2.toString()); + resourceHelpers.addEventEmailAggregation("other-org-id", BUNDLE_NAME, APP_NAME, dailyEmailAggregationJob.computeScheduleExecutionTime().minusMinutes(5), PAYLOAD2.toString()); + resourceHelpers.addEventEmailAggregation(ORG_ID, "other-bundle", APP_NAME, dailyEmailAggregationJob.computeScheduleExecutionTime().minusMinutes(5), PAYLOAD2.toString()); + resourceHelpers.addEventEmailAggregation(ORG_ID, BUNDLE_NAME, "other-app", dailyEmailAggregationJob.computeScheduleExecutionTime().minusMinutes(5), PAYLOAD2.toString()); List keys = emailAggregationResources.getApplicationsWithPendingAggregationAccordingOrgPref(dailyEmailAggregationJob.computeScheduleExecutionTime()); assertEquals(4, keys.size()); @@ -124,20 +121,4 @@ void testApplicationsWithPendingAggregationAccordingOrgPref() { matchedKeys = keys.stream().filter(k -> ORG_ID.equals(k.getOrgId())).filter(k -> (((EventAggregationCriteria) k.getAggregationKey()).getApplicationId().equals(application.getId()))).collect(Collectors.toList()); assertEquals(0, matchedKeys.size()); } - - private Event addEventEmailAggregation(String orgId, String bundleName, String applicationName, JsonObject payload, LocalDateTime created) { - Application application = resourceHelpers.findOrCreateApplication(bundleName, applicationName); - EventType eventType = resourceHelpers.findOrCreateEventType(application.getId(), "event_type_test"); - resourceHelpers.findOrCreateEventTypeEmailSubscription(orgId, "obiwan", eventType, SubscriptionType.DAILY); - - Event event = new Event(); - event.setId(UUID.randomUUID()); - event.setOrgId(orgId); - eventType.setApplication(application); - event.setEventType(eventType); - event.setPayload(payload.toString()); - event.setCreated(created); - - return resourceHelpers.createEvent(event); - } } diff --git a/aggregator/src/test/java/com/redhat/cloud/notifications/helpers/ResourceHelpers.java b/aggregator/src/test/java/com/redhat/cloud/notifications/helpers/ResourceHelpers.java index a4a1e4f835..90bab0562b 100644 --- a/aggregator/src/test/java/com/redhat/cloud/notifications/helpers/ResourceHelpers.java +++ b/aggregator/src/test/java/com/redhat/cloud/notifications/helpers/ResourceHelpers.java @@ -1,15 +1,28 @@ package com.redhat.cloud.notifications.helpers; +import com.redhat.cloud.notifications.models.AggregationEmailTemplate; import com.redhat.cloud.notifications.models.AggregationOrgConfig; +import com.redhat.cloud.notifications.models.Application; import com.redhat.cloud.notifications.models.EmailAggregation; import com.redhat.cloud.notifications.models.EmailAggregationKey; +import com.redhat.cloud.notifications.models.Endpoint; +import com.redhat.cloud.notifications.models.EndpointType; +import com.redhat.cloud.notifications.models.Event; +import com.redhat.cloud.notifications.models.EventType; +import com.redhat.cloud.notifications.models.SubscriptionType; +import com.redhat.cloud.notifications.models.Template; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import jakarta.persistence.EntityManager; +import jakarta.persistence.NoResultException; import jakarta.transaction.Transactional; +import org.apache.commons.lang3.RandomStringUtils; import java.time.LocalDateTime; import java.time.ZoneOffset; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; @ApplicationScoped public class ResourceHelpers extends com.redhat.cloud.notifications.models.ResourceHelpers { @@ -75,4 +88,78 @@ public Integer purgeOldAggregation(EmailAggregationKey key, LocalDateTime lastUs .setParameter("created", lastUsedTime) .executeUpdate(); } + + @Transactional + public Endpoint getOrCreateEmailEndpointAndLinkItToEventType(final String orgId, final EventType eventType) { + Endpoint emailEndpoint; + try { + final String query = "FROM Endpoint WHERE orgId = :orgId AND compositeType.type = :type"; + emailEndpoint = entityManager.createQuery(query, Endpoint.class) + .setParameter("orgId", orgId) + .setParameter("type", EndpointType.EMAIL_SUBSCRIPTION) + .getSingleResult(); + } catch (NoResultException e) { + emailEndpoint = new Endpoint(); + emailEndpoint.setType(EndpointType.EMAIL_SUBSCRIPTION); + emailEndpoint.setOrgId(orgId); + emailEndpoint.setName(RandomStringUtils.secure().nextAlphabetic(10)); + emailEndpoint.setDescription(RandomStringUtils.randomAlphabetic(10)); + entityManager.persist(emailEndpoint); + } + + Set linkedEventTypes = emailEndpoint.getEventTypes(); + if (linkedEventTypes == null) { + linkedEventTypes = new HashSet<>(); + } + linkedEventTypes.add(eventType); + emailEndpoint.setEventTypes(linkedEventTypes); + return entityManager.merge(emailEndpoint); + } + + @Transactional + public AggregationEmailTemplate getOrCreateAggregationTemplate(Application application) { + try { + String query = "FROM AggregationEmailTemplate WHERE application.id = :appId"; + return entityManager.createQuery(query, AggregationEmailTemplate.class) + .setParameter("appId", application.getId()) + .getSingleResult(); + } catch (NoResultException e) { + Template emailTemplate = new Template(); + emailTemplate.setName(RandomStringUtils.randomAlphabetic(10)); + emailTemplate.setData(RandomStringUtils.randomAlphabetic(10)); + emailTemplate.setDescription(RandomStringUtils.randomAlphabetic(10)); + entityManager.persist(emailTemplate); + + AggregationEmailTemplate aggregationEmailTemplate = new AggregationEmailTemplate(); + aggregationEmailTemplate.setApplication(application); + aggregationEmailTemplate.setApplicationId(application.getId()); + aggregationEmailTemplate.setSubscriptionType(SubscriptionType.DAILY); + aggregationEmailTemplate.setBodyTemplate(emailTemplate); + aggregationEmailTemplate.setBodyTemplateId(emailTemplate.getId()); + aggregationEmailTemplate.setSubjectTemplate(emailTemplate); + aggregationEmailTemplate.setSubjectTemplateId(emailTemplate.getId()); + aggregationEmailTemplate.setApplication(application); + entityManager.persist(aggregationEmailTemplate); + return aggregationEmailTemplate; + } + } + + public Event addEventEmailAggregation(String orgId, String bundleName, String applicationName, LocalDateTime created, String eventPayload) { + Application application = findOrCreateApplication(bundleName, applicationName); + EventType eventType = findOrCreateEventType(application.getId(), "event_type_test"); + findOrCreateEventTypeEmailSubscription(orgId, "obiwan", eventType, SubscriptionType.DAILY); + + getOrCreateEmailEndpointAndLinkItToEventType(orgId, eventType); + getOrCreateAggregationTemplate(application); + + Event event = new Event(); + event.setId(UUID.randomUUID()); + event.setOrgId(orgId); + eventType.setApplication(application); + event.setEventType(eventType); + event.setCreated(created); + event.setPayload(eventPayload); + + return createEvent(event); + } }