|
16 | 16 | import dev.openfeature.contrib.providers.gofeatureflag.events.EventsPublisher;
|
17 | 17 | import dev.openfeature.contrib.providers.gofeatureflag.exception.InvalidEndpoint;
|
18 | 18 | import dev.openfeature.contrib.providers.gofeatureflag.exception.InvalidOptions;
|
| 19 | +import dev.openfeature.contrib.providers.gofeatureflag.exception.InvalidTypeInCache; |
19 | 20 | import dev.openfeature.sdk.ErrorCode;
|
20 | 21 | import dev.openfeature.sdk.EvaluationContext;
|
21 | 22 | import dev.openfeature.sdk.FeatureProvider;
|
@@ -255,68 +256,74 @@ public ProviderState getState() {
|
255 | 256 | * @param <T> the type of your evaluation
|
256 | 257 | * @return a ProviderEvaluation that contains the open-feature response
|
257 | 258 | */
|
| 259 | + @SuppressWarnings("unchecked") |
258 | 260 | private <T> ProviderEvaluation<T> getEvaluation(
|
259 | 261 | String key, T defaultValue, EvaluationContext evaluationContext, Class<?> expectedType) {
|
260 |
| - if (!ProviderState.READY.equals(state)) { |
261 |
| - ErrorCode errorCode = ErrorCode.PROVIDER_NOT_READY; |
262 |
| - if (ProviderState.ERROR.equals(state)) { |
263 |
| - errorCode = ErrorCode.GENERAL; |
264 |
| - } |
265 |
| - return ProviderEvaluation.<T>builder() |
266 |
| - .errorCode(errorCode) |
267 |
| - .reason(errorCode.name()) |
268 |
| - .value(defaultValue) |
269 |
| - .build(); |
270 |
| - } |
271 |
| - ProviderEvaluation<T> res; |
272 | 262 | GoFeatureFlagUser user = GoFeatureFlagUser.fromEvaluationContext(evaluationContext);
|
273 |
| - if (cache == null) { |
274 |
| - EvaluationResponse<T> proxyRes = resolveEvaluationGoFeatureFlagProxy(key, defaultValue, user, expectedType); |
275 |
| - res = proxyRes.getProviderEvaluation(); |
276 |
| - } else { |
277 |
| - res = getProviderEvaluationWithCheckCache(key, defaultValue, expectedType, user); |
278 |
| - } |
279 |
| - return res; |
280 |
| - } |
281 |
| - |
282 |
| - private <T> ProviderEvaluation getProviderEvaluationWithCheckCache( |
283 |
| - String key, T defaultValue, Class<?> expectedType, GoFeatureFlagUser user) { |
284 |
| - ProviderEvaluation<?> res; |
285 | 263 | try {
|
| 264 | + if (!ProviderState.READY.equals(state)) { |
| 265 | + ErrorCode errorCode = ErrorCode.PROVIDER_NOT_READY; |
| 266 | + if (ProviderState.ERROR.equals(state)) { |
| 267 | + errorCode = ErrorCode.GENERAL; |
| 268 | + } |
| 269 | + return ProviderEvaluation.<T>builder() |
| 270 | + .errorCode(errorCode) |
| 271 | + .reason(errorCode.name()) |
| 272 | + .value(defaultValue) |
| 273 | + .build(); |
| 274 | + } |
| 275 | + |
| 276 | + if (cache == null) { |
| 277 | + return resolveEvaluationGoFeatureFlagProxy(key, defaultValue, user, expectedType).getProviderEvaluation(); |
| 278 | + } |
| 279 | + |
286 | 280 | String cacheKey = buildCacheKey(key, BeanUtils.buildKey(user));
|
287 |
| - res = cache.getIfPresent(cacheKey); |
288 |
| - if (res == null) { |
| 281 | + ProviderEvaluation<?> cachedProviderEvaluation = cache.getIfPresent(cacheKey); |
| 282 | + if (cachedProviderEvaluation == null) { |
289 | 283 | EvaluationResponse<T> proxyRes = resolveEvaluationGoFeatureFlagProxy(
|
290 |
| - key, defaultValue, user, expectedType); |
| 284 | + key, defaultValue, user, expectedType); |
291 | 285 | if (Boolean.TRUE.equals(proxyRes.getCachable())) {
|
292 | 286 | cache.put(cacheKey, proxyRes.getProviderEvaluation());
|
293 | 287 | }
|
294 |
| - res = proxyRes.getProviderEvaluation(); |
295 |
| - } else { |
296 |
| - res.setReason(CACHED_REASON); |
297 |
| - addCacheEvaluationEvent(key, defaultValue, user, res); |
| 288 | + return proxyRes.getProviderEvaluation(); |
| 289 | + } |
| 290 | + cachedProviderEvaluation.setReason(CACHED_REASON); |
| 291 | + addCacheEvaluationEvent(key, defaultValue, user, cachedProviderEvaluation); |
| 292 | + |
| 293 | + if (cachedProviderEvaluation.getValue().getClass() != expectedType){ |
| 294 | + throw new InvalidTypeInCache(expectedType, cachedProviderEvaluation.getValue().getClass()); |
298 | 295 | }
|
| 296 | + return (ProviderEvaluation<T>) cachedProviderEvaluation; |
299 | 297 | } catch (JsonProcessingException e) {
|
300 | 298 | log.error("Error building key for user", e);
|
301 |
| - EvaluationResponse<T> proxyRes = resolveEvaluationGoFeatureFlagProxy( |
302 |
| - key, defaultValue, user, expectedType); |
303 |
| - res = proxyRes.getProviderEvaluation(); |
| 299 | + return resolveEvaluationGoFeatureFlagProxy(key, defaultValue, user, expectedType).getProviderEvaluation(); |
| 300 | + } catch (InvalidTypeInCache e) { |
| 301 | + log.warn(e.getMessage(), e); |
| 302 | + return resolveEvaluationGoFeatureFlagProxy(key, defaultValue, user, expectedType).getProviderEvaluation(); |
304 | 303 | }
|
305 |
| - return res; |
306 | 304 | }
|
307 | 305 |
|
| 306 | + /** |
| 307 | + * addCacheEvaluationEvent is adding an event to the list of event to send to GO Feature Flag. |
| 308 | + * |
| 309 | + * @param key - name of the feature flag |
| 310 | + * @param defaultValue - value used if something is not working as expected |
| 311 | + * @param user - user (containing EvaluationContext) used for the request |
| 312 | + * @param providerEvaluation - object containing the evaluation response for openfeature |
| 313 | + * @param <T> the type of your evaluation |
| 314 | + */ |
308 | 315 | private <T> void addCacheEvaluationEvent(String key, T defaultValue, GoFeatureFlagUser user,
|
309 |
| - ProviderEvaluation<?> res) { |
| 316 | + ProviderEvaluation<?> providerEvaluation) { |
310 | 317 | eventsPublisher.add(Event.builder()
|
311 |
| - .key(key) |
312 |
| - .kind("feature") |
313 |
| - .contextKind(user.isAnonymous() ? "anonymousUser" : "user") |
314 |
| - .defaultValue(defaultValue) |
315 |
| - .variation(res.getVariant()) |
316 |
| - .value(res.getValue()) |
317 |
| - .userKey(user.getKey()) |
318 |
| - .creationDate(System.currentTimeMillis()) |
319 |
| - .build() |
| 318 | + .key(key) |
| 319 | + .kind("feature") |
| 320 | + .contextKind(user.isAnonymous() ? "anonymousUser" : "user") |
| 321 | + .defaultValue(defaultValue) |
| 322 | + .variation(providerEvaluation.getVariant()) |
| 323 | + .value(providerEvaluation.getValue()) |
| 324 | + .userKey(user.getKey()) |
| 325 | + .creationDate(System.currentTimeMillis()) |
| 326 | + .build() |
320 | 327 | );
|
321 | 328 | }
|
322 | 329 |
|
@@ -529,11 +536,11 @@ private void publishEvents(List<Event> eventsList) {
|
529 | 536 | .build();
|
530 | 537 |
|
531 | 538 | Request.Builder reqBuilder = new Request.Builder()
|
532 |
| - .url(url) |
533 |
| - .addHeader("Content-Type", "application/json") |
534 |
| - .post(RequestBody.create( |
535 |
| - requestMapper.writeValueAsBytes(events), |
536 |
| - MediaType.get("application/json; charset=utf-8"))); |
| 539 | + .url(url) |
| 540 | + .addHeader("Content-Type", "application/json") |
| 541 | + .post(RequestBody.create( |
| 542 | + requestMapper.writeValueAsBytes(events), |
| 543 | + MediaType.get("application/json; charset=utf-8"))); |
537 | 544 |
|
538 | 545 | if (this.apiKey != null && !"".equals(this.apiKey)) {
|
539 | 546 | reqBuilder.addHeader("Authorization", "Bearer " + this.apiKey);
|
|
0 commit comments