From f4181832b8df66a073969fe45d11e76376864f0f Mon Sep 17 00:00:00 2001 From: amckenzie Date: Tue, 22 Oct 2019 15:04:28 +0100 Subject: [PATCH] Better error message for badly linked events --- CHANGELOG.md | 2 + .../process/EventLinkageChecker.java | 24 +++++---- .../EventLinkageErrorMessageGenerator.java | 37 +++++++++++++ .../process/LinkedEventNumberTable.java | 17 ++++++ .../verifiers/ProcessedEventLinkVerifier.java | 4 +- .../verifiers/PublishedEventLinkVerifier.java | 4 +- .../process/EventLinkageCheckerTest.java | 45 +++++++++------- ...EventLinkageErrorMessageGeneratorTest.java | 54 +++++++++++++++++++ .../ProcessedEventLinkVerifierTest.java | 3 +- .../PublishedEventLinkVerifierTest.java | 3 +- 10 files changed, 161 insertions(+), 32 deletions(-) create mode 100644 event-store-management/event-store-management-core/src/main/java/uk/gov/justice/services/eventstore/management/validation/process/EventLinkageErrorMessageGenerator.java create mode 100644 event-store-management/event-store-management-core/src/main/java/uk/gov/justice/services/eventstore/management/validation/process/LinkedEventNumberTable.java create mode 100644 event-store-management/event-store-management-core/src/test/java/uk/gov/justice/services/eventstore/management/validation/process/EventLinkageErrorMessageGeneratorTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 667de0e2f..6ae4d51fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ on [Keep a CHANGELOG](http://keepachangelog.com/). This project adheres to - Pre publish and publish timer beans now run in a separate thread. - New JNDI boolean values of 'pre.publish.disable' and 'publish.disable' to disable the running of PrePublisherTimerBean and PublisherTimerBean respectively +- Error message of event linking verification now gives more accurate error messages +based on whether the problem is in published_event or processed_event ## [2.2.1] - 2019-10-18 ### Fixed diff --git a/event-store-management/event-store-management-core/src/main/java/uk/gov/justice/services/eventstore/management/validation/process/EventLinkageChecker.java b/event-store-management/event-store-management-core/src/main/java/uk/gov/justice/services/eventstore/management/validation/process/EventLinkageChecker.java index a5f9906c0..3091d07fd 100644 --- a/event-store-management/event-store-management-core/src/main/java/uk/gov/justice/services/eventstore/management/validation/process/EventLinkageChecker.java +++ b/event-store-management/event-store-management-core/src/main/java/uk/gov/justice/services/eventstore/management/validation/process/EventLinkageChecker.java @@ -12,15 +12,19 @@ import java.util.ArrayList; import java.util.List; +import javax.inject.Inject; import javax.sql.DataSource; public class EventLinkageChecker { + @Inject + private EventLinkageErrorMessageGenerator eventLinkageErrorMessageGenerator; + public List verifyEventNumbersAreLinkedCorrectly( - final String tableName, + final LinkedEventNumberTable linkedEventNumberTable, final DataSource dataSource) { - final String query = format("SELECT event_number, previous_event_number FROM %s ORDER BY event_number", tableName); + final String query = format("SELECT event_number, previous_event_number FROM %s ORDER BY event_number", linkedEventNumberTable.getTableName()); final List errors = new ArrayList<>(); @@ -36,13 +40,13 @@ public List verifyEventNumbersAreLinkedCorrectly( if (previousEventNumber != lastEventNumber) { - final String message = - "Events incorrectly linked in %s table. " + - "Event with event number %d " + - "is linked to previous event number %d " + - "whereas it should be %d"; + final String errorMessage = eventLinkageErrorMessageGenerator.generateErrorMessage( + previousEventNumber, + eventNumber, + lastEventNumber, + linkedEventNumberTable); - errors.add(error(format(message, tableName, eventNumber, previousEventNumber, lastEventNumber))); + errors.add(error(errorMessage)); } lastEventNumber = eventNumber; @@ -54,7 +58,7 @@ public List verifyEventNumbersAreLinkedCorrectly( final String message = format( "All %d events in the %s table are correctly linked", count, - tableName); + linkedEventNumberTable.getTableName()); return singletonList(success(message)); } @@ -62,7 +66,7 @@ public List verifyEventNumbersAreLinkedCorrectly( return errors; } catch (final SQLException e) { - throw new CatchupVerificationException(format("Failed to get event numbers from %s table", tableName), e); + throw new CatchupVerificationException(format("Failed to get event numbers from %s table", linkedEventNumberTable.getTableName()), e); } } } diff --git a/event-store-management/event-store-management-core/src/main/java/uk/gov/justice/services/eventstore/management/validation/process/EventLinkageErrorMessageGenerator.java b/event-store-management/event-store-management-core/src/main/java/uk/gov/justice/services/eventstore/management/validation/process/EventLinkageErrorMessageGenerator.java new file mode 100644 index 000000000..6d1d4c9f5 --- /dev/null +++ b/event-store-management/event-store-management-core/src/main/java/uk/gov/justice/services/eventstore/management/validation/process/EventLinkageErrorMessageGenerator.java @@ -0,0 +1,37 @@ +package uk.gov.justice.services.eventstore.management.validation.process; + +import static java.lang.String.format; +import static uk.gov.justice.services.eventstore.management.validation.process.LinkedEventNumberTable.PUBLISHED_EVENT; + +public class EventLinkageErrorMessageGenerator { + + public String generateErrorMessage( + final int previousEventNumber, + final int eventNumber, + final int lastEventNumber, + final LinkedEventNumberTable linkedEventNumberTable) { + + + final String message; + if (linkedEventNumberTable == PUBLISHED_EVENT) { + message = "Events incorrectly linked in %s table: " + + "Event with event number %d " + + "is linked to previous event number %d " + + "whereas it should be %d"; + + } else { + message = "Events missing from %s table: " + + "Event with event_number %d " + + "has a previous_event_number of %d, " + + "but the event in the previous row in the database " + + "has an event_number of %d"; + } + + return format( + message, + linkedEventNumberTable.getTableName(), + eventNumber, + previousEventNumber, + lastEventNumber); + } +} diff --git a/event-store-management/event-store-management-core/src/main/java/uk/gov/justice/services/eventstore/management/validation/process/LinkedEventNumberTable.java b/event-store-management/event-store-management-core/src/main/java/uk/gov/justice/services/eventstore/management/validation/process/LinkedEventNumberTable.java new file mode 100644 index 000000000..d2715ab14 --- /dev/null +++ b/event-store-management/event-store-management-core/src/main/java/uk/gov/justice/services/eventstore/management/validation/process/LinkedEventNumberTable.java @@ -0,0 +1,17 @@ +package uk.gov.justice.services.eventstore.management.validation.process; + +public enum LinkedEventNumberTable { + + PUBLISHED_EVENT("published_event"), + PROCESSED_EVENT("processed_event"); + + private final String tableName; + + LinkedEventNumberTable(final String tableName) { + this.tableName = tableName; + } + + public String getTableName() { + return tableName; + } +} diff --git a/event-store-management/event-store-management-core/src/main/java/uk/gov/justice/services/eventstore/management/validation/process/verifiers/ProcessedEventLinkVerifier.java b/event-store-management/event-store-management-core/src/main/java/uk/gov/justice/services/eventstore/management/validation/process/verifiers/ProcessedEventLinkVerifier.java index e02034549..6a28cd615 100644 --- a/event-store-management/event-store-management-core/src/main/java/uk/gov/justice/services/eventstore/management/validation/process/verifiers/ProcessedEventLinkVerifier.java +++ b/event-store-management/event-store-management-core/src/main/java/uk/gov/justice/services/eventstore/management/validation/process/verifiers/ProcessedEventLinkVerifier.java @@ -1,5 +1,7 @@ package uk.gov.justice.services.eventstore.management.validation.process.verifiers; +import static uk.gov.justice.services.eventstore.management.validation.process.LinkedEventNumberTable.PROCESSED_EVENT; + import uk.gov.justice.services.eventstore.management.validation.process.EventLinkageChecker; import uk.gov.justice.services.eventstore.management.validation.process.VerificationResult; import uk.gov.justice.services.eventstore.management.validation.process.Verifier; @@ -28,7 +30,7 @@ public List verify() { logger.info("Verifying all previous_event_numbers in processed_event point to an existing event..."); return eventLinkageChecker.verifyEventNumbersAreLinkedCorrectly( - "processed_event", + PROCESSED_EVENT, viewStoreJdbcDataSourceProvider.getDataSource()); } } diff --git a/event-store-management/event-store-management-core/src/main/java/uk/gov/justice/services/eventstore/management/validation/process/verifiers/PublishedEventLinkVerifier.java b/event-store-management/event-store-management-core/src/main/java/uk/gov/justice/services/eventstore/management/validation/process/verifiers/PublishedEventLinkVerifier.java index be8dccfb8..8fd7b7482 100644 --- a/event-store-management/event-store-management-core/src/main/java/uk/gov/justice/services/eventstore/management/validation/process/verifiers/PublishedEventLinkVerifier.java +++ b/event-store-management/event-store-management-core/src/main/java/uk/gov/justice/services/eventstore/management/validation/process/verifiers/PublishedEventLinkVerifier.java @@ -1,5 +1,7 @@ package uk.gov.justice.services.eventstore.management.validation.process.verifiers; +import static uk.gov.justice.services.eventstore.management.validation.process.LinkedEventNumberTable.PUBLISHED_EVENT; + import uk.gov.justice.services.eventsourcing.source.core.EventStoreDataSourceProvider; import uk.gov.justice.services.eventstore.management.validation.process.EventLinkageChecker; import uk.gov.justice.services.eventstore.management.validation.process.VerificationResult; @@ -28,7 +30,7 @@ public List verify() { logger.info("Verifying all previous_event_numbers in processed_event point to an existing event..."); return eventLinkageChecker.verifyEventNumbersAreLinkedCorrectly( - "published_event", + PUBLISHED_EVENT, eventStoreDataSourceProvider.getDefaultDataSource()); } } diff --git a/event-store-management/event-store-management-core/src/test/java/uk/gov/justice/services/eventstore/management/validation/process/EventLinkageCheckerTest.java b/event-store-management/event-store-management-core/src/test/java/uk/gov/justice/services/eventstore/management/validation/process/EventLinkageCheckerTest.java index 18f74e407..341a3d8f3 100644 --- a/event-store-management/event-store-management-core/src/test/java/uk/gov/justice/services/eventstore/management/validation/process/EventLinkageCheckerTest.java +++ b/event-store-management/event-store-management-core/src/test/java/uk/gov/justice/services/eventstore/management/validation/process/EventLinkageCheckerTest.java @@ -5,6 +5,8 @@ import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import static uk.gov.justice.services.eventstore.management.validation.process.LinkedEventNumberTable.PROCESSED_EVENT; +import static uk.gov.justice.services.eventstore.management.validation.process.LinkedEventNumberTable.PUBLISHED_EVENT; import static uk.gov.justice.services.eventstore.management.validation.process.VerificationResult.VerificationResultType.ERROR; import static uk.gov.justice.services.eventstore.management.validation.process.VerificationResult.VerificationResultType.SUCCESS; @@ -19,20 +21,22 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; +import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class) public class EventLinkageCheckerTest { + @Mock + private EventLinkageErrorMessageGenerator eventLinkageErrorMessageGenerator; + @InjectMocks private EventLinkageChecker eventLinkageChecker; @Test public void shouldReturnSuccessIfAllEventsAreCorrectlyLinked() throws Exception { - final String tableName = "some_table"; - - final String sql = "SELECT event_number, previous_event_number FROM some_table ORDER BY event_number"; + final String sql = "SELECT event_number, previous_event_number FROM published_event ORDER BY event_number"; final DataSource dataSource = mock(DataSource.class); final Connection connection = mock(Connection.class); @@ -48,20 +52,20 @@ public void shouldReturnSuccessIfAllEventsAreCorrectlyLinked() throws Exception when(resultSet.getInt("event_number")).thenReturn(1, 2, 3); final List publishedEventsResults = eventLinkageChecker.verifyEventNumbersAreLinkedCorrectly( - tableName, + PUBLISHED_EVENT, dataSource); assertThat(publishedEventsResults.size(), is(1)); assertThat(publishedEventsResults.get(0).getVerificationResultType(), is(SUCCESS)); - assertThat(publishedEventsResults.get(0).getMessage(), is("All 3 events in the some_table table are correctly linked")); + assertThat(publishedEventsResults.get(0).getMessage(), is("All 3 events in the published_event table are correctly linked")); } @Test public void shouldReturnErrorIfAnyEventsAreIncorrectlyLinked() throws Exception { - final String tableName = "some_table"; + final String errorMessage = "error message"; - final String sql = "SELECT event_number, previous_event_number FROM some_table ORDER BY event_number"; + final String sql = "SELECT event_number, previous_event_number FROM published_event ORDER BY event_number"; final DataSource dataSource = mock(DataSource.class); final Connection connection = mock(Connection.class); @@ -76,21 +80,24 @@ public void shouldReturnErrorIfAnyEventsAreIncorrectlyLinked() throws Exception when(resultSet.getInt("previous_event_number")).thenReturn(0, 1, 3); when(resultSet.getInt("event_number")).thenReturn(1, 2, 4); + when(eventLinkageErrorMessageGenerator.generateErrorMessage(3, 4, 2, PUBLISHED_EVENT)).thenReturn(errorMessage); + final List publishedEventsResults = eventLinkageChecker.verifyEventNumbersAreLinkedCorrectly( - tableName, + PUBLISHED_EVENT, dataSource); assertThat(publishedEventsResults.size(), is(1)); assertThat(publishedEventsResults.get(0).getVerificationResultType(), is(ERROR)); - assertThat(publishedEventsResults.get(0).getMessage(), is("Events incorrectly linked in some_table table. Event with event number 4 is linked to previous event number 3 whereas it should be 2")); + assertThat(publishedEventsResults.get(0).getMessage(), is(errorMessage)); } @Test public void shouldReturnAllErrors() throws Exception { - final String tableName = "some_table"; + final String errorMessage_1 = "error message 1"; + final String errorMessage_2 = "error message 2"; - final String sql = "SELECT event_number, previous_event_number FROM some_table ORDER BY event_number"; + final String sql = "SELECT event_number, previous_event_number FROM processed_event ORDER BY event_number"; final DataSource dataSource = mock(DataSource.class); final Connection connection = mock(Connection.class); @@ -105,24 +112,26 @@ public void shouldReturnAllErrors() throws Exception { when(resultSet.getInt("previous_event_number")).thenReturn(0, 2, 4); when(resultSet.getInt("event_number")).thenReturn(1, 3, 5); + when(eventLinkageErrorMessageGenerator.generateErrorMessage(2, 3, 1, PROCESSED_EVENT)).thenReturn(errorMessage_1); + when(eventLinkageErrorMessageGenerator.generateErrorMessage(4, 5, 3, PROCESSED_EVENT)).thenReturn(errorMessage_2); + final List publishedEventsResults = eventLinkageChecker.verifyEventNumbersAreLinkedCorrectly( - tableName, + PROCESSED_EVENT, dataSource); assertThat(publishedEventsResults.size(), is(2)); assertThat(publishedEventsResults.get(0).getVerificationResultType(), is(ERROR)); - assertThat(publishedEventsResults.get(0).getMessage(), is("Events incorrectly linked in some_table table. Event with event number 3 is linked to previous event number 2 whereas it should be 1")); + assertThat(publishedEventsResults.get(0).getMessage(), is(errorMessage_1)); assertThat(publishedEventsResults.get(1).getVerificationResultType(), is(ERROR)); - assertThat(publishedEventsResults.get(1).getMessage(), is("Events incorrectly linked in some_table table. Event with event number 5 is linked to previous event number 4 whereas it should be 3")); + assertThat(publishedEventsResults.get(1).getMessage(), is(errorMessage_2)); } @Test public void shouldThrowExceptionIfDataAccessFails() throws Exception { final SQLException sqlException = new SQLException("Ooops"); - final String tableName = "some_table"; - final String sql = "SELECT event_number, previous_event_number FROM some_table ORDER BY event_number"; + final String sql = "SELECT event_number, previous_event_number FROM published_event ORDER BY event_number"; final DataSource dataSource = mock(DataSource.class); final Connection connection = mock(Connection.class); @@ -136,12 +145,12 @@ public void shouldThrowExceptionIfDataAccessFails() throws Exception { try { eventLinkageChecker.verifyEventNumbersAreLinkedCorrectly( - tableName, + PUBLISHED_EVENT, dataSource); fail(); } catch (final CatchupVerificationException expected) { assertThat(expected.getCause(), is(sqlException)); - assertThat(expected.getMessage(), is("Failed to get event numbers from some_table table")); + assertThat(expected.getMessage(), is("Failed to get event numbers from published_event table")); } } } diff --git a/event-store-management/event-store-management-core/src/test/java/uk/gov/justice/services/eventstore/management/validation/process/EventLinkageErrorMessageGeneratorTest.java b/event-store-management/event-store-management-core/src/test/java/uk/gov/justice/services/eventstore/management/validation/process/EventLinkageErrorMessageGeneratorTest.java new file mode 100644 index 000000000..efe21f102 --- /dev/null +++ b/event-store-management/event-store-management-core/src/test/java/uk/gov/justice/services/eventstore/management/validation/process/EventLinkageErrorMessageGeneratorTest.java @@ -0,0 +1,54 @@ +package uk.gov.justice.services.eventstore.management.validation.process; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static uk.gov.justice.services.eventstore.management.validation.process.LinkedEventNumberTable.PROCESSED_EVENT; +import static uk.gov.justice.services.eventstore.management.validation.process.LinkedEventNumberTable.PUBLISHED_EVENT; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.runners.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class EventLinkageErrorMessageGeneratorTest { + + @InjectMocks + private EventLinkageErrorMessageGenerator eventLinkageErrorMessageGenerator; + + @Test + public void shouldGenerateTheCorrectErrorMessageForPublishedEvent() throws Exception { + + final int previousEventNumber = 23; + final int currentEventNumber = 24; + final int lastEvenNumber = 13; + + final String errorMessage = eventLinkageErrorMessageGenerator.generateErrorMessage( + previousEventNumber, + currentEventNumber, + lastEvenNumber, + PUBLISHED_EVENT); + + assertThat(errorMessage, is("Events incorrectly linked in published_event table: " + + "Event with event number 24 is linked to previous event number 23 " + + "whereas it should be 13")); + } + + @Test + public void shouldGenerateTheCorrectErrorMessageForProcessedEvent() throws Exception { + + final int previousEventNumber = 41; + final int currentEventNumber = 42; + final int lastEvenNumber = 23; + + final String errorMessage = eventLinkageErrorMessageGenerator.generateErrorMessage( + previousEventNumber, + currentEventNumber, + lastEvenNumber, + PROCESSED_EVENT); + + assertThat(errorMessage, is("Events missing from processed_event table: " + + "Event with event_number 42 has a previous_event_number of 41, " + + "but the event in the previous row in the database has an event_number of 23")); + } +} diff --git a/event-store-management/event-store-management-core/src/test/java/uk/gov/justice/services/eventstore/management/validation/process/verifiers/ProcessedEventLinkVerifierTest.java b/event-store-management/event-store-management-core/src/test/java/uk/gov/justice/services/eventstore/management/validation/process/verifiers/ProcessedEventLinkVerifierTest.java index f4ff38912..5b84d2bb8 100644 --- a/event-store-management/event-store-management-core/src/test/java/uk/gov/justice/services/eventstore/management/validation/process/verifiers/ProcessedEventLinkVerifierTest.java +++ b/event-store-management/event-store-management-core/src/test/java/uk/gov/justice/services/eventstore/management/validation/process/verifiers/ProcessedEventLinkVerifierTest.java @@ -5,6 +5,7 @@ import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import static uk.gov.justice.services.eventstore.management.validation.process.LinkedEventNumberTable.PROCESSED_EVENT; import uk.gov.justice.services.eventstore.management.validation.process.EventLinkageChecker; import uk.gov.justice.services.eventstore.management.validation.process.VerificationResult; @@ -44,7 +45,7 @@ public void shouldCheckTheLinkingOfEventNumbersInProcessedEvent() throws Excepti when(viewStoreJdbcDataSourceProvider.getDataSource()).thenReturn(viewStoreDataSource); - when(eventLinkageChecker.verifyEventNumbersAreLinkedCorrectly("processed_event", viewStoreDataSource)).thenReturn(results); + when(eventLinkageChecker.verifyEventNumbersAreLinkedCorrectly(PROCESSED_EVENT, viewStoreDataSource)).thenReturn(results); assertThat(processedEventLinkVerifier.verify(), is(results)); } diff --git a/event-store-management/event-store-management-core/src/test/java/uk/gov/justice/services/eventstore/management/validation/process/verifiers/PublishedEventLinkVerifierTest.java b/event-store-management/event-store-management-core/src/test/java/uk/gov/justice/services/eventstore/management/validation/process/verifiers/PublishedEventLinkVerifierTest.java index 848f097df..3fd537040 100644 --- a/event-store-management/event-store-management-core/src/test/java/uk/gov/justice/services/eventstore/management/validation/process/verifiers/PublishedEventLinkVerifierTest.java +++ b/event-store-management/event-store-management-core/src/test/java/uk/gov/justice/services/eventstore/management/validation/process/verifiers/PublishedEventLinkVerifierTest.java @@ -5,6 +5,7 @@ import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import static uk.gov.justice.services.eventstore.management.validation.process.LinkedEventNumberTable.PUBLISHED_EVENT; import uk.gov.justice.services.eventsourcing.source.core.EventStoreDataSourceProvider; import uk.gov.justice.services.eventstore.management.validation.process.EventLinkageChecker; @@ -45,7 +46,7 @@ public void shouldCheckTheLinkingOfEventNumbersInPublishedEvent() throws Excepti when(eventStoreDataSourceProvider.getDefaultDataSource()).thenReturn(eventStoreDataSource); - when(eventLinkageChecker.verifyEventNumbersAreLinkedCorrectly("published_event", eventStoreDataSource)).thenReturn(results); + when(eventLinkageChecker.verifyEventNumbersAreLinkedCorrectly(PUBLISHED_EVENT, eventStoreDataSource)).thenReturn(results); assertThat(publishedEventLinkVerifier.verify(), is(results)); }