From 963be584447dccaa0413bd776e99232663191acf Mon Sep 17 00:00:00 2001 From: Ouahid Khelifi Date: Thu, 19 Sep 2024 14:02:44 +0200 Subject: [PATCH] fix: migrate dictionaries event with latest start or stop publish or unpublish state (cherry picked from commit cae1d1561e1f2aa97b6242aa1b3d4cf6196d8eb1) (cherry picked from commit 86a941e2bd59d0aeac0334c0f40a22aa8ab215d4) --- .../rest/api/service/EventService.java | 2 + .../api/service/impl/EventServiceImpl.java | 2 +- .../upgrader/EventsLatestUpgrader.java | 95 ++++++++++++++----- .../upgrader/EventsLatestUpgraderTest.java | 51 +++++++++- 4 files changed, 121 insertions(+), 29 deletions(-) diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/rest/api/service/EventService.java b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/rest/api/service/EventService.java index f75a6b4bacd..6820a8e7b8b 100644 --- a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/rest/api/service/EventService.java +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/rest/api/service/EventService.java @@ -32,6 +32,8 @@ * @author Titouan COMPIEGNE */ public interface EventService { + public static final String EVENT_LATEST_DYNAMIC_SUFFIX = "-dynamic"; + EventEntity findById(ExecutionContext executionContext, String id); EventEntity createApiEvent( diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/rest/api/service/impl/EventServiceImpl.java b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/rest/api/service/impl/EventServiceImpl.java index 3098b308f4e..6b76119a0dc 100644 --- a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/rest/api/service/impl/EventServiceImpl.java +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/rest/api/service/impl/EventServiceImpl.java @@ -198,7 +198,7 @@ public EventEntity createDynamicDictionaryEvent( eventProperties.put(Event.EventProperties.DICTIONARY_ID.getValue(), dictionaryId); } EventEntity event = createEvent(executionContext, environmentsIds, organizationId, type, null, eventProperties); - createOrPatchLatestEvent(dictionaryId + "-dynamic", organizationId, event); + createOrPatchLatestEvent(dictionaryId + EVENT_LATEST_DYNAMIC_SUFFIX, organizationId, event); return event; } diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/rest/api/service/impl/upgrade/upgrader/EventsLatestUpgrader.java b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/rest/api/service/impl/upgrade/upgrader/EventsLatestUpgrader.java index 3a6c14d4557..16cea1b790e 100644 --- a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/rest/api/service/impl/upgrade/upgrader/EventsLatestUpgrader.java +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/rest/api/service/impl/upgrade/upgrader/EventsLatestUpgrader.java @@ -29,8 +29,11 @@ import io.gravitee.repository.management.api.search.EventCriteria; import io.gravitee.repository.management.api.search.builder.PageableBuilder; import io.gravitee.repository.management.model.Dictionary; +import io.gravitee.repository.management.model.DictionaryType; import io.gravitee.repository.management.model.Event; +import io.gravitee.repository.management.model.EventType; import io.gravitee.repository.management.model.Organization; +import io.gravitee.rest.api.service.EventService; import java.util.HashMap; import java.util.List; import java.util.Set; @@ -127,8 +130,9 @@ private void migrateDictionaryEvents() throws TechnicalException { eventsForModelCounter = 0; Set dictionaries = this.dictionaryRepository.findAll(); if (dictionaries != null) { - List ids = dictionaries.stream().map(Dictionary::getId).collect(Collectors.toList()); - migrateEvents(Event.EventProperties.DICTIONARY_ID.getValue(), ids); + for (Dictionary dictionary : dictionaries) { + migrateDictionaryEvents(dictionary); + } } log.info("{} events regarding {} dictionaries have been migrated", eventsForModelCounter, modelCounter); } @@ -148,29 +152,72 @@ private void migrateOrganizationEvents() throws TechnicalException { private void migrateEvents(final String propertyId, final List ids) throws TechnicalException { for (String id : ids) { modelCounter++; - Page search = - this.eventRepository.search( - EventCriteria.builder().property(propertyId, id).build(), - new PageableBuilder().pageNumber(0).pageSize(1).build() - ); - if (search.getPageElements() > 0) { - Event event = search.getContent().get(0); - if (event.getProperties() == null) { - event.setProperties(new HashMap<>()); - } - event.getProperties().put(Event.EventProperties.ID.getValue(), event.getId()); - event.setId(id); - // allow to reformat json payload without pretty - if (event.getPayload() != null) { - try { - event.setPayload(objectMapper.writeValueAsString(objectMapper.readTree(event.getPayload()))); - } catch (JsonProcessingException e) { - // Ignore this and keep existing payload - } - } - this.eventLatestRepository.createOrUpdate(event); - eventsForModelCounter++; + Page eventPage = searchEvents(propertyId, id); + if (eventPage.getPageElements() > 0) { + processEvent(eventPage.getContent().get(0), id); + } + } + } + + private void migrateDictionaryEvents(Dictionary dictionary) throws TechnicalException { + Page eventPage = searchEvents( + Event.EventProperties.DICTIONARY_ID.getValue(), + dictionary.getId(), + Set.of(EventType.PUBLISH_DICTIONARY, EventType.UNPUBLISH_DICTIONARY) + ); + if (eventPage.getPageElements() > 0) { + Event event = eventPage.getContent().get(0); + processEvent( + event, + DictionaryType.DYNAMIC.equals(dictionary.getType()) + ? dictionary.getId() + EventService.EVENT_LATEST_DYNAMIC_SUFFIX + : dictionary.getId() + ); + } + + if (DictionaryType.DYNAMIC.equals(dictionary.getType())) { + eventPage = + searchEvents( + Event.EventProperties.DICTIONARY_ID.getValue(), + dictionary.getId(), + Set.of(EventType.START_DICTIONARY, EventType.STOP_DICTIONARY) + ); + if (eventPage.getPageElements() > 0) { + Event event = eventPage.getContent().get(0); + processEvent(event, dictionary.getId()); + } + } + } + + private Page searchEvents(String propertyId, String id) { + return searchEvents(propertyId, id, null); + } + + private Page searchEvents(String propertyId, String id, Set types) { + EventCriteria.EventCriteriaBuilder criteria = EventCriteria.builder().property(propertyId, id); + + if (types != null && !types.isEmpty()) { + criteria.types(types); + } + + return this.eventRepository.search(criteria.build(), new PageableBuilder().pageNumber(0).pageSize(1).build()); + } + + private void processEvent(Event event, String id) throws TechnicalException { + if (event.getProperties() == null) { + event.setProperties(new HashMap<>()); + } + event.getProperties().put(Event.EventProperties.ID.getValue(), event.getId()); + event.setId(id); + // allow to reformat json payload without pretty + if (event.getPayload() != null) { + try { + event.setPayload(objectMapper.writeValueAsString(objectMapper.readTree(event.getPayload()))); + } catch (JsonProcessingException e) { + // Ignore this and keep existing payload } } + this.eventLatestRepository.createOrUpdate(event); + eventsForModelCounter++; } } diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/test/java/io/gravitee/rest/api/service/impl/upgrade/upgrader/EventsLatestUpgraderTest.java b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/test/java/io/gravitee/rest/api/service/impl/upgrade/upgrader/EventsLatestUpgraderTest.java index 85089752262..562f768d53d 100644 --- a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/test/java/io/gravitee/rest/api/service/impl/upgrade/upgrader/EventsLatestUpgraderTest.java +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/test/java/io/gravitee/rest/api/service/impl/upgrade/upgrader/EventsLatestUpgraderTest.java @@ -16,6 +16,7 @@ package io.gravitee.rest.api.service.impl.upgrade.upgrader; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.tuple; import static org.junit.Assert.assertFalse; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.argThat; @@ -37,8 +38,11 @@ import io.gravitee.repository.management.api.search.EventCriteria; import io.gravitee.repository.management.api.search.builder.PageableBuilder; import io.gravitee.repository.management.model.Dictionary; +import io.gravitee.repository.management.model.DictionaryType; import io.gravitee.repository.management.model.Event; +import io.gravitee.repository.management.model.EventType; import io.gravitee.repository.management.model.Organization; +import io.gravitee.rest.api.service.EventService; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -48,6 +52,8 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; @@ -76,6 +82,9 @@ public class EventsLatestUpgraderTest { @Mock private EventsLatestUpgrader cut; + @Captor + private ArgumentCaptor eventCaptor; + @Before public void before() { cut = @@ -187,32 +196,66 @@ public void should_create_latest_events_from_existing_apis_with_valid_and_invali public void should_create_latest_events_from_existing_dictionaries() throws TechnicalException { Dictionary dictionary1 = new Dictionary(); dictionary1.setId("dictionary1"); + dictionary1.setType(DictionaryType.DYNAMIC); Dictionary dictionary2 = new Dictionary(); dictionary2.setId("dictionary2"); + dictionary2.setType(DictionaryType.MANUAL); when(dictionaryRepository.findAll()).thenReturn(Set.of(dictionary1, dictionary2)); Event event1 = new Event(); + event1.setType(EventType.PUBLISH_DICTIONARY); when( eventRepository.search( - EventCriteria.builder().property(Event.EventProperties.DICTIONARY_ID.getValue(), dictionary1.getId()).build(), + EventCriteria + .builder() + .property(Event.EventProperties.DICTIONARY_ID.getValue(), dictionary1.getId()) + .types(Set.of(EventType.PUBLISH_DICTIONARY, EventType.UNPUBLISH_DICTIONARY)) + .build(), new PageableBuilder().pageNumber(0).pageSize(1).build() ) ) .thenReturn(new Page<>(List.of(event1), 0, 1, 1)); when(eventLatestRepository.createOrUpdate(event1)).thenReturn(event1); Event event2 = new Event(); + event2.setType(EventType.STOP_DICTIONARY); when( eventRepository.search( - EventCriteria.builder().property(Event.EventProperties.DICTIONARY_ID.getValue(), dictionary2.getId()).build(), + EventCriteria + .builder() + .property(Event.EventProperties.DICTIONARY_ID.getValue(), dictionary1.getId()) + .types(Set.of(EventType.START_DICTIONARY, EventType.STOP_DICTIONARY)) + .build(), new PageableBuilder().pageNumber(0).pageSize(1).build() ) ) .thenReturn(new Page<>(List.of(event2), 0, 1, 1)); when(eventLatestRepository.createOrUpdate(event2)).thenReturn(event2); + Event event3 = new Event(); + event3.setType(EventType.UNPUBLISH_DICTIONARY); + when( + eventRepository.search( + EventCriteria + .builder() + .property(Event.EventProperties.DICTIONARY_ID.getValue(), dictionary2.getId()) + .types(Set.of(EventType.PUBLISH_DICTIONARY, EventType.UNPUBLISH_DICTIONARY)) + .build(), + new PageableBuilder().pageNumber(0).pageSize(1).build() + ) + ) + .thenReturn(new Page<>(List.of(event3), 0, 1, 1)); + when(eventLatestRepository.createOrUpdate(event3)).thenReturn(event3); cut.upgrade(); - verify(eventLatestRepository).createOrUpdate(event1); - verify(eventLatestRepository).createOrUpdate(event2); + verify(eventLatestRepository, times(3)).createOrUpdate(eventCaptor.capture()); + var eventsSaved = eventCaptor.getAllValues(); + assertThat(eventsSaved) + .extracting(Event::getId, Event::getType) + .containsExactlyInAnyOrder( + tuple("dictionary1" + EventService.EVENT_LATEST_DYNAMIC_SUFFIX, EventType.PUBLISH_DICTIONARY), + tuple("dictionary1", EventType.STOP_DICTIONARY), + tuple("dictionary2", EventType.UNPUBLISH_DICTIONARY) + ); + verifyNoMoreInteractions(eventLatestRepository); }