-
Notifications
You must be signed in to change notification settings - Fork 52
Expand file tree
/
Copy pathFirstMatchStrategy.java
More file actions
63 lines (58 loc) · 2.38 KB
/
FirstMatchStrategy.java
File metadata and controls
63 lines (58 loc) · 2.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package dev.openfeature.sdk.multiprovider;
import static dev.openfeature.sdk.ErrorCode.FLAG_NOT_FOUND;
import dev.openfeature.sdk.ErrorCode;
import dev.openfeature.sdk.EvaluationContext;
import dev.openfeature.sdk.FeatureProvider;
import dev.openfeature.sdk.ProviderEvaluation;
import dev.openfeature.sdk.exceptions.FlagNotFoundError;
import java.util.List;
import java.util.function.Function;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
/**
* First match strategy.
*
* <p>Return the first result returned by a provider.
* <ul>
* <li>Skip providers that indicate they had no value due to {@code FLAG_NOT_FOUND}.</li>
* <li>On any other error code, return that error result.</li>
* <li>If a provider throws {@link FlagNotFoundError}, it is treated like {@code FLAG_NOT_FOUND}.</li>
* <li>If all providers report {@code FLAG_NOT_FOUND}, return a {@code FLAG_NOT_FOUND} error.</li>
* </ul>
* As soon as a non-{@code FLAG_NOT_FOUND} result is returned by a provider (success or other error),
* the rest of the operation short-circuits and does not call the remaining providers.
*/
@Slf4j
@NoArgsConstructor
public class FirstMatchStrategy implements Strategy {
@Override
public <T> ProviderEvaluation<T> evaluate(
List<FeatureProvider> providers,
String key,
T defaultValue,
EvaluationContext ctx,
Function<FeatureProvider, ProviderEvaluation<T>> providerFunction) {
for (FeatureProvider provider : providers) {
try {
ProviderEvaluation<T> res = providerFunction.apply(provider);
ErrorCode errorCode = res.getErrorCode();
if (errorCode == null) {
// Successful evaluation
return res;
}
if (!FLAG_NOT_FOUND.equals(errorCode)) {
// Any non-FLAG_NOT_FOUND error bubbles up
return res;
}
// else FLAG_NOT_FOUND: skip to next provider
} catch (FlagNotFoundError ignored) {
// do not log in hot path, just skip
}
}
// All providers either threw or returned FLAG_NOT_FOUND
return ProviderEvaluation.<T>builder()
.errorMessage("Flag not found in any provider")
.errorCode(FLAG_NOT_FOUND)
.build();
}
}