Skip to content

Commit dc11486

Browse files
committed
GH-806 - MongoDB archive mode now uses aggregation to mark event publications completed.
1 parent a7e4a79 commit dc11486

File tree

3 files changed

+60
-15
lines changed

3 files changed

+60
-15
lines changed

spring-modulith-events/spring-modulith-events-mongodb/src/main/java/org/springframework/modulith/events/mongodb/MongoDbEventPublicationRepository.java

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.springframework.modulith.events.mongodb;
1717

18+
import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
1819
import static org.springframework.data.mongodb.core.query.Criteria.*;
1920
import static org.springframework.data.mongodb.core.query.Query.*;
2021

@@ -24,8 +25,12 @@
2425
import java.util.Optional;
2526
import java.util.UUID;
2627

28+
import org.bson.Document;
29+
import org.springframework.data.annotation.Id;
2730
import org.springframework.data.domain.Sort;
2831
import org.springframework.data.mongodb.core.MongoTemplate;
32+
import org.springframework.data.mongodb.core.aggregation.Fields;
33+
import org.springframework.data.mongodb.core.aggregation.MergeOperation.WhenDocumentsMatch;
2934
import org.springframework.data.mongodb.core.query.Criteria;
3035
import org.springframework.data.mongodb.core.query.Query;
3136
import org.springframework.data.mongodb.core.query.Update;
@@ -96,7 +101,8 @@ public TargetEventPublication create(TargetEventPublication publication) {
96101
@Override
97102
public void markCompleted(Object event, PublicationTargetIdentifier identifier, Instant completionDate) {
98103

99-
var query = byEventAndListenerId(event, identifier);
104+
var criteria = byEventAndListenerId(event, identifier);
105+
var query = defaultQuery(criteria);
100106
var update = Update.update(COMPLETION_DATE, completionDate);
101107

102108
if (completionMode == CompletionMode.DELETE) {
@@ -105,9 +111,8 @@ public void markCompleted(Object event, PublicationTargetIdentifier identifier,
105111

106112
} else if (completionMode == CompletionMode.ARCHIVE) {
107113

108-
mongoTemplate.findAndModify(query, update, MongoDbEventPublication.class, collection);
109-
var completedEvent = mongoTemplate.findAndRemove(query, MongoDbEventPublication.class, collection);
110-
mongoTemplate.save(completedEvent, archiveCollection);
114+
markCompleted(criteria, completionDate);
115+
111116
} else {
112117

113118
mongoTemplate.findAndModify(query, update, MongoDbEventPublication.class, collection);
@@ -121,21 +126,20 @@ public void markCompleted(Object event, PublicationTargetIdentifier identifier,
121126
@Override
122127
public void markCompleted(UUID identifier, Instant completionDate) {
123128

124-
var criteria = query(where(ID).is(identifier));
129+
var criteria = where(ID).is(identifier).and(COMPLETION_DATE).isNull();
130+
var query = query(criteria);
125131
var update = Update.update(COMPLETION_DATE, completionDate);
126132

127133
if (completionMode == CompletionMode.DELETE) {
128134

129-
mongoTemplate.remove(criteria, MongoDbEventPublication.class, collection);
135+
mongoTemplate.remove(query, MongoDbEventPublication.class, collection);
130136

131137
} else if (completionMode == CompletionMode.ARCHIVE) {
132138

133-
mongoTemplate.findAndModify(criteria, update, MongoDbEventPublication.class, collection);
134-
var completedEvent = mongoTemplate.findAndRemove(criteria, MongoDbEventPublication.class, collection);
135-
mongoTemplate.save(completedEvent, archiveCollection);
139+
markCompleted(criteria, completionDate);
136140

137141
} else {
138-
mongoTemplate.findAndModify(criteria, update, MongoDbEventPublication.class, collection);
142+
mongoTemplate.findAndModify(query, update, MongoDbEventPublication.class, collection);
139143
}
140144
}
141145

@@ -168,7 +172,7 @@ public List<TargetEventPublication> findIncompletePublicationsPublishedBefore(In
168172
public Optional<TargetEventPublication> findIncompletePublicationsByEventAndTargetIdentifier(
169173
Object event, PublicationTargetIdentifier targetIdentifier) {
170174

171-
var results = readMapped(byEventAndListenerId(event, targetIdentifier));
175+
var results = readMapped(defaultQuery(byEventAndListenerId(event, targetIdentifier)));
172176

173177
// if there are several events with exactly the same payload we return the oldest one first
174178
return results.isEmpty() ? Optional.empty() : Optional.of(results.get(0));
@@ -230,13 +234,13 @@ private List<TargetEventPublication> readMapped(Query query, String collection)
230234

231235
}
232236

233-
private Query byEventAndListenerId(Object event, PublicationTargetIdentifier identifier) {
237+
private Criteria byEventAndListenerId(Object event, PublicationTargetIdentifier identifier) {
234238

235239
var eventAsMongoType = mongoTemplate.getConverter().convertToMongoType(event, TypeInformation.OBJECT);
236240

237-
return defaultQuery(where(EVENT).is(eventAsMongoType) //
241+
return where(EVENT).is(eventAsMongoType) //
238242
.and(LISTENER_ID).is(identifier.getValue())
239-
.and(COMPLETION_DATE).isNull());
243+
.and(COMPLETION_DATE).isNull();
240244
}
241245

242246
private static MongoDbEventPublication domainToDocument(TargetEventPublication publication) {
@@ -256,6 +260,28 @@ private static Query defaultQuery(Criteria criteria) {
256260
return query(criteria).with(DEFAULT_SORT);
257261
}
258262

263+
private void markCompleted(Criteria lookup, Instant now) {
264+
265+
var aggregation = newAggregation(MongoDbEventPublication.class,
266+
267+
match(lookup),
268+
269+
addFields()
270+
.addFieldWithValue(COMPLETION_DATE, now)
271+
.build(),
272+
273+
merge()
274+
.intoCollection(archiveCollection)
275+
.on(ID)
276+
.whenMatched(WhenDocumentsMatch.keepExistingDocument())
277+
.build());
278+
279+
mongoTemplate
280+
.aggregate(aggregation, collection, Document.class)
281+
.forEach(it -> mongoTemplate.remove(query(where(Fields.UNDERSCORE_ID).is(it.get(Fields.UNDERSCORE_ID))),
282+
collection));
283+
}
284+
259285
private static class MongoDbEventPublicationAdapter implements TargetEventPublication {
260286

261287
private final MongoDbEventPublication publication;
@@ -326,4 +352,6 @@ public int hashCode() {
326352
return Objects.hash(publication);
327353
}
328354
}
355+
356+
record IdOnly(@Id UUID id) {}
329357
}

spring-modulith-examples/spring-modulith-example-epr-mongodb/src/main/java/example/Application.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
*/
1616
package example;
1717

18+
import example.order.OrderManagement;
19+
20+
import org.springframework.boot.SpringApplication;
1821
import org.springframework.boot.autoconfigure.SpringBootApplication;
1922

2023
/**
@@ -25,5 +28,10 @@
2528
@SpringBootApplication
2629
public class Application {
2730

28-
public static void main(String... args) {}
31+
public static void main(String... args) {
32+
33+
var context = SpringApplication.run(Application.class, args);
34+
35+
context.getBean(OrderManagement.class).complete();
36+
}
2937
}

spring-modulith-examples/spring-modulith-example-epr-mongodb/src/test/java/example/ApplicationIntegrationTests.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.bson.UuidRepresentation;
2424
import org.junit.jupiter.api.Test;
2525
import org.springframework.beans.factory.annotation.Autowired;
26+
import org.springframework.boot.SpringApplication;
2627
import org.springframework.boot.test.context.SpringBootTest;
2728
import org.springframework.boot.test.context.TestConfiguration;
2829
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
@@ -48,6 +49,14 @@
4849
@Testcontainers(disabledWithoutDocker = true)
4950
class ApplicationIntegrationTests {
5051

52+
public static void main(String[] args) {
53+
54+
SpringApplication.from(Application::main)
55+
.with(MongoDbInfrastructureConfiguration.class)
56+
.run(args)
57+
.getApplicationContext();
58+
}
59+
5160
@TestConfiguration
5261
static class MongoDbInfrastructureConfiguration {
5362

0 commit comments

Comments
 (0)