15
15
*/
16
16
package org .springframework .modulith .events .neo4j ;
17
17
18
+ import static org .neo4j .cypherdsl .core .Cypher .*;
19
+
18
20
import java .time .Instant ;
19
21
import java .time .ZoneOffset ;
20
22
import java .util .ArrayList ;
23
25
import java .util .Objects ;
24
26
import java .util .Optional ;
25
27
import java .util .UUID ;
28
+ import java .util .function .Function ;
26
29
27
30
import org .neo4j .cypherdsl .core .Cypher ;
28
31
import org .neo4j .cypherdsl .core .Node ;
48
51
*
49
52
* @author Gerrit Meier
50
53
* @author Oliver Drotbohm
54
+ * @author Cora Iberkleid
51
55
* @since 1.1
52
56
*/
53
57
@ Transactional
@@ -61,85 +65,115 @@ class Neo4jEventPublicationRepository implements EventPublicationRepository {
61
65
private static final String PUBLICATION_DATE = "publicationDate" ;
62
66
private static final String COMPLETION_DATE = "completionDate" ;
63
67
64
- private static final Node EVENT_PUBLICATION_NODE = Cypher . node ("Neo4jEventPublication" )
68
+ private static final Node EVENT_PUBLICATION_NODE = node ("Neo4jEventPublication" )
65
69
.named ("neo4jEventPublication" );
66
70
67
- private static final Statement INCOMPLETE_BY_EVENT_AND_TARGET_IDENTIFIER_STATEMENT = Cypher
68
- .match (EVENT_PUBLICATION_NODE )
69
- .where (EVENT_PUBLICATION_NODE .property (EVENT_HASH ).eq (Cypher .parameter (EVENT_HASH )))
70
- .and (EVENT_PUBLICATION_NODE .property (LISTENER_ID ).eq (Cypher .parameter (LISTENER_ID )))
71
+ private static final Node EVENT_PUBLICATION_COMPLETED_NODE = node ("Neo4jEventPublicationCompleted" )
72
+ .named ("neo4jEventPublicationCompleted" );
73
+
74
+ private static final Statement INCOMPLETE_BY_EVENT_AND_TARGET_IDENTIFIER_STATEMENT = match (EVENT_PUBLICATION_NODE )
75
+ .where (EVENT_PUBLICATION_NODE .property (EVENT_HASH ).eq (parameter (EVENT_HASH )))
76
+ .and (EVENT_PUBLICATION_NODE .property (LISTENER_ID ).eq (parameter (LISTENER_ID )))
71
77
.and (EVENT_PUBLICATION_NODE .property (COMPLETION_DATE ).isNull ())
72
78
.returning (EVENT_PUBLICATION_NODE )
73
79
.build ();
74
80
75
- private static final Statement DELETE_BY_EVENT_AND_LISTENER_ID = Cypher . match (EVENT_PUBLICATION_NODE )
76
- .where (EVENT_PUBLICATION_NODE .property (EVENT_HASH ).eq (Cypher . parameter (EVENT_HASH )))
77
- .and (EVENT_PUBLICATION_NODE .property (LISTENER_ID ).eq (Cypher . parameter (LISTENER_ID )))
81
+ private static final Statement DELETE_BY_EVENT_AND_LISTENER_ID = match (EVENT_PUBLICATION_NODE )
82
+ .where (EVENT_PUBLICATION_NODE .property (EVENT_HASH ).eq (parameter (EVENT_HASH )))
83
+ .and (EVENT_PUBLICATION_NODE .property (LISTENER_ID ).eq (parameter (LISTENER_ID )))
78
84
.delete (EVENT_PUBLICATION_NODE )
79
85
.build ();
80
86
81
- private static final Statement DELETE_BY_ID_STATEMENT = Cypher . match (EVENT_PUBLICATION_NODE )
82
- .where (EVENT_PUBLICATION_NODE .property (ID ).in (Cypher . parameter (ID )))
87
+ private static final Statement DELETE_BY_ID_STATEMENT = match (EVENT_PUBLICATION_NODE )
88
+ .where (EVENT_PUBLICATION_NODE .property (ID ).in (parameter (ID )))
83
89
.delete (EVENT_PUBLICATION_NODE )
84
90
.build ();
85
91
86
- private static final Statement DELETE_COMPLETED_STATEMENT = Cypher . match (EVENT_PUBLICATION_NODE )
87
- .where (EVENT_PUBLICATION_NODE .property (COMPLETION_DATE ).isNotNull ())
88
- .delete (EVENT_PUBLICATION_NODE )
92
+ private static final Function < Node , Statement > DELETE_COMPLETED_STATEMENT = node -> match (node )
93
+ .where (node .property (COMPLETION_DATE ).isNotNull ())
94
+ .delete (node )
89
95
.build ();
90
96
91
- private static final Statement DELETE_COMPLETED_BEFORE_STATEMENT = Cypher . match (EVENT_PUBLICATION_NODE )
92
- .where (EVENT_PUBLICATION_NODE .property (PUBLICATION_DATE ).lt (Cypher . parameter (PUBLICATION_DATE )))
93
- .and (EVENT_PUBLICATION_NODE .property (COMPLETION_DATE ).isNotNull ())
94
- .delete (EVENT_PUBLICATION_NODE )
97
+ private static final Function < Node , Statement > DELETE_COMPLETED_BEFORE_STATEMENT = node -> match (node )
98
+ .where (node .property (PUBLICATION_DATE ).lt (parameter (PUBLICATION_DATE )))
99
+ .and (node .property (COMPLETION_DATE ).isNotNull ())
100
+ .delete (node )
95
101
.build ();
96
102
97
- private static final Statement INCOMPLETE_PUBLISHED_BEFORE_STATEMENT = Cypher
98
- .match (EVENT_PUBLICATION_NODE )
99
- .where (EVENT_PUBLICATION_NODE .property (PUBLICATION_DATE ).lt (Cypher .parameter (PUBLICATION_DATE )))
103
+ private static final Statement INCOMPLETE_PUBLISHED_BEFORE_STATEMENT = match (EVENT_PUBLICATION_NODE )
104
+ .where (EVENT_PUBLICATION_NODE .property (PUBLICATION_DATE ).lt (parameter (PUBLICATION_DATE )))
100
105
.and (EVENT_PUBLICATION_NODE .property (COMPLETION_DATE ).isNull ())
101
106
.returning (EVENT_PUBLICATION_NODE )
102
107
.orderBy (EVENT_PUBLICATION_NODE .property (PUBLICATION_DATE ))
103
108
.build ();
104
109
105
110
private static final Statement CREATE_STATEMENT = Cypher .create (EVENT_PUBLICATION_NODE )
106
- .set (EVENT_PUBLICATION_NODE .property (ID ).to (Cypher . parameter (ID )))
107
- .set (EVENT_PUBLICATION_NODE .property (EVENT_SERIALIZED ).to (Cypher . parameter (EVENT_SERIALIZED )))
108
- .set (EVENT_PUBLICATION_NODE .property (EVENT_HASH ).to (Cypher . parameter (EVENT_HASH )))
109
- .set (EVENT_PUBLICATION_NODE .property (EVENT_TYPE ).to (Cypher . parameter (EVENT_TYPE )))
110
- .set (EVENT_PUBLICATION_NODE .property (LISTENER_ID ).to (Cypher . parameter (LISTENER_ID )))
111
- .set (EVENT_PUBLICATION_NODE .property (PUBLICATION_DATE ).to (Cypher . parameter (PUBLICATION_DATE )))
111
+ .set (EVENT_PUBLICATION_NODE .property (ID ).to (parameter (ID )))
112
+ .set (EVENT_PUBLICATION_NODE .property (EVENT_SERIALIZED ).to (parameter (EVENT_SERIALIZED )))
113
+ .set (EVENT_PUBLICATION_NODE .property (EVENT_HASH ).to (parameter (EVENT_HASH )))
114
+ .set (EVENT_PUBLICATION_NODE .property (EVENT_TYPE ).to (parameter (EVENT_TYPE )))
115
+ .set (EVENT_PUBLICATION_NODE .property (LISTENER_ID ).to (parameter (LISTENER_ID )))
116
+ .set (EVENT_PUBLICATION_NODE .property (PUBLICATION_DATE ).to (parameter (PUBLICATION_DATE )))
112
117
.build ();
113
118
114
- private static final Statement COMPLETE_STATEMENT = Cypher . match (EVENT_PUBLICATION_NODE )
115
- .where (EVENT_PUBLICATION_NODE .property (EVENT_HASH ).eq (Cypher . parameter (EVENT_HASH )))
116
- .and (EVENT_PUBLICATION_NODE .property (LISTENER_ID ).eq (Cypher . parameter (LISTENER_ID )))
119
+ private static final Statement COMPLETE_STATEMENT = match (EVENT_PUBLICATION_NODE )
120
+ .where (EVENT_PUBLICATION_NODE .property (EVENT_HASH ).eq (parameter (EVENT_HASH )))
121
+ .and (EVENT_PUBLICATION_NODE .property (LISTENER_ID ).eq (parameter (LISTENER_ID )))
117
122
.and (EVENT_PUBLICATION_NODE .property (COMPLETION_DATE ).isNull ())
118
- .set (EVENT_PUBLICATION_NODE .property (COMPLETION_DATE ).to (Cypher .parameter (COMPLETION_DATE )))
123
+ .set (EVENT_PUBLICATION_NODE .property (COMPLETION_DATE ).to (parameter (COMPLETION_DATE )))
124
+ .build ();
125
+
126
+ private static final Statement COMPLETE_IN_ARCHIVE_BY_ID_STATEMENT = match (EVENT_PUBLICATION_NODE )
127
+ .where (EVENT_PUBLICATION_NODE .property (ID ).eq (parameter (ID )))
128
+ .and (not (exists (match (EVENT_PUBLICATION_COMPLETED_NODE )
129
+ .where (EVENT_PUBLICATION_COMPLETED_NODE .property (ID ).eq (parameter (ID )))
130
+ .returning (literalTrue ()).build ())))
131
+ .with (EVENT_PUBLICATION_NODE )
132
+ .create (EVENT_PUBLICATION_COMPLETED_NODE )
133
+ .set (EVENT_PUBLICATION_COMPLETED_NODE .property (ID ).to (EVENT_PUBLICATION_NODE .property (ID )))
134
+ .set (EVENT_PUBLICATION_COMPLETED_NODE .property (COMPLETION_DATE ).to (parameter (COMPLETION_DATE )))
135
+ .build ();
136
+
137
+ private static final Statement COMPLETE_IN_ARCHIVE_BY_EVENT_AND_LISTENER_ID_STATEMENT = match (EVENT_PUBLICATION_NODE )
138
+ .where (EVENT_PUBLICATION_NODE .property (EVENT_HASH ).eq (parameter (EVENT_HASH )))
139
+ .and (EVENT_PUBLICATION_NODE .property (LISTENER_ID ).eq (parameter (LISTENER_ID )))
140
+ .and (not (exists (match (EVENT_PUBLICATION_COMPLETED_NODE )
141
+ .where (EVENT_PUBLICATION_COMPLETED_NODE .property (EVENT_HASH ).eq (parameter (EVENT_HASH )))
142
+ .and (EVENT_PUBLICATION_COMPLETED_NODE .property (LISTENER_ID ).eq (parameter (LISTENER_ID )))
143
+ .returning (literalTrue ()).build ())))
144
+ .with (EVENT_PUBLICATION_NODE )
145
+ .create (EVENT_PUBLICATION_COMPLETED_NODE )
146
+ .set (EVENT_PUBLICATION_COMPLETED_NODE .property (ID ).to (EVENT_PUBLICATION_NODE .property (ID )))
147
+ .set (EVENT_PUBLICATION_COMPLETED_NODE .property (COMPLETION_DATE ).to (parameter (COMPLETION_DATE )))
119
148
.build ();
120
149
121
- private static final Statement COMPLETE_BY_ID_STATEMENT = Cypher . match (EVENT_PUBLICATION_NODE )
122
- .where (EVENT_PUBLICATION_NODE .property (ID ).eq (Cypher . parameter (ID )))
123
- .set (EVENT_PUBLICATION_NODE .property (COMPLETION_DATE ).to (Cypher . parameter (COMPLETION_DATE )))
150
+ private static final Function < Node , Statement > COMPLETE_BY_ID_STATEMENT = node -> match (node )
151
+ .where (node .property (ID ).eq (parameter (ID )))
152
+ .set (node .property (COMPLETION_DATE ).to (parameter (COMPLETION_DATE )))
124
153
.build ();
125
154
126
- private static final ResultStatement INCOMPLETE_STATEMENT = Cypher . match (EVENT_PUBLICATION_NODE )
155
+ private static final ResultStatement INCOMPLETE_STATEMENT = match (EVENT_PUBLICATION_NODE )
127
156
.where (EVENT_PUBLICATION_NODE .property (COMPLETION_DATE ).isNull ())
128
157
.returning (EVENT_PUBLICATION_NODE )
129
158
.orderBy (EVENT_PUBLICATION_NODE .property (PUBLICATION_DATE ))
130
159
.build ();
131
160
132
- private static final ResultStatement ALL_COMPLETED_STATEMENT = Cypher . match (EVENT_PUBLICATION_NODE )
133
- .where (EVENT_PUBLICATION_NODE .property (COMPLETION_DATE ).isNotNull ())
134
- .returning (EVENT_PUBLICATION_NODE )
135
- .orderBy (EVENT_PUBLICATION_NODE .property (PUBLICATION_DATE ))
161
+ private static final Function < Node , ResultStatement > ALL_COMPLETED_STATEMENT = node -> match (node )
162
+ .where (node .property (COMPLETION_DATE ).isNotNull ())
163
+ .returning (node )
164
+ .orderBy (node .property (PUBLICATION_DATE ))
136
165
.build ();
137
166
138
167
private final Neo4jClient neo4jClient ;
139
168
private final Renderer renderer ;
140
169
private final EventSerializer eventSerializer ;
141
170
private final CompletionMode completionMode ;
142
171
172
+ private final Statement deleteCompletedStatement ;
173
+ private final Statement deleteCompletedBeforeStatement ;
174
+ private final Statement completedByIdStatement ;
175
+ private final ResultStatement allCompletedStatement ;
176
+
143
177
Neo4jEventPublicationRepository (Neo4jClient neo4jClient , Configuration cypherDslConfiguration ,
144
178
EventSerializer eventSerializer , CompletionMode completionMode ) {
145
179
@@ -152,6 +186,13 @@ class Neo4jEventPublicationRepository implements EventPublicationRepository {
152
186
this .renderer = Renderer .getRenderer (cypherDslConfiguration );
153
187
this .eventSerializer = eventSerializer ;
154
188
this .completionMode = completionMode ;
189
+
190
+ var archiveNode = completionMode == CompletionMode .ARCHIVE ? EVENT_PUBLICATION_COMPLETED_NODE : EVENT_PUBLICATION_NODE ;
191
+
192
+ this .deleteCompletedStatement = DELETE_COMPLETED_STATEMENT .apply (archiveNode );
193
+ this .deleteCompletedBeforeStatement = DELETE_COMPLETED_BEFORE_STATEMENT .apply (archiveNode );
194
+ this .completedByIdStatement = COMPLETE_BY_ID_STATEMENT .apply (archiveNode );
195
+ this .allCompletedStatement = ALL_COMPLETED_STATEMENT .apply (archiveNode );
155
196
}
156
197
157
198
/*
@@ -201,6 +242,18 @@ public void markCompleted(Object event, PublicationTargetIdentifier identifier,
201
242
.bind (identifier .getValue ()).to (LISTENER_ID )
202
243
.run ();
203
244
245
+ } else if (completionMode == CompletionMode .ARCHIVE ) {
246
+
247
+ neo4jClient .query (renderer .render (COMPLETE_IN_ARCHIVE_BY_EVENT_AND_LISTENER_ID_STATEMENT ))
248
+ .bind (eventHash ).to (EVENT_HASH )
249
+ .bind (identifier .getValue ()).to (LISTENER_ID )
250
+ .bind (Values .value (completionDate .atOffset (ZoneOffset .UTC ))).to (COMPLETION_DATE )
251
+ .run ();
252
+ neo4jClient .query (renderer .render (DELETE_BY_EVENT_AND_LISTENER_ID ))
253
+ .bind (eventHash ).to (EVENT_HASH )
254
+ .bind (identifier .getValue ()).to (LISTENER_ID )
255
+ .run ();
256
+
204
257
} else {
205
258
206
259
neo4jClient .query (renderer .render (COMPLETE_STATEMENT ))
@@ -223,13 +276,22 @@ public void markCompleted(UUID identifier, Instant completionDate) {
223
276
224
277
deletePublications (List .of (identifier ));
225
278
279
+ } else if (completionMode == CompletionMode .ARCHIVE ) {
280
+
281
+ neo4jClient .query (renderer .render (COMPLETE_IN_ARCHIVE_BY_ID_STATEMENT ))
282
+ .bind ("" ).to (ID )
283
+ .bind (Values .value (completionDate .atOffset (ZoneOffset .UTC ))).to (COMPLETION_DATE )
284
+ .run ();
285
+ deletePublications (List .of (identifier ));
286
+
226
287
} else {
227
288
228
- neo4jClient .query (renderer .render (COMPLETE_BY_ID_STATEMENT ))
289
+ neo4jClient .query (renderer .render (completedByIdStatement ))
229
290
.bind (Values .value (identifier .toString ())).to (ID )
230
291
.bind (Values .value (completionDate .atOffset (ZoneOffset .UTC ))).to (COMPLETION_DATE )
231
292
.run ();
232
293
}
294
+
233
295
}
234
296
235
297
/*
@@ -287,7 +349,7 @@ public Optional<TargetEventPublication> findIncompletePublicationsByEventAndTarg
287
349
@ Override
288
350
public List <TargetEventPublication > findCompletedPublications () {
289
351
290
- return new ArrayList <>(neo4jClient .query (renderer .render (ALL_COMPLETED_STATEMENT ))
352
+ return new ArrayList <>(neo4jClient .query (renderer .render (allCompletedStatement ))
291
353
.fetchAs (TargetEventPublication .class )
292
354
.mappedBy (this ::mapRecordToPublication )
293
355
.all ());
@@ -313,7 +375,7 @@ public void deletePublications(List<UUID> identifiers) {
313
375
@ Override
314
376
@ Transactional
315
377
public void deleteCompletedPublications () {
316
- neo4jClient .query (renderer .render (DELETE_COMPLETED_STATEMENT )).run ();
378
+ neo4jClient .query (renderer .render (deleteCompletedStatement )).run ();
317
379
}
318
380
319
381
/*
@@ -324,7 +386,7 @@ public void deleteCompletedPublications() {
324
386
@ Transactional
325
387
public void deleteCompletedPublicationsBefore (Instant instant ) {
326
388
327
- neo4jClient .query (renderer .render (DELETE_COMPLETED_BEFORE_STATEMENT ))
389
+ neo4jClient .query (renderer .render (deleteCompletedBeforeStatement ))
328
390
.bind (Values .value (instant .atOffset (ZoneOffset .UTC ))).to (PUBLICATION_DATE )
329
391
.run ();
330
392
}
0 commit comments