1515 */
1616package org .springframework .modulith .events .mongodb ;
1717
18+ import static org .springframework .data .mongodb .core .aggregation .Aggregation .*;
1819import static org .springframework .data .mongodb .core .query .Criteria .*;
1920import static org .springframework .data .mongodb .core .query .Query .*;
2021
2425import java .util .Optional ;
2526import java .util .UUID ;
2627
28+ import org .bson .Document ;
29+ import org .springframework .data .annotation .Id ;
2730import org .springframework .data .domain .Sort ;
2831import 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 ;
2934import org .springframework .data .mongodb .core .query .Criteria ;
3035import org .springframework .data .mongodb .core .query .Query ;
3136import 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}
0 commit comments