26
26
@ SuppressWarnings ("OverloadMethodsDeclarationOrder" )
27
27
public class GestaltCache implements Gestalt , CoreReloadListener {
28
28
private final Gestalt delegate ;
29
- private final Map <Triple <String , TypeCapture <?>, Tags >, GResultOf <Object >> cache = Collections .synchronizedMap (new HashMap <>());
29
+ private final Map <Triple <String , TypeCapture <?>, Tags >, Object > cache = Collections .synchronizedMap (new HashMap <>());
30
+ private final Map <Triple <String , TypeCapture <?>, Tags >, GResultOf <Object >> cacheResultsOf = Collections .synchronizedMap (new HashMap <>());
30
31
private final Tags defaultTags ;
31
32
private final ObservationService observationService ;
32
33
private final GestaltConfig gestaltConfig ;
@@ -66,7 +67,7 @@ public <T> T getConfig(String path, Class<T> klass) throws GestaltException {
66
67
Objects .requireNonNull (klass );
67
68
68
69
TypeCapture <T > typeCapture = TypeCapture .of (klass );
69
- return getConfigInternal (path , typeCapture , null ). results () ;
70
+ return getConfigInternal (path , typeCapture , null );
70
71
}
71
72
72
73
@ Override
@@ -76,15 +77,15 @@ public <T> T getConfig(String path, Class<T> klass, Tags tags) throws GestaltExc
76
77
Objects .requireNonNull (tags );
77
78
78
79
TypeCapture <T > typeCapture = TypeCapture .of (klass );
79
- return getConfigInternal (path , typeCapture , tags ). results () ;
80
+ return getConfigInternal (path , typeCapture , tags );
80
81
}
81
82
82
83
@ Override
83
84
public <T > T getConfig (String path , TypeCapture <T > klass ) throws GestaltException {
84
85
Objects .requireNonNull (path );
85
86
Objects .requireNonNull (klass );
86
87
87
- return getConfigInternal (path , klass , null ). results () ;
88
+ return getConfigInternal (path , klass , null );
88
89
}
89
90
90
91
@ Override
@@ -93,7 +94,7 @@ public <T> T getConfig(String path, TypeCapture<T> klass, Tags tags) throws Gest
93
94
Objects .requireNonNull (klass );
94
95
Objects .requireNonNull (tags );
95
96
96
- return getConfigInternal (path , klass , tags ). results () ;
97
+ return getConfigInternal (path , klass , tags );
97
98
}
98
99
99
100
@ Override
@@ -102,30 +103,54 @@ public <T> GResultOf<T> getConfigResult(String path, TypeCapture<T> klass, Tags
102
103
Objects .requireNonNull (klass );
103
104
Objects .requireNonNull (tags );
104
105
105
- return getConfigInternal (path , klass , tags );
106
+ return getConfigInternalResult (path , klass , tags );
106
107
}
107
108
108
109
@ SuppressWarnings ("unchecked" )
109
- private <T > GResultOf < T > getConfigInternal (String path , TypeCapture <T > klass , Tags tags ) throws GestaltException {
110
+ private <T > T getConfigInternal (String path , TypeCapture <T > klass , Tags tags ) throws GestaltException {
110
111
111
112
Tags resolvedTags = tagMergingStrategy .mergeTags (tags , defaultTags );
112
113
Triple <String , TypeCapture <?>, Tags > key = new Triple <>(path , klass , resolvedTags );
113
- if (cache .get (key ) != null && cache . get ( key ). hasResults () ) {
114
+ if (cache .get (key ) != null ) {
114
115
if (gestaltConfig .isObservationsEnabled () && observationService != null ) {
115
116
observationService .recordObservation ("cache.hit" , 1 , Tags .of ());
116
117
}
117
- return (GResultOf < T > ) cache .get (key );
118
+ return (T ) cache .get (key );
118
119
} else {
119
120
GResultOf <T > result = delegate .getConfigResult (path , klass , resolvedTags );
120
121
updateCache (path , key , result );
122
+ return result != null ? result .results (): null ;
123
+ }
124
+ }
125
+
126
+ @ SuppressWarnings ("unchecked" )
127
+ private <T > GResultOf <T > getConfigInternalResult (String path , TypeCapture <T > klass , Tags tags ) throws GestaltException {
128
+
129
+ Tags resolvedTags = tagMergingStrategy .mergeTags (tags , defaultTags );
130
+ Triple <String , TypeCapture <?>, Tags > key = new Triple <>(path , klass , resolvedTags );
131
+ if (cacheResultsOf .get (key ) != null && cacheResultsOf .get (key ).hasResults ()) {
132
+ if (gestaltConfig .isObservationsEnabled () && observationService != null ) {
133
+ observationService .recordObservation ("cache.hit" , 1 , Tags .of ());
134
+ }
135
+ return (GResultOf <T >) cacheResultsOf .get (key );
136
+ } else {
137
+ GResultOf <T > result = delegate .getConfigResult (path , klass , resolvedTags );
138
+ updateCacheResults (path , key , result );
121
139
return result ;
122
140
}
123
141
}
124
142
125
143
@ SuppressWarnings ("unchecked" )
126
144
private <T > void updateCache (String path , Triple <String , TypeCapture <?>, Tags > key , GResultOf <T > result ) {
127
145
if (shouldCacheValue (path , result != null ? result .getMetadata () : Map .of ())) {
128
- cache .put (key , (GResultOf <Object >) result );
146
+ cache .put (key , result != null ? result .results () : null );
147
+ }
148
+ }
149
+
150
+ @ SuppressWarnings ("unchecked" )
151
+ private <T > void updateCacheResults (String path , Triple <String , TypeCapture <?>, Tags > key , GResultOf <T > result ) {
152
+ if (shouldCacheValue (path , result != null ? result .getMetadata () : Map .of ())) {
153
+ cacheResultsOf .put (key , (GResultOf <Object >) result );
129
154
}
130
155
}
131
156
@@ -135,7 +160,7 @@ public <T> T getConfig(String path, T defaultVal, Class<T> klass) {
135
160
Objects .requireNonNull (klass );
136
161
137
162
TypeCapture <T > typeCapture = TypeCapture .of (klass );
138
- return getConfigInternal (path , defaultVal , typeCapture , null ). results () ;
163
+ return getConfigInternal (path , defaultVal , typeCapture , null );
139
164
}
140
165
141
166
@ Override
@@ -145,7 +170,7 @@ public <T> T getConfig(String path, T defaultVal, Class<T> klass, Tags tags) {
145
170
Objects .requireNonNull (tags );
146
171
147
172
TypeCapture <T > typeCapture = TypeCapture .of (klass );
148
- return getConfigInternal (path , defaultVal , typeCapture , tags ). results () ;
173
+ return getConfigInternal (path , defaultVal , typeCapture , tags );
149
174
}
150
175
151
176
@ Override
@@ -154,7 +179,7 @@ public <T> GResultOf<T> getConfigResult(String path, T defaultVal, TypeCapture<T
154
179
Objects .requireNonNull (klass );
155
180
Objects .requireNonNull (tags );
156
181
157
- return getConfigInternal (path , defaultVal , klass , tags );
182
+ return getConfigInternalResult (path , defaultVal , klass , tags );
158
183
}
159
184
160
185
@@ -164,7 +189,7 @@ public <T> T getConfig(String path, T defaultVal, TypeCapture<T> klass) {
164
189
Objects .requireNonNull (path );
165
190
Objects .requireNonNull (klass );
166
191
167
- return getConfigInternal (path , defaultVal , klass , null ). results () ;
192
+ return getConfigInternal (path , defaultVal , klass , null );
168
193
}
169
194
170
195
@ Override
@@ -173,15 +198,44 @@ public <T> T getConfig(String path, T defaultVal, TypeCapture<T> klass, Tags tag
173
198
Objects .requireNonNull (klass );
174
199
Objects .requireNonNull (tags );
175
200
176
- return getConfigInternal (path , defaultVal , klass , tags ). results () ;
201
+ return getConfigInternal (path , defaultVal , klass , tags );
177
202
}
178
203
179
204
@ SuppressWarnings ("unchecked" )
180
- private <T > GResultOf < T > getConfigInternal (String path , T defaultVal , TypeCapture <T > klass , Tags tags ) {
205
+ private <T > T getConfigInternal (String path , T defaultVal , TypeCapture <T > klass , Tags tags ) {
181
206
Tags resolvedTags = tagMergingStrategy .mergeTags (tags , defaultTags );
182
207
Triple <String , TypeCapture <?>, Tags > key = new Triple <>(path , klass , resolvedTags );
183
208
if (cache .containsKey (key )) {
184
- GResultOf <T > result = (GResultOf <T >) cache .get (key );
209
+ T result = (T ) cache .get (key );
210
+ if (result == null ) {
211
+ result = defaultVal ;
212
+ }
213
+
214
+ if (gestaltConfig .isObservationsEnabled () && observationService != null ) {
215
+ observationService .recordObservation ("cache.hit" , 1 , Tags .of ());
216
+ }
217
+
218
+ return result ;
219
+
220
+ } else {
221
+ Optional <GResultOf <T >> result = delegate .getConfigOptionalResult (path , klass , resolvedTags );
222
+
223
+ updateCache (path , key , result .orElse (null ));
224
+
225
+ if (result .isPresent () && result .get ().hasResults ()) {
226
+ return result .get ().results ();
227
+ } else {
228
+ return defaultVal ;
229
+ }
230
+ }
231
+ }
232
+
233
+ @ SuppressWarnings ("unchecked" )
234
+ private <T > GResultOf <T > getConfigInternalResult (String path , T defaultVal , TypeCapture <T > klass , Tags tags ) {
235
+ Tags resolvedTags = tagMergingStrategy .mergeTags (tags , defaultTags );
236
+ Triple <String , TypeCapture <?>, Tags > key = new Triple <>(path , klass , resolvedTags );
237
+ if (cacheResultsOf .containsKey (key )) {
238
+ GResultOf <T > result = (GResultOf <T >) cacheResultsOf .get (key );
185
239
if (result == null || !result .hasResults ()) {
186
240
result = GResultOf .result (defaultVal , true );
187
241
}
@@ -195,7 +249,7 @@ private <T> GResultOf<T> getConfigInternal(String path, T defaultVal, TypeCaptur
195
249
} else {
196
250
Optional <GResultOf <T >> result = delegate .getConfigOptionalResult (path , klass , resolvedTags );
197
251
198
- updateCache (path , key , result .orElse (null ));
252
+ updateCacheResults (path , key , result .orElse (null ));
199
253
200
254
if (result .isPresent () && result .get ().hasResults ()) {
201
255
return result .get ();
@@ -211,7 +265,7 @@ public <T> Optional<T> getConfigOptional(String path, Class<T> klass) {
211
265
Objects .requireNonNull (klass );
212
266
213
267
TypeCapture <T > typeCapture = TypeCapture .of (klass );
214
- return getConfigOptionalInternal (path , typeCapture , null ). map ( GResultOf :: results ) ;
268
+ return getConfigOptionalInternal (path , typeCapture , null );
215
269
}
216
270
217
271
@ Override
@@ -221,15 +275,15 @@ public <T> Optional<T> getConfigOptional(String path, Class<T> klass, Tags tags)
221
275
Objects .requireNonNull (tags );
222
276
223
277
TypeCapture <T > typeCapture = TypeCapture .of (klass );
224
- return getConfigOptionalInternal (path , typeCapture , tags ). map ( GResultOf :: results ) ;
278
+ return getConfigOptionalInternal (path , typeCapture , tags );
225
279
}
226
280
227
281
@ Override
228
282
public <T > Optional <T > getConfigOptional (String path , TypeCapture <T > klass ) {
229
283
Objects .requireNonNull (path );
230
284
Objects .requireNonNull (klass );
231
285
232
- return getConfigOptionalInternal (path , klass , null ). map ( GResultOf :: results ) ;
286
+ return getConfigOptionalInternal (path , klass , null );
233
287
}
234
288
235
289
@ Override
@@ -238,7 +292,7 @@ public <T> Optional<T> getConfigOptional(String path, TypeCapture<T> klass, Tags
238
292
Objects .requireNonNull (klass );
239
293
Objects .requireNonNull (tags );
240
294
241
- return getConfigOptionalInternal (path , klass , tags ). map ( GResultOf :: results ) ;
295
+ return getConfigOptionalInternal (path , klass , tags );
242
296
}
243
297
244
298
@ Override
@@ -247,11 +301,11 @@ public <T> Optional<GResultOf<T>> getConfigOptionalResult(String path, TypeCaptu
247
301
Objects .requireNonNull (klass );
248
302
Objects .requireNonNull (tags );
249
303
250
- return getConfigOptionalInternal (path , klass , tags );
304
+ return getConfigOptionalInternalResult (path , klass , tags );
251
305
}
252
306
253
307
@ SuppressWarnings ("unchecked" )
254
- public <T > Optional <GResultOf < T > > getConfigOptionalInternal (String path , TypeCapture <T > klass , Tags tags ) {
308
+ public <T > Optional <T > getConfigOptionalInternal (String path , TypeCapture <T > klass , Tags tags ) {
255
309
256
310
Tags resolvedTags = tagMergingStrategy .mergeTags (tags , defaultTags );
257
311
Triple <String , TypeCapture <?>, Tags > key = new Triple <>(path , klass , resolvedTags );
@@ -260,12 +314,31 @@ public <T> Optional<GResultOf<T>> getConfigOptionalInternal(String path, TypeCap
260
314
observationService .recordObservation ("cache.hit" , 1 , Tags .of ());
261
315
}
262
316
263
- GResultOf < T > result = (GResultOf < T > ) cache .get (key );
317
+ T result = (T ) cache .get (key );
264
318
return Optional .ofNullable (result );
265
319
} else {
266
320
Optional <GResultOf <T >> resultOptional = delegate .getConfigOptionalResult (path , klass , resolvedTags );
267
321
GResultOf <T > result = resultOptional .orElse (null );
268
322
updateCache (path , key , result );
323
+ return Optional .ofNullable (result != null ? result .results () : null );
324
+ }
325
+ }
326
+
327
+ public <T > Optional <GResultOf <T >> getConfigOptionalInternalResult (String path , TypeCapture <T > klass , Tags tags ) {
328
+
329
+ Tags resolvedTags = tagMergingStrategy .mergeTags (tags , defaultTags );
330
+ Triple <String , TypeCapture <?>, Tags > key = new Triple <>(path , klass , resolvedTags );
331
+ if (cacheResultsOf .containsKey (key )) {
332
+ if (gestaltConfig .isObservationsEnabled () && observationService != null ) {
333
+ observationService .recordObservation ("cache.hit" , 1 , Tags .of ());
334
+ }
335
+
336
+ GResultOf <T > result = (GResultOf <T >) cacheResultsOf .get (key );
337
+ return Optional .ofNullable (result );
338
+ } else {
339
+ Optional <GResultOf <T >> resultOptional = delegate .getConfigOptionalResult (path , klass , resolvedTags );
340
+ GResultOf <T > result = resultOptional .orElse (null );
341
+ updateCacheResults (path , key , result );
269
342
return Optional .ofNullable (result );
270
343
}
271
344
}
@@ -274,9 +347,9 @@ private boolean shouldCacheValue(String path, Map<String, List<MetaDataValue<?>>
274
347
boolean notIsSecret = nonCacheableSecrets .stream ().noneMatch (it -> it .isSecret (path ));
275
348
boolean noCacheMetadata = metadata .containsKey (IsNoCacheMetadata .NO_CACHE ) &&
276
349
metadata .get (IsNoCacheMetadata .NO_CACHE ).stream ()
277
- .map (it -> it instanceof IsNoCacheMetadata && ((IsNoCacheMetadata ) it ).getMetadata ())
278
- .filter (it -> it )
279
- .findFirst ().orElse (false );
350
+ .map (it -> it instanceof IsNoCacheMetadata && ((IsNoCacheMetadata ) it ).getMetadata ())
351
+ .filter (it -> it )
352
+ .findFirst ().orElse (false );
280
353
281
354
return notIsSecret && !noCacheMetadata ;
282
355
}
0 commit comments