diff --git a/spring-modulith-events/spring-modulith-events-jdbc/src/main/java/org/springframework/modulith/events/jdbc/JdbcEventPublicationRepository.java b/spring-modulith-events/spring-modulith-events-jdbc/src/main/java/org/springframework/modulith/events/jdbc/JdbcEventPublicationRepository.java index 67c634c0..45c2b73a 100644 --- a/spring-modulith-events/spring-modulith-events-jdbc/src/main/java/org/springframework/modulith/events/jdbc/JdbcEventPublicationRepository.java +++ b/spring-modulith-events/spring-modulith-events-jdbc/src/main/java/org/springframework/modulith/events/jdbc/JdbcEventPublicationRepository.java @@ -59,6 +59,7 @@ class JdbcEventPublicationRepository implements EventPublicationRepository { SELECT ID, COMPLETION_DATE, EVENT_TYPE, LISTENER_ID, PUBLICATION_DATE, SERIALIZED_EVENT FROM EVENT_PUBLICATION WHERE COMPLETION_DATE IS NULL + ORDER BY PUBLICATION_DATE ASC """; private static final String SQL_STATEMENT_UPDATE = """ diff --git a/spring-modulith-events/spring-modulith-events-jdbc/src/test/java/org/springframework/modulith/events/jdbc/JdbcEventPublicationRepositoryIntegrationTests.java b/spring-modulith-events/spring-modulith-events-jdbc/src/test/java/org/springframework/modulith/events/jdbc/JdbcEventPublicationRepositoryIntegrationTests.java index 95fe4042..790e1f31 100644 --- a/spring-modulith-events/spring-modulith-events-jdbc/src/test/java/org/springframework/modulith/events/jdbc/JdbcEventPublicationRepositoryIntegrationTests.java +++ b/spring-modulith-events/spring-modulith-events-jdbc/src/test/java/org/springframework/modulith/events/jdbc/JdbcEventPublicationRepositoryIntegrationTests.java @@ -16,11 +16,15 @@ package org.springframework.modulith.events.jdbc; import static org.assertj.core.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import lombok.Value; +import java.time.LocalDateTime; +import java.time.ZoneOffset; import java.time.temporal.ChronoUnit; +import java.util.Comparator; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; @@ -97,6 +101,31 @@ class JdbcEventPublicationRepositoryIntegrationTests { assertThat(repository.findIncompletePublications()).isEmpty(); } + @Test // GH-133 + void returnsOldestIncompletePublicationsFirst() { + + when(serializer.serialize(any())).thenReturn("{}"); + + var now = LocalDateTime.now(); + + createPublicationAt(now.withHour(3)); + createPublicationAt(now.withHour(0)); + createPublicationAt(now.withHour(1)); + + assertThat(repository.findIncompletePublications()) + .isSortedAccordingTo(Comparator.comparing(EventPublication::getPublicationDate)); + } + + private void createPublicationAt(LocalDateTime publicationDate) { + + EventPublication publication = mock(EventPublication.class); + when(publication.getEvent()).thenReturn(""); + when(publication.getTargetIdentifier()).thenReturn(TARGET_IDENTIFIER); + when(publication.getPublicationDate()).thenReturn(publicationDate.toInstant(ZoneOffset.UTC)); + + repository.create(publication); + } + @Nested class Update { @@ -240,10 +269,12 @@ class JdbcEventPublicationRepositoryIntegrationTests { @Nested @ActiveProfiles("hsqldb") + @Testcontainers(disabledWithoutDocker = false) class HSQL extends TestBase {} @Nested @ActiveProfiles("h2") + @Testcontainers(disabledWithoutDocker = false) class H2 extends TestBase {} @Nested diff --git a/spring-modulith-events/spring-modulith-events-jpa/src/main/java/org/springframework/modulith/events/jpa/JpaEventPublicationRepository.java b/spring-modulith-events/spring-modulith-events-jpa/src/main/java/org/springframework/modulith/events/jpa/JpaEventPublicationRepository.java index cfbb9dc6..ab6afc85 100644 --- a/spring-modulith-events/spring-modulith-events-jpa/src/main/java/org/springframework/modulith/events/jpa/JpaEventPublicationRepository.java +++ b/spring-modulith-events/spring-modulith-events-jpa/src/main/java/org/springframework/modulith/events/jpa/JpaEventPublicationRepository.java @@ -53,6 +53,8 @@ class JpaEventPublicationRepository implements EventPublicationRepository { from JpaEventPublication p where p.completionDate is null + order by + p.publicationDate asc """; private static final String DELETE_COMPLETED = """ diff --git a/spring-modulith-events/spring-modulith-events-jpa/src/test/java/org/springframework/modulith/events/jpa/JpaEventPublicationRepositoryIntegrationTests.java b/spring-modulith-events/spring-modulith-events-jpa/src/test/java/org/springframework/modulith/events/jpa/JpaEventPublicationRepositoryIntegrationTests.java index 5ce070d8..ee75b08b 100644 --- a/spring-modulith-events/spring-modulith-events-jpa/src/test/java/org/springframework/modulith/events/jpa/JpaEventPublicationRepositoryIntegrationTests.java +++ b/spring-modulith-events/spring-modulith-events-jpa/src/test/java/org/springframework/modulith/events/jpa/JpaEventPublicationRepositoryIntegrationTests.java @@ -23,6 +23,9 @@ import jakarta.persistence.EntityManagerFactory; import lombok.RequiredArgsConstructor; import lombok.Value; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.util.Comparator; import java.util.List; import javax.sql.DataSource; @@ -196,6 +199,23 @@ class JpaEventPublicationRepositoryIntegrationTests { .element(0).extracting(it -> it.serializedEvent).isEqualTo(serializedEvent2); } + @Test // GH-133 + void returnsOldestIncompletePublicationsFirst() { + + var now = LocalDateTime.now(); + + savePublicationAt(now.withHour(3)); + savePublicationAt(now.withHour(0)); + savePublicationAt(now.withHour(1)); + + assertThat(repository.findIncompletePublications()) + .isSortedAccordingTo(Comparator.comparing(EventPublication::getPublicationDate)); + } + + private void savePublicationAt(LocalDateTime date) { + em.persist(new JpaEventPublication(date.toInstant(ZoneOffset.UTC), "", "", Object.class)); + } + @Value private static final class TestEvent { String eventId; diff --git a/spring-modulith-events/spring-modulith-events-mongodb/src/main/java/org/springframework/modulith/events/mongodb/MongoDbEventPublicationRepository.java b/spring-modulith-events/spring-modulith-events-mongodb/src/main/java/org/springframework/modulith/events/mongodb/MongoDbEventPublicationRepository.java index 9fa869ce..bdf90655 100644 --- a/spring-modulith-events/spring-modulith-events-mongodb/src/main/java/org/springframework/modulith/events/mongodb/MongoDbEventPublicationRepository.java +++ b/spring-modulith-events/spring-modulith-events-mongodb/src/main/java/org/springframework/modulith/events/mongodb/MongoDbEventPublicationRepository.java @@ -79,7 +79,8 @@ class MongoDbEventPublicationRepository implements EventPublicationRepository { @Override public List findIncompletePublications() { - var query = query(where("completionDate").isNull()); + var query = query(where("completionDate").isNull()) + .with(Sort.by("publicationDate").ascending()); return mongoTemplate.find(query, MongoDbEventPublication.class).stream() // . map(this::documentToDomain) // diff --git a/spring-modulith-events/spring-modulith-events-mongodb/src/test/java/org/springframework/modulith/events/mongodb/MongoDbEventPublicationRepositoryTest.java b/spring-modulith-events/spring-modulith-events-mongodb/src/test/java/org/springframework/modulith/events/mongodb/MongoDbEventPublicationRepositoryTest.java index cc521fae..05945337 100644 --- a/spring-modulith-events/spring-modulith-events-mongodb/src/test/java/org/springframework/modulith/events/mongodb/MongoDbEventPublicationRepositoryTest.java +++ b/spring-modulith-events/spring-modulith-events-mongodb/src/test/java/org/springframework/modulith/events/mongodb/MongoDbEventPublicationRepositoryTest.java @@ -19,8 +19,12 @@ import static org.assertj.core.api.Assertions.*; import lombok.Value; +import java.time.LocalDateTime; +import java.time.ZoneOffset; import java.time.temporal.ChronoUnit; +import java.util.Comparator; +import org.bson.types.ObjectId; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; @@ -100,6 +104,25 @@ class MongoDbEventPublicationRepositoryTest { .element(0).extracting(EventPublication::getEvent).isEqualTo(testEvent1); } + @Test // GH-133 + void returnsOldestIncompletePublicationsFirst() { + + var now = LocalDateTime.now(); + + savePublicationAt(now.withHour(3)); + savePublicationAt(now.withHour(0)); + savePublicationAt(now.withHour(1)); + + assertThat(repository.findIncompletePublications()) + .isSortedAccordingTo(Comparator.comparing(EventPublication::getPublicationDate)); + } + + private void savePublicationAt(LocalDateTime date) { + + mongoTemplate.save( + new MongoDbEventPublication(new ObjectId(), date.toInstant(ZoneOffset.UTC), "", "", null)); + } + @Nested class FindByEventAndTargetIdentifier {