17
17
import java .util .Collection ;
18
18
import java .util .List ;
19
19
import java .util .Optional ;
20
+ import java .util .UUID ;
20
21
import java .util .concurrent .CompletableFuture ;
21
22
import java .util .concurrent .CompletionStage ;
22
23
import java .util .concurrent .Executor ;
25
26
import javax .annotation .Nullable ;
26
27
27
28
import org .eclipse .ditto .base .model .entity .id .EntityId ;
29
+ import org .eclipse .ditto .base .model .headers .DittoHeaderDefinition ;
28
30
import org .eclipse .ditto .base .model .headers .DittoHeaders ;
31
+ import org .eclipse .ditto .base .model .headers .DittoHeadersBuilder ;
29
32
import org .eclipse .ditto .base .model .signals .Signal ;
30
33
import org .eclipse .ditto .base .model .signals .WithResource ;
31
34
import org .eclipse .ditto .internal .utils .cache .Cache ;
54
57
*/
55
58
public class DittoCachingSignalEnrichmentFacade implements CachingSignalEnrichmentFacade {
56
59
57
- private static final ThreadSafeDittoLogger LOGGER = DittoLoggerFactory .getThreadSafeLogger (DittoCachingSignalEnrichmentFacade .class );
60
+ private static final ThreadSafeDittoLogger LOGGER =
61
+ DittoLoggerFactory .getThreadSafeLogger (DittoCachingSignalEnrichmentFacade .class );
58
62
private static final String CACHE_NAME_SUFFIX = "_signal_enrichment_cache" ;
59
63
60
64
protected final Cache <SignalEnrichmentCacheKey , JsonObject > extraFieldsCache ;
@@ -93,23 +97,45 @@ public static DittoCachingSignalEnrichmentFacade newInstance(final SignalEnrichm
93
97
94
98
@ Override
95
99
public CompletionStage <JsonObject > retrieveThing (final ThingId thingId , final List <ThingEvent <?>> events ,
96
- final long minAcceptableSeqNr ) {
100
+ final long atRevisionNumber ) {
97
101
98
- final DittoHeaders dittoHeaders = DittoHeaders .empty ();
102
+ final DittoHeaders dittoHeadersNotAddedToCacheKey =
103
+ buildDittoHeadersNotAddedToCacheKey (events , atRevisionNumber );
99
104
100
105
final JsonFieldSelector fieldSelector = determineSelector (thingId .getNamespace ());
101
106
102
- if (minAcceptableSeqNr < 0 ) {
103
- final var cacheKey =
104
- SignalEnrichmentCacheKey .of (thingId , SignalEnrichmentContext .of (dittoHeaders , fieldSelector ));
107
+ if (atRevisionNumber < 0 ) {
108
+ final var cacheKey = SignalEnrichmentCacheKey .of (
109
+ thingId ,
110
+ SignalEnrichmentContext .of (DittoHeaders .empty (), dittoHeadersNotAddedToCacheKey , fieldSelector ));
105
111
extraFieldsCache .invalidate (cacheKey );
106
- return doCacheLookup (cacheKey , dittoHeaders );
112
+ return doCacheLookup (cacheKey , dittoHeadersNotAddedToCacheKey );
107
113
} else {
108
114
final var cachingParameters =
109
- new CachingParameters (fieldSelector , events , false , minAcceptableSeqNr );
115
+ new CachingParameters (fieldSelector , events , false , atRevisionNumber );
110
116
111
- return doRetrievePartialThing (thingId , dittoHeaders , cachingParameters );
117
+ return doRetrievePartialThing (thingId , DittoHeaders .empty (), dittoHeadersNotAddedToCacheKey ,
118
+ cachingParameters );
119
+ }
120
+ }
121
+
122
+ private static DittoHeaders buildDittoHeadersNotAddedToCacheKey (final List <ThingEvent <?>> events ,
123
+ final long atRevisionNumber ) {
124
+ final DittoHeadersBuilder <?, ?> dittoHeadersBuilder = DittoHeaders .newBuilder ();
125
+ if (!events .isEmpty ()) {
126
+ dittoHeadersBuilder .correlationId (
127
+ events .get (events .size () - 1 )
128
+ .getDittoHeaders ()
129
+ .getCorrelationId ()
130
+ .orElseGet (() -> UUID .randomUUID ().toString ())
131
+ + "-enrichment"
132
+ );
112
133
}
134
+ if (atRevisionNumber > 0 ) {
135
+ dittoHeadersBuilder
136
+ .putHeader (DittoHeaderDefinition .AT_HISTORICAL_REVISION .getKey (), String .valueOf (atRevisionNumber ));
137
+ }
138
+ return dittoHeadersBuilder .build ();
113
139
}
114
140
115
141
@ Override
@@ -125,7 +151,7 @@ public CompletionStage<JsonObject> retrievePartialThing(final ThingId thingId,
125
151
final var cachingParameters =
126
152
new CachingParameters (jsonFieldSelector , thingEvents , true , 0 );
127
153
128
- return doRetrievePartialThing (thingId , dittoHeaders , cachingParameters )
154
+ return doRetrievePartialThing (thingId , dittoHeaders , null , cachingParameters )
129
155
.thenApply (jsonObject -> applyJsonFieldSelector (jsonObject , jsonFieldSelector ));
130
156
}
131
157
@@ -140,7 +166,7 @@ public CompletionStage<JsonObject> retrievePartialThing(final ThingId thingId,
140
166
* @param minAcceptableSeqNr minimum sequence number of the concerned signals to not invalidate the cache.
141
167
* @return future that completes with the parts of a thing or fails with an error.
142
168
*/
143
- @ SuppressWarnings ("java:S1612" )
169
+ @ SuppressWarnings ({ "java:S1612" , "unused" } )
144
170
public CompletionStage <JsonObject > retrievePartialThing (final EntityId thingId ,
145
171
final JsonFieldSelector jsonFieldSelector ,
146
172
final DittoHeaders dittoHeaders ,
@@ -156,19 +182,22 @@ public CompletionStage<JsonObject> retrievePartialThing(final EntityId thingId,
156
182
final var cachingParameters =
157
183
new CachingParameters (jsonFieldSelector , thingEvents , true , minAcceptableSeqNr );
158
184
159
- return doRetrievePartialThing (thingId , dittoHeaders , cachingParameters )
185
+ return doRetrievePartialThing (thingId , dittoHeaders , null , cachingParameters )
160
186
.thenApply (jsonObject -> applyJsonFieldSelector (jsonObject , jsonFieldSelector ));
161
187
}
162
188
163
189
protected CompletionStage <JsonObject > doRetrievePartialThing (final EntityId thingId ,
164
- final DittoHeaders dittoHeaders ,
165
- final CachingParameters cachingParameters ) {
190
+ final DittoHeaders dittoHeaders ,
191
+ @ Nullable final DittoHeaders dittoHeadersNotAddedToCacheKey ,
192
+ final CachingParameters cachingParameters ) {
166
193
167
194
final var fieldSelector = cachingParameters .fieldSelector ;
168
195
final JsonFieldSelector enhancedFieldSelector = enhanceFieldSelectorWithRevision (fieldSelector );
169
196
170
- final var idWithResourceType =
171
- SignalEnrichmentCacheKey .of (thingId , SignalEnrichmentContext .of (dittoHeaders , enhancedFieldSelector ));
197
+ final var idWithResourceType = SignalEnrichmentCacheKey .of (
198
+ thingId ,
199
+ SignalEnrichmentContext .of (dittoHeaders , dittoHeadersNotAddedToCacheKey , enhancedFieldSelector )
200
+ );
172
201
173
202
final var cachingParametersWithEnhancedFieldSelector = new CachingParameters (enhancedFieldSelector ,
174
203
cachingParameters .concernedEvents ,
@@ -282,7 +311,7 @@ private static DittoHeaders getLastDittoHeaders(final List<? extends Signal<?>>
282
311
}
283
312
284
313
protected CompletableFuture <JsonObject > doCacheLookup (final SignalEnrichmentCacheKey cacheKey ,
285
- final DittoHeaders dittoHeaders ) {
314
+ final DittoHeaders dittoHeaders ) {
286
315
LOGGER .withCorrelationId (dittoHeaders ).debug ("Looking up cache entry for <{}>" , cacheKey );
287
316
288
317
return extraFieldsCache .get (cacheKey )
@@ -343,16 +372,11 @@ private CompletionStage<JsonObject> handleNextExpectedThingEvents(final SignalEn
343
372
JsonObject jsonObject = cachedJsonObject ;
344
373
for (final ThingEvent <?> thingEvent : concernedSignals ) {
345
374
346
- switch (thingEvent .getCommandCategory ()) {
347
- case MERGE :
348
- jsonObject = getMergeJsonObject (jsonObject , thingEvent );
349
- break ;
350
- case DELETE :
351
- jsonObject = getDeleteJsonObject (jsonObject , thingEvent );
352
- break ;
353
- default :
354
- jsonObject = getDefaultJsonObject (jsonObject , thingEvent );
355
- }
375
+ jsonObject = switch (thingEvent .getCommandCategory ()) {
376
+ case MERGE -> getMergeJsonObject (jsonObject , thingEvent );
377
+ case DELETE -> getDeleteJsonObject (jsonObject , thingEvent );
378
+ default -> getDefaultJsonObject (jsonObject , thingEvent );
379
+ };
356
380
// invalidate cache on policy change if the flag is set
357
381
if (cachingParameters .invalidateCacheOnPolicyChange ) {
358
382
final var optionalCompletionStage =
@@ -392,7 +416,8 @@ private static JsonObject getDeleteJsonObject(final JsonObject jsonObject, final
392
416
} else if (resourcePath .isEmpty ()) {
393
417
result = JsonObject .empty ();
394
418
} else {
395
- result = jsonObject .remove (resourcePath ).remove (Thing .JsonFields .METADATA .getPointer ().append (resourcePath ));
419
+ result =
420
+ jsonObject .remove (resourcePath ).remove (Thing .JsonFields .METADATA .getPointer ().append (resourcePath ));
396
421
}
397
422
398
423
return result ;
@@ -463,9 +488,9 @@ protected static final class CachingParameters {
463
488
private final long minAcceptableSeqNr ;
464
489
465
490
public CachingParameters (@ Nullable final JsonFieldSelector fieldSelector ,
466
- final List <ThingEvent <?>> concernedEvents ,
467
- final boolean invalidateCacheOnPolicyChange ,
468
- final long minAcceptableSeqNr ) {
491
+ final List <ThingEvent <?>> concernedEvents ,
492
+ final boolean invalidateCacheOnPolicyChange ,
493
+ final long minAcceptableSeqNr ) {
469
494
470
495
this .fieldSelector = fieldSelector ;
471
496
this .concernedEvents = concernedEvents ;
0 commit comments