1
1
package dev .openfeature .contrib .providers .flagd ;
2
2
3
+ import java .util .ArrayList ;
3
4
import java .util .Collections ;
4
- import java .util .Map ;
5
+ import java .util .List ;
6
+ import java .util .function .Function ;
5
7
6
8
import dev .openfeature .contrib .providers .flagd .resolver .Resolver ;
7
9
import dev .openfeature .contrib .providers .flagd .resolver .common .ConnectionEvent ;
10
12
import dev .openfeature .contrib .providers .flagd .resolver .process .InProcessResolver ;
11
13
import dev .openfeature .sdk .EvaluationContext ;
12
14
import dev .openfeature .sdk .EventProvider ;
15
+ import dev .openfeature .sdk .Hook ;
16
+ import dev .openfeature .sdk .ImmutableContext ;
17
+ import dev .openfeature .sdk .ImmutableStructure ;
13
18
import dev .openfeature .sdk .Metadata ;
14
19
import dev .openfeature .sdk .ProviderEvaluation ;
15
20
import dev .openfeature .sdk .ProviderEventDetails ;
21
+ import dev .openfeature .sdk .Structure ;
16
22
import dev .openfeature .sdk .Value ;
17
23
import lombok .extern .slf4j .Slf4j ;
18
24
22
28
@ Slf4j
23
29
@ SuppressWarnings ({ "PMD.TooManyStaticImports" , "checkstyle:NoFinalizer" })
24
30
public class FlagdProvider extends EventProvider {
31
+ private Function <Structure , EvaluationContext > contextEnricher ;
25
32
private static final String FLAGD_PROVIDER = "flagd" ;
26
33
private final Resolver flagResolver ;
27
34
private volatile boolean initialized = false ;
28
35
private volatile boolean connected = false ;
29
- private volatile Map < String , Object > syncMetadata = Collections . emptyMap ();
30
-
31
- private EvaluationContext evaluationContext ;
36
+ private volatile Structure syncMetadata = new ImmutableStructure ();
37
+ private volatile EvaluationContext enrichedContext = new ImmutableContext ();
38
+ private final List < Hook > hooks = new ArrayList <>() ;
32
39
33
40
protected final void finalize () {
34
41
// DO NOT REMOVE, spotbugs: CT_CONSTRUCTOR_THROW
@@ -62,6 +69,13 @@ public FlagdProvider(final FlagdOptions options) {
62
69
throw new IllegalStateException (
63
70
String .format ("Requested unsupported resolver type of %s" , options .getResolverType ()));
64
71
}
72
+ hooks .add (new SyncMetadataHook (this ::getEnrichedContext ));
73
+ contextEnricher = options .getContextEnricher ();
74
+ }
75
+
76
+ @ Override
77
+ public List <Hook > getProviderHooks () {
78
+ return Collections .unmodifiableList (hooks );
65
79
}
66
80
67
81
@ Override
@@ -70,7 +84,6 @@ public synchronized void initialize(EvaluationContext evaluationContext) throws
70
84
return ;
71
85
}
72
86
73
- this .evaluationContext = evaluationContext ;
74
87
this .flagResolver .init ();
75
88
this .initialized = true ;
76
89
}
@@ -97,48 +110,48 @@ public Metadata getMetadata() {
97
110
98
111
@ Override
99
112
public ProviderEvaluation <Boolean > getBooleanEvaluation (String key , Boolean defaultValue , EvaluationContext ctx ) {
100
- return this .flagResolver .booleanEvaluation (key , defaultValue , mergeContext ( ctx ) );
113
+ return this .flagResolver .booleanEvaluation (key , defaultValue , ctx );
101
114
}
102
115
103
116
@ Override
104
117
public ProviderEvaluation <String > getStringEvaluation (String key , String defaultValue , EvaluationContext ctx ) {
105
- return this .flagResolver .stringEvaluation (key , defaultValue , mergeContext ( ctx ) );
118
+ return this .flagResolver .stringEvaluation (key , defaultValue , ctx );
106
119
}
107
120
108
121
@ Override
109
122
public ProviderEvaluation <Double > getDoubleEvaluation (String key , Double defaultValue , EvaluationContext ctx ) {
110
- return this .flagResolver .doubleEvaluation (key , defaultValue , mergeContext ( ctx ) );
123
+ return this .flagResolver .doubleEvaluation (key , defaultValue , ctx );
111
124
}
112
125
113
126
@ Override
114
127
public ProviderEvaluation <Integer > getIntegerEvaluation (String key , Integer defaultValue , EvaluationContext ctx ) {
115
- return this .flagResolver .integerEvaluation (key , defaultValue , mergeContext ( ctx ) );
128
+ return this .flagResolver .integerEvaluation (key , defaultValue , ctx );
116
129
}
117
130
118
131
@ Override
119
132
public ProviderEvaluation <Value > getObjectEvaluation (String key , Value defaultValue , EvaluationContext ctx ) {
120
- return this .flagResolver .objectEvaluation (key , defaultValue , mergeContext ( ctx ) );
133
+ return this .flagResolver .objectEvaluation (key , defaultValue , ctx );
121
134
}
122
135
123
136
/**
124
- * An unmodifiable view of an object map representing the latest result of the
137
+ * An unmodifiable view of a Structure representing the latest result of the
125
138
* SyncMetadata.
126
139
* Set on initial connection and updated with every reconnection.
127
140
* see:
128
141
* https://buf.build/open-feature/flagd/docs/main:flagd.sync.v1#flagd.sync.v1.FlagSyncService.GetMetadata
129
142
*
130
143
* @return Object map representing sync metadata
131
144
*/
132
- protected Map < String , Object > getSyncMetadata () {
133
- return Collections . unmodifiableMap (syncMetadata );
145
+ protected Structure getSyncMetadata () {
146
+ return new ImmutableStructure (syncMetadata . asMap () );
134
147
}
135
148
136
- private EvaluationContext mergeContext ( final EvaluationContext clientCallCtx ) {
137
- if ( this . evaluationContext != null ) {
138
- return evaluationContext . merge ( clientCallCtx );
139
- }
140
-
141
- return clientCallCtx ;
149
+ /**
150
+ * The updated context mixed into all evaluations based on the sync-metadata.
151
+ * @ return context
152
+ */
153
+ EvaluationContext getEnrichedContext () {
154
+ return enrichedContext ;
142
155
}
143
156
144
157
private boolean isConnected () {
@@ -149,6 +162,7 @@ private void onConnectionEvent(ConnectionEvent connectionEvent) {
149
162
boolean previous = connected ;
150
163
boolean current = connected = connectionEvent .isConnected ();
151
164
syncMetadata = connectionEvent .getSyncMetadata ();
165
+ enrichedContext = contextEnricher .apply (connectionEvent .getSyncMetadata ());
152
166
153
167
// configuration changed
154
168
if (initialized && previous && current ) {
0 commit comments