Skip to content

Commit

Permalink
Update ResourceHelpers.java, EmailAggregationRepositoryBasedOnEventTe…
Browse files Browse the repository at this point in the history
…st.java, and EmailAggregatorTest.java
  • Loading branch information
g-duval committed Jul 4, 2024
1 parent 4cbf07c commit cd563ed
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 58 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.redhat.cloud.notifications.db;

import com.redhat.cloud.notifications.TestHelpers;
import com.redhat.cloud.notifications.db.repositories.EmailAggregationRepository;
import com.redhat.cloud.notifications.models.AggregationEmailTemplate;
import com.redhat.cloud.notifications.models.Application;
Expand All @@ -23,10 +24,12 @@
import org.apache.commons.lang3.StringUtils;

import java.security.SecureRandom;
import java.time.LocalDateTime;
import java.util.UUID;

import static com.redhat.cloud.notifications.TestConstants.DEFAULT_ORG_ID;
import static com.redhat.cloud.notifications.models.SubscriptionType.DAILY;
import static java.time.ZoneOffset.UTC;

@ApplicationScoped
public class ResourceHelpers {
Expand Down Expand Up @@ -284,4 +287,34 @@ public EventTypeEmailSubscription findOrCreateEventTypeEmailSubscription(String
}
return eventTypeEmailSubscription;
}

public com.redhat.cloud.notifications.models.Event addEventEmailAggregation(String orgId, String bundleName, String applicationName, JsonObject payload) {
return addEventEmailAggregation(orgId, bundleName, applicationName, payload, true);
}

public com.redhat.cloud.notifications.models.Event addEventEmailAggregation(String orgId, String bundleName, String applicationName, JsonObject payload, boolean addUserSubscription) {
Application application = findOrCreateApplication(bundleName, applicationName);
EventType eventType = findOrCreateEventType(application.getId(), TestHelpers.eventType);
if (addUserSubscription) {
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(payload.toString());
event.setCreated(LocalDateTime.now(UTC));

Event retevent = createEvent(event);

return retevent;
}

@Transactional
public void clearEvents() {
entityManager.createQuery("DELETE FROM Event")
.executeUpdate();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,18 @@
import com.redhat.cloud.notifications.models.Application;
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;
import jakarta.inject.Inject;
import jakarta.persistence.EntityManager;
import jakarta.transaction.Transactional;
import org.junit.jupiter.api.Test;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.List;
import java.util.UUID;

import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

@QuarkusTest
@QuarkusTestResource(TestLifecycleManager.class)
Expand Down Expand Up @@ -48,12 +45,12 @@ void testAllMethods() {
Application application = resourceHelpers.findOrCreateApplication(BUNDLE_NAME, APP_NAME);
EventAggregationCriteria key = new EventAggregationCriteria(ORG_ID, application.getBundleId(), application.getId(), BUNDLE_NAME, APP_NAME);

clearEvents();
addEventEmailAggregation(ORG_ID, BUNDLE_NAME, APP_NAME, PAYLOAD1);
addEventEmailAggregation(ORG_ID, BUNDLE_NAME, APP_NAME, PAYLOAD2);
addEventEmailAggregation("other-org-id", BUNDLE_NAME, APP_NAME, PAYLOAD2);
addEventEmailAggregation(ORG_ID, "other-bundle", APP_NAME, PAYLOAD2);
addEventEmailAggregation(ORG_ID, BUNDLE_NAME, "other-app", PAYLOAD2);
resourceHelpers.clearEvents();
resourceHelpers.addEventEmailAggregation(ORG_ID, BUNDLE_NAME, APP_NAME, PAYLOAD1);
resourceHelpers.addEventEmailAggregation(ORG_ID, BUNDLE_NAME, APP_NAME, PAYLOAD2);
resourceHelpers.addEventEmailAggregation("other-org-id", BUNDLE_NAME, APP_NAME, PAYLOAD2);
resourceHelpers.addEventEmailAggregation(ORG_ID, "other-bundle", APP_NAME, PAYLOAD2);
resourceHelpers.addEventEmailAggregation(ORG_ID, BUNDLE_NAME, "other-app", PAYLOAD2);

List<Event> aggregations = emailAggregationRepository.getEmailAggregationBasedOnEvent(key, start, end, 0, 10);
assertEquals(2, aggregations.size());
Expand All @@ -63,30 +60,8 @@ void testAllMethods() {
assertEquals(1, aggregations.stream().map(Event::getPayload).map(payload -> new JsonObject(payload)).filter(PAYLOAD1::equals).count());
assertEquals(1, aggregations.stream().map(Event::getPayload).map(payload -> new JsonObject(payload)).filter(PAYLOAD2::equals).count());

clearEvents();
resourceHelpers.clearEvents();
}

@Transactional
void clearEvents() {
entityManager.createQuery("DELETE FROM Event")
.executeUpdate();
}

private com.redhat.cloud.notifications.models.Event addEventEmailAggregation(String orgId, String bundleName, String applicationName, JsonObject payload) {
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(payload.toString());
event.setCreated(LocalDateTime.now(UTC));

Event retevent = resourceHelpers.createEvent(event);

return retevent;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,26 @@
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.EventAggregationCriteria;
import com.redhat.cloud.notifications.models.EventType;
import com.redhat.cloud.notifications.models.SystemSubscriptionProperties;
import com.redhat.cloud.notifications.recipients.RecipientResolver;
import com.redhat.cloud.notifications.recipients.User;
import com.redhat.cloud.notifications.recipients.recipientsresolver.RecipientsResolverService;
import com.redhat.cloud.notifications.recipients.recipientsresolver.pojo.RecipientsQuery;
import io.quarkus.cache.CacheInvalidate;
import io.quarkus.cache.Cache;
import io.quarkus.cache.CacheManager;
import io.quarkus.test.InjectMock;
import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.junit.mockito.InjectSpy;
import io.vertx.core.json.JsonObject;
import jakarta.inject.Inject;
import org.apache.commons.lang3.RandomStringUtils;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.ValueSource;

import java.time.LocalDateTime;
Expand All @@ -34,6 +37,7 @@
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -76,6 +80,9 @@ class EmailAggregatorTest {
@InjectMock
EndpointRepository endpointRepository;

@Inject
CacheManager cacheManager;

Application application;
EventType eventType1;
EventType eventType2;
Expand All @@ -84,22 +91,23 @@ class EmailAggregatorTest {
@BeforeEach
void beforeEach() {
emailAggregator.maxPageSize = 5;
clearCachedData();
clearCachedData("recipients-resolver-results");
clearInvocations(recipientsResolverService);
clearInvocations(recipientResolver);
emailAggregationRepository.purgeOldAggregation(aggregationKey, LocalDateTime.now(ZoneOffset.UTC).plusMinutes(1));
resourceHelpers.clearEvents();
}

@AfterEach
void afterEach() {
resourceHelpers.deleteEventTypeEmailSubscription("org-1", "user-2", eventType2, DAILY);
resourceHelpers.deleteEventTypeEmailSubscription("org-1", "user-2", eventType1, DAILY);
resourceHelpers.clearEvents();
}

@ParameterizedTest
@ValueSource(booleans = {true, false})
void shouldTestRecipientsFromSubscription(boolean useRecipientsResolverClowdappForDailyDigestEnabled) {

@CsvSource({"true,true", "true,false", "false,true", "false,false"})
void shouldTestRecipientsFromSubscription(boolean useRecipientsResolverClowdappForDailyDigestEnabled, boolean isAggregationBasedOnEvents) {
when(engineConfig.isAggregationWithRecipientsResolverEnabled()).thenReturn(useRecipientsResolverClowdappForDailyDigestEnabled);
// init test environment
application = resourceHelpers.findApp("rhel", "policies");
Expand Down Expand Up @@ -136,9 +144,18 @@ void shouldTestRecipientsFromSubscription(boolean useRecipientsResolverClowdappF
}

// Test user subscription based on event type
Map<User, Map<String, Object>> result = aggregate();
verify(emailAggregationRepository, times(1)).getEmailAggregation(any(EmailAggregationKey.class), any(LocalDateTime.class), any(LocalDateTime.class), anyInt(), anyInt());
verify(emailAggregationRepository, times(1)).getEmailAggregation(any(EmailAggregationKey.class), any(LocalDateTime.class), any(LocalDateTime.class), eq(0), eq(emailAggregator.maxPageSize));
Map<User, Map<String, Object>> result = null;
if (isAggregationBasedOnEvents) {
result = aggregateWithEvents();
verify(emailAggregationRepository, times(1)).getEmailAggregationBasedOnEvent(any(EventAggregationCriteria.class), any(LocalDateTime.class), any(LocalDateTime.class), anyInt(), anyInt());
verify(emailAggregationRepository, times(1)).getEmailAggregationBasedOnEvent(any(EventAggregationCriteria.class), any(LocalDateTime.class), any(LocalDateTime.class), eq(0), eq(emailAggregator.maxPageSize));
} else {
result = aggregate();
verify(emailAggregationRepository, times(1)).getEmailAggregation(any(EmailAggregationKey.class), any(LocalDateTime.class), any(LocalDateTime.class), anyInt(), anyInt());
verify(emailAggregationRepository, times(1)).getEmailAggregation(any(EmailAggregationKey.class), any(LocalDateTime.class), any(LocalDateTime.class), eq(0), eq(emailAggregator.maxPageSize));
}
//clearCachedData("recipients-resolver-results");

verifyRecipientsResolverInteractions(4);

// nobody subscribed to the right event type yet
Expand All @@ -147,19 +164,27 @@ void shouldTestRecipientsFromSubscription(boolean useRecipientsResolverClowdappF
clearInvocations(emailAggregationRepository);
resourceHelpers.createEventTypeEmailSubscription("org-1", "user-2", eventType1, DAILY);
// because after the previous aggregate() call the email_aggregation DB table was not purged, we already have 4 records on database
result = aggregate();
verify(emailAggregationRepository, times(2)).getEmailAggregation(any(EmailAggregationKey.class), any(LocalDateTime.class), any(LocalDateTime.class), anyInt(), anyInt());
verify(emailAggregationRepository, times(1)).getEmailAggregation(any(EmailAggregationKey.class), any(LocalDateTime.class), any(LocalDateTime.class), eq(0), eq(emailAggregator.maxPageSize));
verify(emailAggregationRepository, times(1)).getEmailAggregation(any(EmailAggregationKey.class), any(LocalDateTime.class), any(LocalDateTime.class), eq(5), eq(emailAggregator.maxPageSize));
if (isAggregationBasedOnEvents) {
result = aggregateWithEvents();
verify(emailAggregationRepository, times(2)).getEmailAggregationBasedOnEvent(any(EventAggregationCriteria.class), any(LocalDateTime.class), any(LocalDateTime.class), anyInt(), anyInt());
verify(emailAggregationRepository, times(1)).getEmailAggregationBasedOnEvent(any(EventAggregationCriteria.class), any(LocalDateTime.class), any(LocalDateTime.class), eq(0), eq(emailAggregator.maxPageSize));
verify(emailAggregationRepository, times(1)).getEmailAggregationBasedOnEvent(any(EventAggregationCriteria.class), any(LocalDateTime.class), any(LocalDateTime.class), eq(5), eq(emailAggregator.maxPageSize));
} else {
result = aggregate();
verify(emailAggregationRepository, times(2)).getEmailAggregation(any(EmailAggregationKey.class), any(LocalDateTime.class), any(LocalDateTime.class), anyInt(), anyInt());
verify(emailAggregationRepository, times(1)).getEmailAggregation(any(EmailAggregationKey.class), any(LocalDateTime.class), any(LocalDateTime.class), eq(0), eq(emailAggregator.maxPageSize));
verify(emailAggregationRepository, times(1)).getEmailAggregation(any(EmailAggregationKey.class), any(LocalDateTime.class), any(LocalDateTime.class), eq(5), eq(emailAggregator.maxPageSize));
}
assertEquals(1, result.size());
User user = result.keySet().stream().findFirst().get();
assertTrue(user.getEmail().equals("user-2"));
assertEquals(8, ((LinkedHashMap) result.get(user).get("policies")).size());
verifyRecipientsResolverInteractions(12);
}

@Test
void shouldTestFallbackOnLegacyRecipientsResolverFetching() {
@ParameterizedTest
@ValueSource(booleans = {true, false})
void shouldTestFallbackOnLegacyRecipientsResolverFetching(boolean isAggregationBasedOnEvents) {

when(engineConfig.isAggregationWithRecipientsResolverEnabled()).thenReturn(true);
// init test environment
Expand Down Expand Up @@ -187,9 +212,16 @@ void shouldTestFallbackOnLegacyRecipientsResolverFetching() {
});

// Test user subscription based on event type
Map<User, Map<String, Object>> result = aggregate();
verify(emailAggregationRepository, times(1)).getEmailAggregation(any(EmailAggregationKey.class), any(LocalDateTime.class), any(LocalDateTime.class), anyInt(), anyInt());
verify(emailAggregationRepository, times(1)).getEmailAggregation(any(EmailAggregationKey.class), any(LocalDateTime.class), any(LocalDateTime.class), eq(0), eq(emailAggregator.maxPageSize));
Map<User, Map<String, Object>> result = null;
if (isAggregationBasedOnEvents) {
result = aggregateWithEvents();
verify(emailAggregationRepository, times(1)).getEmailAggregationBasedOnEvent(any(EventAggregationCriteria.class), any(LocalDateTime.class), any(LocalDateTime.class), anyInt(), anyInt());
verify(emailAggregationRepository, times(1)).getEmailAggregationBasedOnEvent(any(EventAggregationCriteria.class), any(LocalDateTime.class), any(LocalDateTime.class), eq(0), eq(emailAggregator.maxPageSize));
} else {
result = aggregate();
verify(emailAggregationRepository, times(1)).getEmailAggregation(any(EmailAggregationKey.class), any(LocalDateTime.class), any(LocalDateTime.class), anyInt(), anyInt());
verify(emailAggregationRepository, times(1)).getEmailAggregation(any(EmailAggregationKey.class), any(LocalDateTime.class), any(LocalDateTime.class), eq(0), eq(emailAggregator.maxPageSize));
}
verify(recipientsResolverService, times(4)).getRecipients(any());
verify(recipientResolver, times(4)).recipientUsers(anyString(), any(), any());

Expand Down Expand Up @@ -219,11 +251,25 @@ private Map<User, Map<String, Object>> aggregate() {
return result;
}

@CacheInvalidate(cacheName = "recipients-resolver-results")
void clearCachedData() {
/*
* This would normally happen after a certain duration fixed in application.properties with the
* quarkus.cache.caffeine.recipients-resolver-results.expire-after-write key.
*/
private Map<User, Map<String, Object>> aggregateWithEvents() {
Map<User, Map<String, Object>> result = new HashMap<>();
for (int i = 0; i < 4; i++) {
JsonObject payload = TestHelpers.createEmailAggregation("org-1", "rhel", "policies", RandomStringUtils.random(10), RandomStringUtils.random(10)).getPayload();
resourceHelpers.addEventEmailAggregation("org-1", "rhel", "policies", payload, false);
}
JsonObject payload = TestHelpers.createEmailAggregation("org-2", "rhel", "policies", RandomStringUtils.random(10), RandomStringUtils.random(10)).getPayload();
resourceHelpers.addEventEmailAggregation("org-2", "rhel", "policies", payload, false);

Application policiesApp = resourceHelpers.findApp("rhel", "policies");
EventAggregationCriteria eventAggregationCriteria = new EventAggregationCriteria(aggregationKey.getOrgId(), policiesApp.getBundleId(), policiesApp.getId(), aggregationKey.getBundle(), aggregationKey.getApplication());
result.putAll(emailAggregator.getAggregated(application.getId(), eventAggregationCriteria, DAILY, LocalDateTime.now(ZoneOffset.UTC).minusMinutes(1), LocalDateTime.now(ZoneOffset.UTC).plusMinutes(1)));
return result;
}

public void clearCachedData(String cacheName) {
Optional<Cache> cache = cacheManager.getCache(cacheName);
if (cache.isPresent()) {
cache.get().invalidateAll().await().indefinitely();
}
}
}

0 comments on commit cd563ed

Please sign in to comment.