Skip to content

Commit 4a041b0

Browse files
authoredSep 25, 2024··
feat!: use sdk-maintained state, require 1.12 (#964)
Signed-off-by: Todd Baert <[email protected]>

File tree

25 files changed

+602
-957
lines changed

25 files changed

+602
-957
lines changed
 

Diff for: ‎hooks/open-telemetry/pom.xml

-7
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,6 @@
3838
</dependencyManagement>
3939

4040
<dependencies>
41-
<dependency>
42-
<groupId>dev.openfeature</groupId>
43-
<artifactId>sdk</artifactId>
44-
<version>[1.4,2.0)</version>
45-
<scope>provided</scope>
46-
</dependency>
47-
4841
<dependency>
4942
<groupId>io.opentelemetry</groupId>
5043
<artifactId>opentelemetry-semconv</artifactId>

Diff for: ‎pom.xml

+3-2
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,11 @@
6262
<dependencies>
6363
<dependency>
6464
<!-- provided -->
65+
<!-- this can be overriden in child POMs to support specific SDK requirements -->
6566
<groupId>dev.openfeature</groupId>
6667
<artifactId>sdk</artifactId>
67-
<!-- 1.0 <= v < 2.0 -->
68-
<version>[1.0,2.0)</version>
68+
<!-- 1.12 <= v < 2.0 -->
69+
<version>[1.12,2.0)</version>
6970
<!-- use the version provided at runtime -->
7071
<scope>provided</scope>
7172
</dependency>

Diff for: ‎providers/configcat/src/main/java/dev/openfeature/contrib/providers/configcat/ConfigCatProvider.java

+5-17
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,23 @@
11
package dev.openfeature.contrib.providers.configcat;
22

3+
import java.util.ArrayList;
4+
import java.util.concurrent.atomic.AtomicBoolean;
5+
36
import com.configcat.ConfigCatClient;
47
import com.configcat.EvaluationDetails;
58
import com.configcat.User;
9+
610
import dev.openfeature.sdk.EvaluationContext;
711
import dev.openfeature.sdk.EventProvider;
812
import dev.openfeature.sdk.Metadata;
913
import dev.openfeature.sdk.ProviderEvaluation;
1014
import dev.openfeature.sdk.ProviderEventDetails;
11-
import dev.openfeature.sdk.ProviderState;
1215
import dev.openfeature.sdk.Value;
1316
import dev.openfeature.sdk.exceptions.GeneralError;
14-
import dev.openfeature.sdk.exceptions.ProviderNotReadyError;
1517
import lombok.Getter;
1618
import lombok.SneakyThrows;
1719
import lombok.extern.slf4j.Slf4j;
1820

19-
import java.util.ArrayList;
20-
import java.util.concurrent.atomic.AtomicBoolean;
21-
2221
/**
2322
* Provider implementation for ConfigCat.
2423
*/
@@ -36,9 +35,6 @@ public class ConfigCatProvider extends EventProvider {
3635
@Getter
3736
private ConfigCatClient configCatClient;
3837

39-
@Getter
40-
private ProviderState state = ProviderState.NOT_READY;
41-
4238
private AtomicBoolean isInitialized = new AtomicBoolean(false);
4339

4440
/**
@@ -64,8 +60,7 @@ public void initialize(EvaluationContext evaluationContext) throws Exception {
6460
configCatClient = ConfigCatClient.get(configCatProviderConfig.getSdkKey(),
6561
configCatProviderConfig.getOptions());
6662
configCatProviderConfig.postInit();
67-
state = ProviderState.READY;
68-
log.info("finished initializing provider, state: {}", state);
63+
log.info("finished initializing provider");
6964

7065
configCatClient.getHooks().addOnClientReady(() -> {
7166
ProviderEventDetails providerEventDetails = ProviderEventDetails.builder()
@@ -123,12 +118,6 @@ public ProviderEvaluation<Value> getObjectEvaluation(String key, Value defaultVa
123118

124119
private <T> ProviderEvaluation<T> getEvaluation(Class<T> classOfT, String key, T defaultValue,
125120
EvaluationContext ctx) {
126-
if (!ProviderState.READY.equals(state)) {
127-
if (ProviderState.NOT_READY.equals(state)) {
128-
throw new ProviderNotReadyError(PROVIDER_NOT_YET_INITIALIZED);
129-
}
130-
throw new GeneralError(UNKNOWN_ERROR);
131-
}
132121
User user = ctx == null ? null : ContextTransformer.transform(ctx);
133122
EvaluationDetails<T> evaluationDetails;
134123
T evaluatedValue;
@@ -157,6 +146,5 @@ public void shutdown() {
157146
if (configCatClient != null) {
158147
configCatClient.close();
159148
}
160-
state = ProviderState.NOT_READY;
161149
}
162150
}

Diff for: ‎providers/configcat/src/test/java/dev/openfeature/contrib/providers/configcat/ConfigCatProviderTest.java

+10-32
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,26 @@
11
package dev.openfeature.contrib.providers.configcat;
22

3+
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
4+
import static org.junit.jupiter.api.Assertions.assertEquals;
5+
6+
import java.util.HashMap;
7+
8+
import org.junit.jupiter.api.AfterAll;
9+
import org.junit.jupiter.api.BeforeAll;
10+
import org.junit.jupiter.api.Test;
11+
312
import com.configcat.OverrideBehaviour;
413
import com.configcat.OverrideDataSourceBuilder;
514
import com.configcat.User;
15+
616
import dev.openfeature.sdk.Client;
717
import dev.openfeature.sdk.ImmutableContext;
818
import dev.openfeature.sdk.MutableContext;
919
import dev.openfeature.sdk.OpenFeatureAPI;
1020
import dev.openfeature.sdk.ProviderEventDetails;
1121
import dev.openfeature.sdk.Value;
12-
import dev.openfeature.sdk.exceptions.GeneralError;
13-
import dev.openfeature.sdk.exceptions.ProviderNotReadyError;
1422
import lombok.SneakyThrows;
1523
import lombok.extern.slf4j.Slf4j;
16-
import org.junit.jupiter.api.AfterAll;
17-
import org.junit.jupiter.api.BeforeAll;
18-
import org.junit.jupiter.api.Test;
19-
20-
import java.util.HashMap;
21-
22-
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
23-
import static org.junit.jupiter.api.Assertions.assertEquals;
24-
import static org.junit.jupiter.api.Assertions.assertThrows;
2524

2625
/**
2726
* ConfigCatProvider test, based on local config file evaluation.
@@ -181,27 +180,6 @@ void getStringEvaluationByUser() {
181180
assertEquals("fallback", client.getStringValue(USERS_FLAG_NAME + "Str", "111", evaluationContext));
182181
}
183182

184-
@SneakyThrows
185-
@Test
186-
void shouldThrowIfNotInitialized() {
187-
ConfigCatProviderConfig configCatProviderConfig = ConfigCatProviderConfig.builder().sdkKey("configcat-sdk-1/TEST_KEY-0123456789012/1234567890123456789012").build();
188-
ConfigCatProvider tempConfigCatProvider = new ConfigCatProvider(configCatProviderConfig);
189-
190-
assertThrows(ProviderNotReadyError.class, ()-> tempConfigCatProvider.getBooleanEvaluation("fail_not_initialized", false, new ImmutableContext()));
191-
192-
OpenFeatureAPI.getInstance().setProviderAndWait("tempConfigCatProvider", tempConfigCatProvider);
193-
194-
assertThrows(GeneralError.class, ()-> tempConfigCatProvider.initialize(null));
195-
196-
tempConfigCatProvider.shutdown();
197-
198-
assertThrows(ProviderNotReadyError.class, ()-> tempConfigCatProvider.getBooleanEvaluation("fail_not_initialized", false, new ImmutableContext()));
199-
assertThrows(ProviderNotReadyError.class, ()-> tempConfigCatProvider.getDoubleEvaluation("fail_not_initialized", 0.1, new ImmutableContext()));
200-
assertThrows(ProviderNotReadyError.class, ()-> tempConfigCatProvider.getIntegerEvaluation("fail_not_initialized", 3, new ImmutableContext()));
201-
assertThrows(ProviderNotReadyError.class, ()-> tempConfigCatProvider.getObjectEvaluation("fail_not_initialized", null, new ImmutableContext()));
202-
assertThrows(ProviderNotReadyError.class, ()-> tempConfigCatProvider.getStringEvaluation("fail_not_initialized", "", new ImmutableContext()));
203-
}
204-
205183
@Test
206184
void eventsTest() {
207185
configCatProvider.emitProviderReady(ProviderEventDetails.builder().build());

Diff for: ‎providers/flagd/pom.xml

-9
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,7 @@
3232
</developers>
3333

3434
<dependencies>
35-
3635
<!-- we inherent dev.openfeature.javasdk and the test dependencies from the parent pom -->
37-
<!-- override parent definition -->
38-
<dependency>
39-
<groupId>dev.openfeature</groupId>
40-
<artifactId>sdk</artifactId>
41-
<version>[1.4,2.0)</version>
42-
<scope>provided</scope>
43-
</dependency>
44-
4536
<dependency>
4637
<groupId>io.grpc</groupId>
4738
<artifactId>grpc-netty</artifactId>

Diff for: ‎providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/FlagdProvider.java

+23-57
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package dev.openfeature.contrib.providers.flagd;
22

3+
import java.util.List;
4+
35
import dev.openfeature.contrib.providers.flagd.resolver.Resolver;
46
import dev.openfeature.contrib.providers.flagd.resolver.grpc.GrpcResolver;
57
import dev.openfeature.contrib.providers.flagd.resolver.grpc.cache.Cache;
@@ -9,27 +11,19 @@
911
import dev.openfeature.sdk.Metadata;
1012
import dev.openfeature.sdk.ProviderEvaluation;
1113
import dev.openfeature.sdk.ProviderEventDetails;
12-
import dev.openfeature.sdk.ProviderState;
1314
import dev.openfeature.sdk.Value;
1415
import lombok.extern.slf4j.Slf4j;
1516

16-
import java.util.List;
17-
import java.util.concurrent.locks.Lock;
18-
import java.util.concurrent.locks.ReadWriteLock;
19-
import java.util.concurrent.locks.ReentrantReadWriteLock;
20-
2117
/**
2218
* OpenFeature provider for flagd.
2319
*/
2420
@Slf4j
25-
@SuppressWarnings({"PMD.TooManyStaticImports", "checkstyle:NoFinalizer"})
21+
@SuppressWarnings({ "PMD.TooManyStaticImports", "checkstyle:NoFinalizer" })
2622
public class FlagdProvider extends EventProvider {
2723
private static final String FLAGD_PROVIDER = "flagD Provider";
28-
29-
private final ReadWriteLock lock = new ReentrantReadWriteLock();
3024
private final Resolver flagResolver;
31-
private ProviderState state = ProviderState.NOT_READY;
32-
private boolean initialized = false;
25+
private volatile boolean initialized = false;
26+
private volatile boolean connected = false;
3327

3428
private EvaluationContext evaluationContext;
3529

@@ -52,14 +46,14 @@ public FlagdProvider() {
5246
public FlagdProvider(final FlagdOptions options) {
5347
switch (options.getResolverType().asString()) {
5448
case Config.RESOLVER_IN_PROCESS:
55-
this.flagResolver = new InProcessResolver(options, this::setState);
49+
this.flagResolver = new InProcessResolver(options, this::isConnected,
50+
this::onResolverConnectionChanged);
5651
break;
5752
case Config.RESOLVER_RPC:
58-
this.flagResolver =
59-
new GrpcResolver(options,
60-
new Cache(options.getCacheType(), options.getMaxCacheSize()),
61-
this::getState,
62-
this::setState);
53+
this.flagResolver = new GrpcResolver(options,
54+
new Cache(options.getCacheType(), options.getMaxCacheSize()),
55+
this::isConnected,
56+
this::onResolverConnectionChanged);
6357
break;
6458
default:
6559
throw new IllegalStateException(
@@ -86,24 +80,13 @@ public synchronized void shutdown() {
8680

8781
try {
8882
this.flagResolver.shutdown();
89-
this.initialized = false;
9083
} catch (Exception e) {
9184
log.error("Error during shutdown {}", FLAGD_PROVIDER, e);
92-
}
93-
}
94-
95-
@Override
96-
public ProviderState getState() {
97-
Lock l = this.lock.readLock();
98-
try {
99-
l.lock();
100-
return this.state;
10185
} finally {
102-
l.unlock();
86+
this.initialized = false;
10387
}
10488
}
10589

106-
10790
@Override
10891
public Metadata getMetadata() {
10992
return () -> FLAGD_PROVIDER;
@@ -142,49 +125,32 @@ private EvaluationContext mergeContext(final EvaluationContext clientCallCtx) {
142125
return clientCallCtx;
143126
}
144127

145-
private void setState(ProviderState newState, List<String> changedFlagsKeys) {
146-
ProviderState oldState;
147-
Lock l = this.lock.writeLock();
148-
try {
149-
l.lock();
150-
oldState = this.state;
151-
this.state = newState;
152-
} finally {
153-
l.unlock();
154-
}
155-
this.handleStateTransition(oldState, newState, changedFlagsKeys);
128+
private boolean isConnected() {
129+
return this.connected;
156130
}
157131

158-
private void handleStateTransition(ProviderState oldState, ProviderState newState, List<String> changedFlagKeys) {
159-
// we got initialized
160-
if (ProviderState.NOT_READY.equals(oldState) && ProviderState.READY.equals(newState)) {
161-
// nothing to do, the SDK emits the events
162-
log.debug("Init completed");
163-
return;
164-
}
165-
// we got shutdown, not checking oldState as behavior remains the same for shutdown
166-
if (ProviderState.NOT_READY.equals(newState)) {
167-
// nothing to do
168-
log.debug("shutdown completed");
169-
return;
170-
}
132+
private void onResolverConnectionChanged(boolean newConnectedState, List<String> changedFlagKeys) {
133+
boolean previous = connected;
134+
boolean current = newConnectedState;
135+
this.connected = newConnectedState;
136+
171137
// configuration changed
172-
if (ProviderState.READY.equals(oldState) && ProviderState.READY.equals(newState)) {
138+
if (initialized && previous && current) {
173139
log.debug("Configuration changed");
174140
ProviderEventDetails details = ProviderEventDetails.builder().flagsChanged(changedFlagKeys)
175141
.message("configuration changed").build();
176142
this.emitProviderConfigurationChanged(details);
177143
return;
178144
}
179145
// there was an error
180-
if (ProviderState.READY.equals(oldState) && ProviderState.ERROR.equals(newState)) {
146+
if (initialized && previous && !current) {
181147
log.debug("There has been an error");
182148
ProviderEventDetails details = ProviderEventDetails.builder().message("there has been an error").build();
183149
this.emitProviderError(details);
184150
return;
185151
}
186-
// we recover from an error
187-
if (ProviderState.ERROR.equals(oldState) && ProviderState.READY.equals(newState)) {
152+
// we recovered from an error
153+
if (initialized && !previous && current) {
188154
log.debug("Recovered from error");
189155
ProviderEventDetails details = ProviderEventDetails.builder().message("recovered from error").build();
190156
this.emitProviderReady(details);
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package dev.openfeature.contrib.providers.flagd.resolver.common;
22

3-
import java.util.concurrent.atomic.AtomicBoolean;
3+
import java.util.function.Supplier;
44

55
import dev.openfeature.sdk.exceptions.GeneralError;
66

@@ -14,20 +14,23 @@ private Util() {
1414

1515
/**
1616
* A helper to block the caller for given conditions.
17-
*
18-
* @param deadline number of milliseconds to block
19-
* @param check {@link AtomicBoolean} to check for status true
17+
*
18+
* @param deadline number of milliseconds to block
19+
* @param connectedSupplier func to check for status true
20+
* @throws InterruptedException if interrupted
2021
*/
21-
public static void busyWaitAndCheck(final Long deadline, final AtomicBoolean check) throws InterruptedException {
22+
public static void busyWaitAndCheck(final Long deadline, final Supplier<Boolean> connectedSupplier)
23+
throws InterruptedException {
2224
long start = System.currentTimeMillis();
2325

2426
do {
2527
if (deadline <= System.currentTimeMillis() - start) {
2628
throw new GeneralError(
27-
String.format("Deadline exceeded. Condition did not complete within the %d deadline", deadline));
29+
String.format("Deadline exceeded. Condition did not complete within the %d deadline",
30+
deadline));
2831
}
2932

3033
Thread.sleep(50L);
31-
} while (!check.get());
34+
} while (!connectedSupplier.get());
3235
}
3336
}

Diff for: ‎providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/resolver/grpc/EventStreamObserver.java

+13-13
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
11
package dev.openfeature.contrib.providers.flagd.resolver.grpc;
22

3+
import java.util.ArrayList;
4+
import java.util.Collections;
5+
import java.util.List;
6+
import java.util.Map;
7+
import java.util.function.BiConsumer;
8+
39
import com.google.protobuf.Value;
10+
411
import dev.openfeature.contrib.providers.flagd.resolver.grpc.cache.Cache;
512
import dev.openfeature.flagd.grpc.evaluation.Evaluation.EventStreamResponse;
6-
import dev.openfeature.sdk.ProviderState;
713
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
814
import io.grpc.stub.StreamObserver;
915
import lombok.extern.slf4j.Slf4j;
1016

11-
import java.util.ArrayList;
12-
import java.util.Collections;
13-
import java.util.List;
14-
import java.util.Map;
15-
import java.util.function.BiConsumer;
16-
1717
/**
1818
* EventStreamObserver handles events emitted by flagd.
1919
*/
2020
@Slf4j
2121
@SuppressFBWarnings(justification = "cache needs to be read and write by multiple objects")
2222
class EventStreamObserver implements StreamObserver<EventStreamResponse> {
23-
private final BiConsumer<ProviderState, List<String>> stateConsumer;
23+
private final BiConsumer<Boolean, List<String>> stateConsumer;
2424
private final Object sync;
2525
private final Cache cache;
2626

@@ -35,7 +35,7 @@ class EventStreamObserver implements StreamObserver<EventStreamResponse> {
3535
* @param cache cache to update
3636
* @param stateConsumer lambda to call for setting the state
3737
*/
38-
EventStreamObserver(Object sync, Cache cache, BiConsumer<ProviderState, List<String>> stateConsumer) {
38+
EventStreamObserver(Object sync, Cache cache, BiConsumer<Boolean, List<String>> stateConsumer) {
3939
this.sync = sync;
4040
this.cache = cache;
4141
this.stateConsumer = stateConsumer;
@@ -61,7 +61,7 @@ public void onError(Throwable t) {
6161
if (this.cache.getEnabled()) {
6262
this.cache.clear();
6363
}
64-
this.stateConsumer.accept(ProviderState.ERROR, Collections.emptyList());
64+
this.stateConsumer.accept(false, Collections.emptyList());
6565

6666
// handle last call of this stream
6767
handleEndOfStream();
@@ -72,7 +72,7 @@ public void onCompleted() {
7272
if (this.cache.getEnabled()) {
7373
this.cache.clear();
7474
}
75-
this.stateConsumer.accept(ProviderState.ERROR, Collections.emptyList());
75+
this.stateConsumer.accept(false, Collections.emptyList());
7676

7777
// handle last call of this stream
7878
handleEndOfStream();
@@ -99,11 +99,11 @@ private void handleConfigurationChangeEvent(EventStreamResponse value) {
9999
}
100100
}
101101

102-
this.stateConsumer.accept(ProviderState.READY, changedFlags);
102+
this.stateConsumer.accept(true, changedFlags);
103103
}
104104

105105
private void handleProviderReadyEvent() {
106-
this.stateConsumer.accept(ProviderState.READY, Collections.emptyList());
106+
this.stateConsumer.accept(true, Collections.emptyList());
107107
if (this.cache.getEnabled()) {
108108
this.cache.clear();
109109
}

Diff for: ‎providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/resolver/grpc/GrpcConnector.java

+14-18
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@
44
import java.util.List;
55
import java.util.Random;
66
import java.util.concurrent.TimeUnit;
7-
import java.util.concurrent.atomic.AtomicBoolean;
87
import java.util.function.BiConsumer;
8+
import java.util.function.Supplier;
9+
910
import dev.openfeature.contrib.providers.flagd.FlagdOptions;
1011
import dev.openfeature.contrib.providers.flagd.resolver.common.ChannelBuilder;
1112
import dev.openfeature.contrib.providers.flagd.resolver.common.Util;
1213
import dev.openfeature.contrib.providers.flagd.resolver.grpc.cache.Cache;
1314
import dev.openfeature.flagd.grpc.evaluation.Evaluation.EventStreamRequest;
1415
import dev.openfeature.flagd.grpc.evaluation.Evaluation.EventStreamResponse;
1516
import dev.openfeature.flagd.grpc.evaluation.ServiceGrpc;
16-
import dev.openfeature.sdk.ProviderState;
1717
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
1818
import io.grpc.ManagedChannel;
1919
import io.grpc.stub.StreamObserver;
@@ -26,7 +26,6 @@
2626
@SuppressFBWarnings(justification = "cache needs to be read and write by multiple objects")
2727
public class GrpcConnector {
2828
private final Object sync = new Object();
29-
private final AtomicBoolean connected = new AtomicBoolean(false);
3029
private final Random random = new Random();
3130

3231
private final ServiceGrpc.ServiceBlockingStub serviceBlockingStub;
@@ -38,7 +37,8 @@ public class GrpcConnector {
3837
private final long deadline;
3938

4039
private final Cache cache;
41-
private final BiConsumer<ProviderState, List<String>> stateConsumer;
40+
private final BiConsumer<Boolean, List<String>> stateConsumer;
41+
private final Supplier<Boolean> connectedSupplier;
4242

4343
private int eventStreamAttempt = 1;
4444
private int eventStreamRetryBackoff;
@@ -53,8 +53,8 @@ public class GrpcConnector {
5353
* @param cache cache to use.
5454
* @param stateConsumer lambda to call for setting the state.
5555
*/
56-
public GrpcConnector(final FlagdOptions options, final Cache cache,
57-
BiConsumer<ProviderState, List<String>> stateConsumer) {
56+
public GrpcConnector(final FlagdOptions options, final Cache cache, final Supplier<Boolean> connectedSupplier,
57+
BiConsumer<Boolean, List<String>> stateConsumer) {
5858
this.channel = ChannelBuilder.nettyChannel(options);
5959
this.serviceStub = ServiceGrpc.newStub(channel);
6060
this.serviceBlockingStub = ServiceGrpc.newBlockingStub(channel);
@@ -65,6 +65,7 @@ public GrpcConnector(final FlagdOptions options, final Cache cache,
6565
this.deadline = options.getDeadline();
6666
this.cache = cache;
6767
this.stateConsumer = stateConsumer;
68+
this.connectedSupplier = connectedSupplier;
6869
}
6970

7071
/**
@@ -76,7 +77,7 @@ public void initialize() throws Exception {
7677
eventObserverThread.start();
7778

7879
// block till ready
79-
Util.busyWaitAndCheck(this.deadline, this.connected);
80+
Util.busyWaitAndCheck(this.deadline, this.connectedSupplier);
8081
}
8182

8283
/**
@@ -103,7 +104,7 @@ public void shutdown() throws Exception {
103104
this.channel.awaitTermination(this.deadline, TimeUnit.MILLISECONDS);
104105
log.warn(String.format("Unable to shut down channel by %d deadline", this.deadline));
105106
}
106-
this.stateConsumer.accept(ProviderState.NOT_READY, Collections.emptyList());
107+
this.stateConsumer.accept(false, Collections.emptyList());
107108
}
108109
}
109110

@@ -154,21 +155,16 @@ private void observeEventStream() {
154155
}
155156

156157
log.error("failed to connect to event stream, exhausted retries");
157-
this.grpcStateConsumer(ProviderState.ERROR, null);
158+
this.grpcStateConsumer(false, null);
158159
}
159160

160-
private void grpcStateConsumer(final ProviderState state, final List<String> changedFlags) {
161-
// check for readiness
162-
if (ProviderState.READY.equals(state)) {
161+
private void grpcStateConsumer(final boolean connected, final List<String> changedFlags) {
162+
// reset reconnection states
163+
if (connected) {
163164
this.eventStreamAttempt = 1;
164165
this.eventStreamRetryBackoff = this.startEventStreamRetryBackoff;
165-
this.connected.set(true);
166-
} else if (ProviderState.ERROR.equals(state)) {
167-
// reset connection status
168-
this.connected.set(false);
169166
}
170-
171167
// chain to initiator
172-
this.stateConsumer.accept(state, changedFlags);
168+
this.stateConsumer.accept(connected, changedFlags);
173169
}
174170
}

Diff for: ‎providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/resolver/grpc/GrpcResolver.java

+9-11
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package dev.openfeature.contrib.providers.flagd.resolver.grpc;
22

3-
import dev.openfeature.contrib.providers.flagd.Config;
4-
53
import java.util.HashMap;
64
import java.util.List;
75
import java.util.Map;
@@ -16,6 +14,7 @@
1614
import com.google.protobuf.NullValue;
1715
import com.google.protobuf.Struct;
1816

17+
import dev.openfeature.contrib.providers.flagd.Config;
1918
import dev.openfeature.contrib.providers.flagd.FlagdOptions;
2019
import dev.openfeature.contrib.providers.flagd.resolver.Resolver;
2120
import dev.openfeature.contrib.providers.flagd.resolver.grpc.cache.Cache;
@@ -30,7 +29,6 @@
3029
import dev.openfeature.sdk.ImmutableMetadata;
3130
import dev.openfeature.sdk.MutableStructure;
3231
import dev.openfeature.sdk.ProviderEvaluation;
33-
import dev.openfeature.sdk.ProviderState;
3432
import dev.openfeature.sdk.Value;
3533
import dev.openfeature.sdk.exceptions.FlagNotFoundError;
3634
import dev.openfeature.sdk.exceptions.GeneralError;
@@ -51,23 +49,23 @@ public final class GrpcResolver implements Resolver {
5149
private final GrpcConnector connector;
5250
private final Cache cache;
5351
private final ResolveStrategy strategy;
54-
private final Supplier<ProviderState> stateSupplier;
52+
private final Supplier<Boolean> connectedSupplier;
5553

5654
/**
5755
* Initialize Grpc resolver.
5856
*
5957
* @param options flagd options.
6058
* @param cache cache to use.
61-
* @param stateSupplier lambda to call for getting the state.
62-
* @param stateConsumer lambda to communicate back the state.
59+
* @param connectedSupplier lambda to call for getting the state.
60+
* @param onResolverConnectionChanged lambda to communicate back the state.
6361
*/
64-
public GrpcResolver(final FlagdOptions options, final Cache cache, final Supplier<ProviderState> stateSupplier,
65-
final BiConsumer<ProviderState,List<String>> stateConsumer) {
62+
public GrpcResolver(final FlagdOptions options, final Cache cache, final Supplier<Boolean> connectedSupplier,
63+
final BiConsumer<Boolean, List<String>> onResolverConnectionChanged) {
6664
this.cache = cache;
67-
this.stateSupplier = stateSupplier;
65+
this.connectedSupplier = connectedSupplier;
6866

6967
this.strategy = ResolveFactory.getStrategy(options);
70-
this.connector = new GrpcConnector(options, cache, stateConsumer);
68+
this.connector = new GrpcConnector(options, cache, connectedSupplier, onResolverConnectionChanged);
7169
}
7270

7371
/**
@@ -199,7 +197,7 @@ private <T> Boolean isEvaluationCacheable(ProviderEvaluation<T> evaluation) {
199197
}
200198

201199
private Boolean cacheAvailable() {
202-
return this.cache.getEnabled() && ProviderState.READY.equals(this.stateSupplier.get());
200+
return this.cache.getEnabled() && this.connectedSupplier.get();
203201
}
204202

205203
/**

Diff for: ‎providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/resolver/process/InProcessResolver.java

+22-23
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
package dev.openfeature.contrib.providers.flagd.resolver.process;
22

3+
import static dev.openfeature.contrib.providers.flagd.resolver.process.model.FeatureFlag.EMPTY_TARGETING_STRING;
4+
5+
import java.util.List;
6+
import java.util.function.BiConsumer;
7+
import java.util.function.Supplier;
8+
39
import dev.openfeature.contrib.providers.flagd.FlagdOptions;
410
import dev.openfeature.contrib.providers.flagd.resolver.Resolver;
511
import dev.openfeature.contrib.providers.flagd.resolver.common.Util;
@@ -16,19 +22,12 @@
1622
import dev.openfeature.sdk.EvaluationContext;
1723
import dev.openfeature.sdk.ImmutableMetadata;
1824
import dev.openfeature.sdk.ProviderEvaluation;
19-
import dev.openfeature.sdk.ProviderState;
2025
import dev.openfeature.sdk.Reason;
2126
import dev.openfeature.sdk.Value;
2227
import dev.openfeature.sdk.exceptions.ParseError;
2328
import dev.openfeature.sdk.exceptions.TypeMismatchError;
2429
import lombok.extern.slf4j.Slf4j;
2530

26-
import java.util.List;
27-
import java.util.concurrent.atomic.AtomicBoolean;
28-
import java.util.function.BiConsumer;
29-
30-
import static dev.openfeature.contrib.providers.flagd.resolver.process.model.FeatureFlag.EMPTY_TARGETING_STRING;
31-
3231
/**
3332
* flagd in-process resolver. Resolves feature flags in-process. Flags are
3433
* retrieved from {@link Storage}, where the
@@ -37,20 +36,25 @@
3736
@Slf4j
3837
public class InProcessResolver implements Resolver {
3938
private final Storage flagStore;
40-
private final BiConsumer<ProviderState, List<String>> stateConsumer;
39+
private final BiConsumer<Boolean, List<String>> onResolverConnectionChanged;
4140
private final Operator operator;
4241
private final long deadline;
4342
private final ImmutableMetadata metadata;
44-
private final AtomicBoolean connected = new AtomicBoolean(false);
43+
private final Supplier<Boolean> connectedSupplier;
4544

4645
/**
4746
* Initialize an in-process resolver.
47+
* @param options flagd options
48+
* @param connectedSupplier supplier for connection state
49+
* @param onResolverConnectionChanged handler for connection change
4850
*/
49-
public InProcessResolver(FlagdOptions options, BiConsumer<ProviderState, List<String>> stateConsumer) {
51+
public InProcessResolver(FlagdOptions options, final Supplier<Boolean> connectedSupplier,
52+
BiConsumer<Boolean, List<String>> onResolverConnectionChanged) {
5053
this.flagStore = new FlagStore(getConnector(options));
5154
this.deadline = options.getDeadline();
52-
this.stateConsumer = stateConsumer;
55+
this.onResolverConnectionChanged = onResolverConnectionChanged;
5356
this.operator = new Operator();
57+
this.connectedSupplier = connectedSupplier;
5458
this.metadata = options.getSelector() == null ? null
5559
: ImmutableMetadata.builder()
5660
.addString("scope", options.getSelector())
@@ -68,15 +72,11 @@ public void init() throws Exception {
6872
final StorageStateChange storageStateChange = flagStore.getStateQueue().take();
6973
switch (storageStateChange.getStorageState()) {
7074
case OK:
71-
stateConsumer.accept(ProviderState.READY, storageStateChange.getChangedFlagsKeys());
72-
this.connected.set(true);
75+
onResolverConnectionChanged.accept(true, storageStateChange.getChangedFlagsKeys());
7376
break;
7477
case ERROR:
75-
stateConsumer.accept(ProviderState.ERROR, null);
76-
this.connected.set(false);
78+
onResolverConnectionChanged.accept(false, null);
7779
break;
78-
case STALE:
79-
// todo set stale state
8080
default:
8181
log.info(String.format("Storage emitted unhandled status: %s",
8282
storageStateChange.getStorageState()));
@@ -91,7 +91,7 @@ public void init() throws Exception {
9191
stateWatcher.start();
9292

9393
// block till ready
94-
Util.busyWaitAndCheck(this.deadline, this.connected);
94+
Util.busyWaitAndCheck(this.deadline, this.connectedSupplier);
9595
}
9696

9797
/**
@@ -101,8 +101,7 @@ public void init() throws Exception {
101101
*/
102102
public void shutdown() throws InterruptedException {
103103
flagStore.shutdown();
104-
this.connected.set(false);
105-
stateConsumer.accept(ProviderState.NOT_READY, null);
104+
onResolverConnectionChanged.accept(false, null);
106105
}
107106

108107
/**
@@ -165,9 +164,9 @@ private <T> ProviderEvaluation<T> resolve(Class<T> type, String key, EvaluationC
165164
// missing flag
166165
if (flag == null) {
167166
return ProviderEvaluation.<T>builder()
168-
.errorMessage("flag: " + key + " not found")
169-
.errorCode(ErrorCode.FLAG_NOT_FOUND)
170-
.build();
167+
.errorMessage("flag: " + key + " not found")
168+
.errorCode(ErrorCode.FLAG_NOT_FOUND)
169+
.build();
171170
}
172171

173172
// state check

Diff for: ‎providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/FlagdProviderTest.java

+82-109
Large diffs are not rendered by default.

Diff for: ‎providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/resolver/grpc/EventStreamObserverTest.java

+11-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package dev.openfeature.contrib.providers.flagd.resolver.grpc;
22

3+
import static org.junit.Assert.assertFalse;
4+
import static org.junit.Assert.assertTrue;
35
import static org.junit.jupiter.api.Assertions.assertEquals;
46
import static org.mockito.ArgumentMatchers.eq;
57
import static org.mockito.Mockito.atLeast;
@@ -22,15 +24,14 @@
2224

2325
import dev.openfeature.contrib.providers.flagd.resolver.grpc.cache.Cache;
2426
import dev.openfeature.flagd.grpc.evaluation.Evaluation.EventStreamResponse;
25-
import dev.openfeature.sdk.ProviderState;
2627

2728
class EventStreamObserverTest {
2829

2930
@Nested
3031
class StateChange {
3132

3233
Cache cache;
33-
List<ProviderState> states;
34+
List<Boolean> states;
3435
EventStreamObserver stream;
3536
Runnable reconnect;
3637
Object sync;
@@ -46,7 +47,7 @@ void setUp() {
4647
}
4748

4849
@Test
49-
public void Change() {
50+
public void change() {
5051
EventStreamResponse resp = mock(EventStreamResponse.class);
5152
Struct flagData = mock(Struct.class);
5253
when(resp.getType()).thenReturn("configuration_change");
@@ -55,35 +56,35 @@ public void Change() {
5556
stream.onNext(resp);
5657
// we notify that we are ready
5758
assertEquals(1, states.size());
58-
assertEquals(ProviderState.READY, states.get(0));
59+
assertTrue(states.get(0));
5960
// we flush the cache
6061
verify(cache, atLeast(1)).clear();
6162
}
6263

6364
@Test
64-
public void Ready() {
65+
public void ready() {
6566
EventStreamResponse resp = mock(EventStreamResponse.class);
6667
when(resp.getType()).thenReturn("provider_ready");
6768
stream.onNext(resp);
6869
// we notify that we are ready
6970
assertEquals(1, states.size());
70-
assertEquals(ProviderState.READY, states.get(0));
71+
assertTrue(states.get(0));
7172
// cache was cleaned
7273
verify(cache, atLeast(1)).clear();
7374
}
7475

7576
@Test
76-
public void Reconnections() {
77+
public void reconnections() {
7778
stream.onError(new Throwable("error"));
7879
// we flush the cache
7980
verify(cache, atLeast(1)).clear();
8081
// we notify the error
8182
assertEquals(1, states.size());
82-
assertEquals(ProviderState.ERROR, states.get(0));
83+
assertFalse(states.get(0));
8384
}
8485

8586
@Test
86-
public void CacheBustingForKnownKeys() {
87+
public void cacheBustingForKnownKeys() {
8788
final String key1 = "myKey1";
8889
final String key2 = "myKey2";
8990

@@ -106,7 +107,7 @@ public void CacheBustingForKnownKeys() {
106107
stream.onNext(resp);
107108
// we notify that the configuration changed
108109
assertEquals(1, states.size());
109-
assertEquals(ProviderState.READY, states.get(0));
110+
assertTrue(states.get(0));
110111
// we did NOT flush the whole cache
111112
verify(cache, atMost(0)).clear();
112113
// we only clean the two keys

Diff for: ‎providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/resolver/grpc/GrpcConnectorTest.java

+9-22
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ void validate_retry_calls(int retries) throws NoSuchFieldException, IllegalAcces
5858
final ServiceGrpc.ServiceStub mockStub = mock(ServiceGrpc.ServiceStub.class);
5959
doAnswer(invocation -> null).when(mockStub).eventStream(any(), any());
6060

61-
final GrpcConnector connector = new GrpcConnector(options, cache, (state,changedFlagKeys) -> {
61+
final GrpcConnector connector = new GrpcConnector(options, cache, () -> true, (state,changedFlagKeys) -> {
6262
});
6363

6464
Field serviceStubField = GrpcConnector.class.getDeclaredField("serviceStub");
@@ -94,20 +94,10 @@ void initialization_succeed_with_connected_status() throws NoSuchFieldException,
9494
final ServiceGrpc.ServiceStub mockStub = mock(ServiceGrpc.ServiceStub.class);
9595
doAnswer(invocation -> null).when(mockStub).eventStream(any(), any());
9696

97-
final GrpcConnector connector = new GrpcConnector(FlagdOptions.builder().build(), cache, (state,changedFlagKeys) -> {
97+
// pass true in connected lambda
98+
final GrpcConnector connector = new GrpcConnector(FlagdOptions.builder().build(), cache, () -> true, (state, changedFlagKeys) -> {
9899
});
99100

100-
Field serviceStubField = GrpcConnector.class.getDeclaredField("serviceStub");
101-
serviceStubField.setAccessible(true);
102-
serviceStubField.set(connector, mockStub);
103-
104-
// override default connected state variable
105-
final AtomicBoolean connected = new AtomicBoolean(true);
106-
107-
Field syncField = GrpcConnector.class.getDeclaredField("connected");
108-
syncField.setAccessible(true);
109-
syncField.set(connector, connected);
110-
111101
assertDoesNotThrow(connector::initialize);
112102
}
113103

@@ -118,13 +108,10 @@ void initialization_fail_with_timeout() throws Exception {
118108
final ServiceGrpc.ServiceStub mockStub = mock(ServiceGrpc.ServiceStub.class);
119109
doAnswer(invocation -> null).when(mockStub).eventStream(any(), any());
120110

121-
final GrpcConnector connector = new GrpcConnector(FlagdOptions.builder().build(), cache, (state,changedFlagKeys) -> {
111+
// pass false in connected lambda
112+
final GrpcConnector connector = new GrpcConnector(FlagdOptions.builder().build(), cache, () -> false, (state, changedFlagKeys) -> {
122113
});
123114

124-
Field serviceStubField = GrpcConnector.class.getDeclaredField("serviceStub");
125-
serviceStubField.setAccessible(true);
126-
serviceStubField.set(connector, mockStub);
127-
128115
assertThrows(RuntimeException.class, connector::initialize);
129116
}
130117

@@ -149,7 +136,7 @@ void host_and_port_arg_should_build_tcp_socket() {
149136
.forAddress(anyString(), anyInt())).thenReturn(mockChannelBuilder);
150137

151138
final FlagdOptions flagdOptions = FlagdOptions.builder().host(host).port(port).tls(false).build();
152-
new GrpcConnector(flagdOptions, null, null);
139+
new GrpcConnector(flagdOptions, null, null, null);
153140

154141
// verify host/port matches
155142
mockStaticChannelBuilder.verify(() -> NettyChannelBuilder
@@ -180,7 +167,7 @@ void no_args_host_and_port_env_set_should_build_tcp_socket() throws Exception {
180167
mockStaticChannelBuilder.when(() -> NettyChannelBuilder
181168
.forAddress(anyString(), anyInt())).thenReturn(mockChannelBuilder);
182169

183-
new GrpcConnector(FlagdOptions.builder().build(), null, null);
170+
new GrpcConnector(FlagdOptions.builder().build(), null, null, null);
184171

185172
// verify host/port matches & called times(= 1 as we rely on reusable channel)
186173
mockStaticChannelBuilder.verify(() -> NettyChannelBuilder.
@@ -217,7 +204,7 @@ void path_arg_should_build_domain_socket_with_correct_path() {
217204
})) {
218205
when(NettyChannelBuilder.forAddress(any(DomainSocketAddress.class))).thenReturn(mockChannelBuilder);
219206

220-
new GrpcConnector(FlagdOptions.builder().socketPath(path).build(), null, null);
207+
new GrpcConnector(FlagdOptions.builder().socketPath(path).build(), null, null, null);
221208

222209
// verify path matches
223210
mockStaticChannelBuilder.verify(() -> NettyChannelBuilder
@@ -260,7 +247,7 @@ void no_args_socket_env_should_build_domain_socket_with_correct_path() throws Ex
260247
mockStaticChannelBuilder.when(() -> NettyChannelBuilder
261248
.forAddress(any(DomainSocketAddress.class))).thenReturn(mockChannelBuilder);
262249

263-
new GrpcConnector(FlagdOptions.builder().build(), null, null);
250+
new GrpcConnector(FlagdOptions.builder().build(), null, null, null);
264251

265252
//verify path matches & called times(= 1 as we rely on reusable channel)
266253
mockStaticChannelBuilder.verify(() -> NettyChannelBuilder

Diff for: ‎providers/flagd/src/test/java/dev/openfeature/contrib/providers/flagd/resolver/process/InProcessResolverTest.java

+331-322
Large diffs are not rendered by default.

Diff for: ‎providers/flipt/src/main/java/dev/openfeature/contrib/providers/flipt/FliptProvider.java

+7-41
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
package dev.openfeature.contrib.providers.flipt;
22

3+
import static dev.openfeature.sdk.Reason.DEFAULT;
4+
import static dev.openfeature.sdk.Reason.TARGETING_MATCH;
5+
6+
import java.util.Map;
7+
import java.util.concurrent.atomic.AtomicBoolean;
8+
39
import dev.openfeature.sdk.EvaluationContext;
410
import dev.openfeature.sdk.EventProvider;
511
import dev.openfeature.sdk.ImmutableMetadata;
612
import dev.openfeature.sdk.Metadata;
713
import dev.openfeature.sdk.ProviderEvaluation;
8-
import dev.openfeature.sdk.ProviderEventDetails;
9-
import dev.openfeature.sdk.ProviderState;
1014
import dev.openfeature.sdk.Value;
1115
import dev.openfeature.sdk.exceptions.GeneralError;
12-
import dev.openfeature.sdk.exceptions.ProviderNotReadyError;
1316
import io.flipt.api.FliptClient;
1417
import io.flipt.api.evaluation.models.BooleanEvaluationResponse;
1518
import io.flipt.api.evaluation.models.EvaluationRequest;
@@ -19,12 +22,6 @@
1922
import lombok.Setter;
2023
import lombok.extern.slf4j.Slf4j;
2124

22-
import java.util.Map;
23-
import java.util.concurrent.atomic.AtomicBoolean;
24-
25-
import static dev.openfeature.sdk.Reason.DEFAULT;
26-
import static dev.openfeature.sdk.Reason.TARGETING_MATCH;
27-
2825
/**
2926
* Provider implementation for Flipt.
3027
*/
@@ -43,10 +40,6 @@ public class FliptProvider extends EventProvider {
4340
@Getter
4441
private FliptClient fliptClient;
4542

46-
@Setter(AccessLevel.PROTECTED)
47-
@Getter
48-
private ProviderState state = ProviderState.NOT_READY;
49-
5043
private AtomicBoolean isInitialized = new AtomicBoolean(false);
5144

5245
/**
@@ -73,36 +66,16 @@ public void initialize(EvaluationContext evaluationContext) throws Exception {
7366
super.initialize(evaluationContext);
7467
fliptClient = fliptProviderConfig.getFliptClientBuilder().build();
7568

76-
state = ProviderState.READY;
77-
log.info("finished initializing provider, state: {}", state);
69+
log.info("finished initializing provider");
7870
}
7971

8072
@Override
8173
public Metadata getMetadata() {
8274
return () -> NAME;
8375
}
8476

85-
@Override
86-
public void emitProviderReady(ProviderEventDetails details) {
87-
super.emitProviderReady(details);
88-
state = ProviderState.READY;
89-
}
90-
91-
@Override
92-
public void emitProviderError(ProviderEventDetails details) {
93-
super.emitProviderError(details);
94-
state = ProviderState.ERROR;
95-
}
96-
9777
@Override
9878
public ProviderEvaluation<Boolean> getBooleanEvaluation(String key, Boolean defaultValue, EvaluationContext ctx) {
99-
if (!ProviderState.READY.equals(state)) {
100-
if (ProviderState.NOT_READY.equals(state)) {
101-
throw new ProviderNotReadyError(PROVIDER_NOT_YET_INITIALIZED);
102-
}
103-
throw new GeneralError(UNKNOWN_ERROR);
104-
}
105-
10679
Map<String, String> contextMap = ContextTransformer.transform(ctx);
10780
EvaluationRequest request = EvaluationRequest.builder().namespaceKey(fliptProviderConfig.getNamespace())
10881
.flagKey(key).entityId(ctx.getTargetingKey()).context(contextMap).build();
@@ -179,12 +152,6 @@ private static Double getDoubleValue(ProviderEvaluation<Value> valueProviderEval
179152

180153
@Override
181154
public ProviderEvaluation<Value> getObjectEvaluation(String key, Value defaultValue, EvaluationContext ctx) {
182-
if (!ProviderState.READY.equals(state)) {
183-
if (ProviderState.NOT_READY.equals(state)) {
184-
throw new ProviderNotReadyError(PROVIDER_NOT_YET_INITIALIZED);
185-
}
186-
throw new GeneralError(UNKNOWN_ERROR);
187-
}
188155
Map<String, String> contextMap = ContextTransformer.transform(ctx);
189156
EvaluationRequest request = EvaluationRequest.builder().namespaceKey(fliptProviderConfig.getNamespace())
190157
.flagKey(key).entityId(ctx.getTargetingKey()).context(contextMap).build();
@@ -222,6 +189,5 @@ public ProviderEvaluation<Value> getObjectEvaluation(String key, Value defaultVa
222189
public void shutdown() {
223190
super.shutdown();
224191
log.info("shutdown");
225-
state = ProviderState.NOT_READY;
226192
}
227193
}

Diff for: ‎providers/flipt/src/test/java/dev/openfeature/contrib/providers/flipt/FliptProviderTest.java

-36
Original file line numberDiff line numberDiff line change
@@ -173,40 +173,4 @@ void getEvaluationMetadataTest() {
173173
evaluationContext);
174174
assertEquals(null, nonExistingFlagEvaluation.getFlagMetadata().getBoolean("variant-attachment"));
175175
}
176-
177-
@SneakyThrows
178-
@Test
179-
void shouldThrowIfNotInitialized() {
180-
FliptProvider asyncInitfliptProvider = buildFliptProvider();
181-
assertEquals(ProviderState.NOT_READY, asyncInitfliptProvider.getState());
182-
183-
// ErrorCode.PROVIDER_NOT_READY should be returned when evaluated via the client
184-
assertThrows(ProviderNotReadyError.class, () -> asyncInitfliptProvider
185-
.getBooleanEvaluation("fail_not_initialized", false, new ImmutableContext()));
186-
assertThrows(ProviderNotReadyError.class,
187-
() -> asyncInitfliptProvider.getStringEvaluation("fail_not_initialized", "", new ImmutableContext()));
188-
189-
asyncInitfliptProvider.initialize(null);
190-
assertThrows(GeneralError.class, () -> asyncInitfliptProvider.initialize(null));
191-
192-
asyncInitfliptProvider.shutdown();
193-
}
194-
195-
@SneakyThrows
196-
@Test
197-
void shouldThrowIfErrorEvent() {
198-
FliptProvider asyncInitfliptProvider = buildFliptProvider();
199-
asyncInitfliptProvider.initialize(new ImmutableContext());
200-
201-
asyncInitfliptProvider.emitProviderError(ProviderEventDetails.builder().build());
202-
203-
// ErrorCode.PROVIDER_NOT_READY should be returned when evaluated via the client
204-
assertThrows(GeneralError.class,
205-
() -> asyncInitfliptProvider.getBooleanEvaluation("fail", false, new ImmutableContext()));
206-
assertThrows(GeneralError.class,
207-
() -> asyncInitfliptProvider.getStringEvaluation("fail", "", new ImmutableContext()));
208-
209-
asyncInitfliptProvider.shutdown();
210-
}
211-
212176
}

Diff for: ‎providers/go-feature-flag/src/main/java/dev/openfeature/contrib/providers/gofeatureflag/GoFeatureFlagProvider.java

+8-28
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
package dev.openfeature.contrib.providers.gofeatureflag;
22

3+
import java.util.ArrayList;
4+
import java.util.List;
5+
import java.util.concurrent.TimeUnit;
6+
7+
import org.jetbrains.annotations.NotNull;
8+
39
import com.fasterxml.jackson.core.JsonProcessingException;
10+
411
import dev.openfeature.contrib.providers.gofeatureflag.bean.ConfigurationChange;
512
import dev.openfeature.contrib.providers.gofeatureflag.controller.CacheController;
613
import dev.openfeature.contrib.providers.gofeatureflag.controller.GoFeatureFlagController;
@@ -16,22 +23,14 @@
1623
import dev.openfeature.sdk.Metadata;
1724
import dev.openfeature.sdk.ProviderEvaluation;
1825
import dev.openfeature.sdk.ProviderEventDetails;
19-
import dev.openfeature.sdk.ProviderState;
2026
import dev.openfeature.sdk.Reason;
2127
import dev.openfeature.sdk.Value;
22-
import dev.openfeature.sdk.exceptions.GeneralError;
23-
import dev.openfeature.sdk.exceptions.ProviderNotReadyError;
2428
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
2529
import io.reactivex.rxjava3.core.Observable;
2630
import io.reactivex.rxjava3.disposables.Disposable;
2731
import io.reactivex.rxjava3.schedulers.Schedulers;
2832
import io.reactivex.rxjava3.subjects.PublishSubject;
2933
import lombok.extern.slf4j.Slf4j;
30-
import org.jetbrains.annotations.NotNull;
31-
32-
import java.util.ArrayList;
33-
import java.util.List;
34-
import java.util.concurrent.TimeUnit;
3534

3635
/**
3736
* GoFeatureFlagProvider is the JAVA provider implementation for the feature flag solution GO Feature Flag.
@@ -46,7 +45,6 @@ public class GoFeatureFlagProvider extends EventProvider {
4645
private final GoFeatureFlagProviderOptions options;
4746
private final List<Hook> hooks = new ArrayList<>();
4847
private DataCollectorHook dataCollectorHook;
49-
private ProviderState state = ProviderState.NOT_READY;
5048
private Disposable flagChangeDisposable;
5149
private GoFeatureFlagController gofeatureflagController;
5250
private CacheController cacheCtrl;
@@ -127,9 +125,8 @@ public void initialize(EvaluationContext evaluationContext) throws Exception {
127125
this.flagChangeDisposable =
128126
this.startCheckFlagConfigurationChangesDaemon();
129127
}
130-
state = ProviderState.READY;
131128
super.emitProviderReady(ProviderEventDetails.builder().message("Provider is ready to call the API").build());
132-
log.info("finishing initializing provider, state: {}", state);
129+
log.info("finishing initializing provider");
133130
}
134131

135132

@@ -175,11 +172,6 @@ private Disposable startCheckFlagConfigurationChangesDaemon() {
175172
);
176173
}
177174

178-
@Override
179-
public ProviderState getState() {
180-
return state;
181-
}
182-
183175
/**
184176
* getEvaluation is the function resolving the flag, it will 1st check in the cache and if it is not available
185177
* will call the evaluation endpoint to get the value of the flag.
@@ -195,18 +187,6 @@ public ProviderState getState() {
195187
private <T> ProviderEvaluation<T> getEvaluation(
196188
String key, T defaultValue, EvaluationContext evaluationContext, Class<?> expectedType) {
197189
try {
198-
if (!ProviderState.READY.equals(state)) {
199-
if (ProviderState.NOT_READY.equals(state)) {
200-
201-
/*
202-
should be handled by the SDK framework, ErrorCode.PROVIDER_NOT_READY and default value
203-
should be returned when evaluated via the client.
204-
*/
205-
throw new ProviderNotReadyError("provider not initialized yet");
206-
}
207-
throw new GeneralError("unknown error, provider state: " + state);
208-
}
209-
210190
if (this.cacheCtrl == null) {
211191
return this.gofeatureflagController
212192
.evaluateFlag(key, defaultValue, evaluationContext, expectedType)

Diff for: ‎providers/go-feature-flag/src/test/java/dev/openfeature/contrib/providers/gofeatureflag/GoFeatureFlagProviderTest.java

-27
Original file line numberDiff line numberDiff line change
@@ -180,33 +180,6 @@ void constructor_options_valid_endpoint() {
180180
assertDoesNotThrow(() -> new GoFeatureFlagProvider(GoFeatureFlagProviderOptions.builder().endpoint("http://localhost:1031").build()));
181181
}
182182

183-
@SneakyThrows
184-
@Test
185-
void should_return_not_ready_if_not_initialized() {
186-
GoFeatureFlagProvider g = new GoFeatureFlagProvider(GoFeatureFlagProviderOptions.builder().endpoint(this.baseUrl.toString()).timeout(1000).build()) {
187-
@Override
188-
public void initialize(EvaluationContext evaluationContext) throws Exception {
189-
190-
// make the provider not initialized for this test
191-
Thread.sleep(3000);
192-
}
193-
};
194-
195-
/*
196-
ErrorCode.PROVIDER_NOT_READY and default value should be returned when evaluated via the client,
197-
see next step in this test.
198-
*/
199-
assertThrows(ProviderNotReadyError.class, () -> g.getBooleanEvaluation("bool_targeting_match", false, this.evaluationContext));
200-
201-
String providerName = "shouldReturnNotReadyIfNotInitialized";
202-
OpenFeatureAPI.getInstance().setProviderAndWait(providerName, g);
203-
assertThat(OpenFeatureAPI.getInstance().getProvider(providerName).getState()).isEqualTo(ProviderState.NOT_READY);
204-
Client client = OpenFeatureAPI.getInstance().getClient(providerName);
205-
FlagEvaluationDetails<Boolean> booleanFlagEvaluationDetails = client.getBooleanDetails("return_error_when_not_initialized", false, new ImmutableContext("targetingKey"));
206-
assertEquals(ErrorCode.PROVIDER_NOT_READY, booleanFlagEvaluationDetails.getErrorCode());
207-
assertEquals(Boolean.FALSE, booleanFlagEvaluationDetails.getValue());
208-
}
209-
210183
@SneakyThrows
211184
@Test
212185
void client_test() {

Diff for: ‎providers/statsig/src/main/java/dev/openfeature/contrib/providers/statsig/StatsigProvider.java

+8-47
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,30 @@
11
package dev.openfeature.contrib.providers.statsig;
22

3+
import java.util.ArrayList;
4+
import java.util.List;
5+
import java.util.concurrent.Future;
6+
7+
import org.jetbrains.annotations.NotNull;
8+
39
import com.statsig.sdk.APIFeatureGate;
410
import com.statsig.sdk.DynamicConfig;
511
import com.statsig.sdk.EvaluationReason;
612
import com.statsig.sdk.Layer;
713
import com.statsig.sdk.Statsig;
814
import com.statsig.sdk.StatsigUser;
15+
916
import dev.openfeature.sdk.EvaluationContext;
1017
import dev.openfeature.sdk.EventProvider;
1118
import dev.openfeature.sdk.Metadata;
1219
import dev.openfeature.sdk.MutableContext;
1320
import dev.openfeature.sdk.ProviderEvaluation;
14-
import dev.openfeature.sdk.ProviderState;
1521
import dev.openfeature.sdk.Structure;
1622
import dev.openfeature.sdk.Value;
17-
import dev.openfeature.sdk.exceptions.GeneralError;
18-
import dev.openfeature.sdk.exceptions.ProviderNotReadyError;
1923
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
2024
import lombok.AllArgsConstructor;
2125
import lombok.Getter;
2226
import lombok.SneakyThrows;
2327
import lombok.extern.slf4j.Slf4j;
24-
import org.jetbrains.annotations.NotNull;
25-
26-
import java.util.ArrayList;
27-
import java.util.List;
28-
import java.util.concurrent.Future;
29-
import java.util.concurrent.atomic.AtomicBoolean;
3028

3129
/**
3230
* Provider implementation for Statsig.
@@ -36,18 +34,9 @@ public class StatsigProvider extends EventProvider {
3634

3735
@Getter
3836
private static final String NAME = "Statsig";
39-
40-
private static final String PROVIDER_NOT_YET_INITIALIZED = "provider not yet initialized";
41-
private static final String UNKNOWN_ERROR = "unknown error";
4237
private static final String FEATURE_CONFIG_KEY = "feature_config";
43-
4438
private final StatsigProviderConfig statsigProviderConfig;
4539

46-
@Getter
47-
private ProviderState state = ProviderState.NOT_READY;
48-
49-
private final AtomicBoolean isInitialized = new AtomicBoolean(false);
50-
5140
/**
5241
* Constructor.
5342
* @param statsigProviderConfig StatsigProvider Config
@@ -63,19 +52,12 @@ public StatsigProvider(StatsigProviderConfig statsigProviderConfig) {
6352
*/
6453
@Override
6554
public void initialize(EvaluationContext evaluationContext) throws Exception {
66-
boolean initialized = isInitialized.getAndSet(true);
67-
if (initialized && ProviderState.READY.equals(state)) {
68-
log.debug("already initialized");
69-
return;
70-
}
71-
7255
Future<Void> initFuture = Statsig.initializeAsync(statsigProviderConfig.getSdkKey(),
7356
statsigProviderConfig.getOptions());
7457
initFuture.get();
7558

7659
statsigProviderConfig.postInit();
77-
state = ProviderState.READY;
78-
log.info("finished initializing provider, state: {}", state);
60+
log.info("finished initializing provider");
7961
}
8062

8163
@Override
@@ -87,7 +69,6 @@ public Metadata getMetadata() {
8769
@Override
8870
@SuppressFBWarnings(value = {"NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE"}, justification = "reason can be null")
8971
public ProviderEvaluation<Boolean> getBooleanEvaluation(String key, Boolean defaultValue, EvaluationContext ctx) {
90-
verifyEvaluation();
9172
StatsigUser user = ContextTransformer.transform(ctx);
9273
Boolean evaluatedValue = defaultValue;
9374
Value featureConfigValue = ctx.getValue(FEATURE_CONFIG_KEY);
@@ -136,7 +117,6 @@ private boolean assumeFailure(APIFeatureGate featureGate) {
136117

137118
@Override
138119
public ProviderEvaluation<String> getStringEvaluation(String key, String defaultValue, EvaluationContext ctx) {
139-
verifyEvaluation();
140120
StatsigUser user = ContextTransformer.transform(ctx);
141121
FeatureConfig featureConfig = parseFeatureConfig(ctx);
142122
String evaluatedValue = defaultValue;
@@ -159,7 +139,6 @@ public ProviderEvaluation<String> getStringEvaluation(String key, String default
159139

160140
@Override
161141
public ProviderEvaluation<Integer> getIntegerEvaluation(String key, Integer defaultValue, EvaluationContext ctx) {
162-
verifyEvaluation();
163142
StatsigUser user = ContextTransformer.transform(ctx);
164143
FeatureConfig featureConfig = parseFeatureConfig(ctx);
165144
Integer evaluatedValue = defaultValue;
@@ -182,7 +161,6 @@ public ProviderEvaluation<Integer> getIntegerEvaluation(String key, Integer defa
182161

183162
@Override
184163
public ProviderEvaluation<Double> getDoubleEvaluation(String key, Double defaultValue, EvaluationContext ctx) {
185-
verifyEvaluation();
186164
StatsigUser user = ContextTransformer.transform(ctx);
187165
FeatureConfig featureConfig = parseFeatureConfig(ctx);
188166
Double evaluatedValue = defaultValue;
@@ -206,7 +184,6 @@ public ProviderEvaluation<Double> getDoubleEvaluation(String key, Double default
206184
@SneakyThrows
207185
@Override
208186
public ProviderEvaluation<Value> getObjectEvaluation(String key, Value defaultValue, EvaluationContext ctx) {
209-
verifyEvaluation();
210187
StatsigUser user = ContextTransformer.transform(ctx);
211188
FeatureConfig featureConfig = parseFeatureConfig(ctx);
212189
Value evaluatedValue = defaultValue;
@@ -293,27 +270,11 @@ private static FeatureConfig parseFeatureConfig(EvaluationContext ctx) {
293270
return new FeatureConfig(type, name);
294271
}
295272

296-
private void verifyEvaluation() throws ProviderNotReadyError, GeneralError {
297-
if (!ProviderState.READY.equals(state)) {
298-
299-
/*
300-
According to spec Requirement 2.4.5:
301-
"The provider SHOULD indicate an error if flag resolution is attempted before the provider is ready."
302-
https://github.com/open-feature/spec/blob/main/specification/sections/02-providers.md#requirement-245
303-
*/
304-
if (ProviderState.NOT_READY.equals(state)) {
305-
throw new ProviderNotReadyError(PROVIDER_NOT_YET_INITIALIZED);
306-
}
307-
throw new GeneralError(UNKNOWN_ERROR);
308-
}
309-
}
310-
311273
@SneakyThrows
312274
@Override
313275
public void shutdown() {
314276
log.info("shutdown");
315277
Statsig.shutdown();
316-
state = ProviderState.NOT_READY;
317278
}
318279

319280
/**

Diff for: ‎providers/statsig/src/test/java/dev/openfeature/contrib/providers/statsig/StatsigProviderTest.java

+1-13
Original file line numberDiff line numberDiff line change
@@ -300,19 +300,7 @@ void getBooleanEvaluationByProperties() {
300300
assertEquals(false, statsigProvider.getBooleanEvaluation(PROPERTIES_FLAG_NAME, false,
301301
evaluationContext).getValue());
302302
}
303-
304-
@SneakyThrows
305-
@Test
306-
void shouldThrowIfNotInitialized() {
307-
StatsigProviderConfig statsigProviderConfig = StatsigProviderConfig.builder().sdkKey("test").build();
308-
StatsigProvider tempstatsigProvider = new StatsigProvider(statsigProviderConfig);
309-
310-
assertThrows(ProviderNotReadyError.class, ()-> tempstatsigProvider.getBooleanEvaluation(
311-
"fail_not_initialized", false, new ImmutableContext()));
312-
313-
OpenFeatureAPI.getInstance().setProviderAndWait("tempstatsigProvider", tempstatsigProvider);
314-
}
315-
303+
316304
@SneakyThrows
317305
@Test
318306
void contextTransformTest() {

Diff for: ‎providers/unleash/src/main/java/dev/openfeature/contrib/providers/unleash/UnleashProvider.java

+6-38
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
package dev.openfeature.contrib.providers.unleash;
22

3+
import static io.getunleash.Variant.DISABLED_VARIANT;
4+
5+
import java.util.concurrent.atomic.AtomicBoolean;
6+
37
import dev.openfeature.sdk.EvaluationContext;
48
import dev.openfeature.sdk.EventProvider;
59
import dev.openfeature.sdk.ImmutableMetadata;
610
import dev.openfeature.sdk.Metadata;
711
import dev.openfeature.sdk.ProviderEvaluation;
8-
import dev.openfeature.sdk.ProviderEventDetails;
9-
import dev.openfeature.sdk.ProviderState;
1012
import dev.openfeature.sdk.Value;
1113
import dev.openfeature.sdk.exceptions.GeneralError;
12-
import dev.openfeature.sdk.exceptions.ProviderNotReadyError;
1314
import io.getunleash.DefaultUnleash;
1415
import io.getunleash.Unleash;
1516
import io.getunleash.UnleashContext;
@@ -20,10 +21,6 @@
2021
import lombok.Setter;
2122
import lombok.extern.slf4j.Slf4j;
2223

23-
import java.util.concurrent.atomic.AtomicBoolean;
24-
25-
import static io.getunleash.Variant.DISABLED_VARIANT;
26-
2724
/**
2825
* Provider implementation for Unleash.
2926
*/
@@ -45,10 +42,6 @@ public class UnleashProvider extends EventProvider {
4542
@Getter
4643
private Unleash unleash;
4744

48-
@Setter(AccessLevel.PROTECTED)
49-
@Getter
50-
private ProviderState state = ProviderState.NOT_READY;
51-
5245
private AtomicBoolean isInitialized = new AtomicBoolean(false);
5346

5447
/**
@@ -78,35 +71,17 @@ public void initialize(EvaluationContext evaluationContext) throws Exception {
7871
unleash = new DefaultUnleash(unleashConfig);
7972

8073
// Unleash is per definition ready after it is initialized.
81-
state = ProviderState.READY;
82-
log.info("finished initializing provider, state: {}", state);
74+
log.info("finished initializing provider");
8375
}
8476

8577
@Override
8678
public Metadata getMetadata() {
8779
return () -> NAME;
8880
}
8981

90-
@Override
91-
public void emitProviderReady(ProviderEventDetails details) {
92-
super.emitProviderReady(details);
93-
state = ProviderState.READY;
94-
}
95-
96-
@Override
97-
public void emitProviderError(ProviderEventDetails details) {
98-
super.emitProviderError(details);
99-
state = ProviderState.ERROR;
100-
}
101-
82+
10283
@Override
10384
public ProviderEvaluation<Boolean> getBooleanEvaluation(String key, Boolean defaultValue, EvaluationContext ctx) {
104-
if (!ProviderState.READY.equals(state)) {
105-
if (ProviderState.NOT_READY.equals(state)) {
106-
throw new ProviderNotReadyError(PROVIDER_NOT_YET_INITIALIZED);
107-
}
108-
throw new GeneralError(UNKNOWN_ERROR);
109-
}
11085
UnleashContext context = ctx == null ? UnleashContext.builder().build() : ContextTransformer.transform(ctx);
11186
boolean featureBooleanValue = unleash.isEnabled(key, context, defaultValue);
11287
return ProviderEvaluation.<Boolean>builder()
@@ -172,12 +147,6 @@ private static Double getDoubleValue(ProviderEvaluation<Value> valueProviderEval
172147

173148
@Override
174149
public ProviderEvaluation<Value> getObjectEvaluation(String key, Value defaultValue, EvaluationContext ctx) {
175-
if (!ProviderState.READY.equals(state)) {
176-
if (ProviderState.NOT_READY.equals(state)) {
177-
throw new ProviderNotReadyError(PROVIDER_NOT_YET_INITIALIZED);
178-
}
179-
throw new GeneralError(UNKNOWN_ERROR);
180-
}
181150
UnleashContext context = ctx == null ? UnleashContext.builder().build() : ContextTransformer.transform(ctx);
182151
Variant evaluatedVariant = unleash.getVariant(key, context);
183152
String variantName;
@@ -209,6 +178,5 @@ public void shutdown() {
209178
if (unleash != null) {
210179
unleash.shutdown();
211180
}
212-
state = ProviderState.NOT_READY;
213181
}
214182
}

Diff for: ‎providers/unleash/src/main/java/dev/openfeature/contrib/providers/unleash/UnleashSubscriberWrapper.java

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package dev.openfeature.contrib.providers.unleash;
22

3+
import javax.annotation.Nullable;
4+
35
import dev.openfeature.sdk.EventProvider;
46
import dev.openfeature.sdk.ImmutableMetadata;
57
import dev.openfeature.sdk.ProviderEventDetails;
8+
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
69
import io.getunleash.UnleashException;
710
import io.getunleash.event.ImpressionEvent;
811
import io.getunleash.event.ToggleEvaluated;
@@ -17,8 +20,6 @@
1720
import lombok.Generated;
1821
import lombok.extern.slf4j.Slf4j;
1922

20-
import javax.annotation.Nullable;
21-
2223
/**
2324
* UnleashSubscriber wrapper for emitting event provider events.
2425
*/
@@ -31,9 +32,11 @@ public class UnleashSubscriberWrapper implements UnleashSubscriber {
3132

3233
/**
3334
* Constructor.
35+
*
3436
* @param unleashSubscriber subscriber
35-
* @param eventProvider events provider for emitting events.
37+
* @param eventProvider events provider for emitting events.
3638
*/
39+
@SuppressFBWarnings(value = { "EI_EXPOSE_REP" })
3740
public UnleashSubscriberWrapper(@Nullable UnleashSubscriber unleashSubscriber, EventProvider eventProvider) {
3841
this.unleashSubscriber = unleashSubscriber;
3942
this.eventProvider = eventProvider;

Diff for: ‎providers/unleash/src/test/java/dev/openfeature/contrib/providers/unleash/UnleashProviderTest.java

+24-58
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,38 @@
11
package dev.openfeature.contrib.providers.unleash;
22

3+
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
4+
import static com.github.tomakehurst.wiremock.client.WireMock.any;
5+
import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl;
6+
import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
7+
import static com.github.tomakehurst.wiremock.client.WireMock.get;
8+
import static com.github.tomakehurst.wiremock.client.WireMock.post;
9+
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
10+
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
11+
import static org.junit.jupiter.api.Assertions.assertEquals;
12+
13+
import java.net.URI;
14+
import java.net.URL;
15+
import java.nio.file.Files;
16+
import java.nio.file.Paths;
17+
import java.time.ZonedDateTime;
18+
import java.util.ArrayList;
19+
import java.util.List;
20+
21+
import org.junit.jupiter.api.AfterAll;
22+
import org.junit.jupiter.api.BeforeAll;
23+
import org.junit.jupiter.api.Test;
24+
import org.junit.jupiter.api.TestInstance;
25+
326
import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
427
import com.github.tomakehurst.wiremock.junit5.WireMockTest;
28+
529
import dev.openfeature.sdk.Client;
630
import dev.openfeature.sdk.ImmutableContext;
731
import dev.openfeature.sdk.ImmutableMetadata;
832
import dev.openfeature.sdk.MutableContext;
933
import dev.openfeature.sdk.OpenFeatureAPI;
1034
import dev.openfeature.sdk.ProviderEvaluation;
11-
import dev.openfeature.sdk.ProviderEventDetails;
12-
import dev.openfeature.sdk.ProviderState;
1335
import dev.openfeature.sdk.Value;
14-
import dev.openfeature.sdk.exceptions.GeneralError;
15-
import dev.openfeature.sdk.exceptions.ProviderNotReadyError;
1636
import io.getunleash.UnleashContext;
1737
import io.getunleash.UnleashException;
1838
import io.getunleash.event.ToggleEvaluated;
@@ -21,29 +41,6 @@
2141
import io.getunleash.repository.FeatureToggleResponse;
2242
import io.getunleash.util.UnleashConfig;
2343
import lombok.SneakyThrows;
24-
import org.junit.jupiter.api.AfterAll;
25-
import org.junit.jupiter.api.BeforeAll;
26-
import org.junit.jupiter.api.Test;
27-
import org.junit.jupiter.api.TestInstance;
28-
29-
import java.net.URI;
30-
import java.net.URL;
31-
import java.nio.file.Files;
32-
import java.nio.file.Paths;
33-
import java.time.ZonedDateTime;
34-
import java.util.ArrayList;
35-
import java.util.List;
36-
37-
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
38-
import static com.github.tomakehurst.wiremock.client.WireMock.any;
39-
import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl;
40-
import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
41-
import static com.github.tomakehurst.wiremock.client.WireMock.post;
42-
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
43-
import static com.github.tomakehurst.wiremock.client.WireMock.get;
44-
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
45-
import static org.junit.jupiter.api.Assertions.assertEquals;
46-
import static org.junit.jupiter.api.Assertions.assertThrows;
4744

4845
/**
4946
* UnleashProvider test, based on APIs mocking.
@@ -206,37 +203,6 @@ void getEvaluationMetadataTest() {
206203
assertEquals(false, nonExistingFlagEvaluation.getFlagMetadata().getBoolean("enabled"));
207204
}
208205

209-
@SneakyThrows
210-
@Test
211-
void shouldThrowIfNotInitialized() {
212-
UnleashProvider asyncInitUnleashProvider = buildUnleashProvider(false, "http://fakeAPI", new TestSubscriber());
213-
assertEquals(ProviderState.NOT_READY, asyncInitUnleashProvider.getState());
214-
215-
// ErrorCode.PROVIDER_NOT_READY should be returned when evaluated via the client
216-
assertThrows(ProviderNotReadyError.class, ()-> asyncInitUnleashProvider.getBooleanEvaluation("fail_not_initialized", false, new ImmutableContext()));
217-
assertThrows(ProviderNotReadyError.class, ()-> asyncInitUnleashProvider.getStringEvaluation("fail_not_initialized", "", new ImmutableContext()));
218-
219-
asyncInitUnleashProvider.initialize(null);
220-
assertThrows(GeneralError.class, ()-> asyncInitUnleashProvider.initialize(null));
221-
222-
asyncInitUnleashProvider.shutdown();
223-
}
224-
225-
@SneakyThrows
226-
@Test
227-
void shouldThrowIfErrorEvent() {
228-
UnleashProvider asyncInitUnleashProvider = buildUnleashProvider(false, "http://fakeAPI", null);
229-
asyncInitUnleashProvider.initialize(new ImmutableContext());
230-
231-
asyncInitUnleashProvider.emitProviderError(ProviderEventDetails.builder().build());
232-
233-
// ErrorCode.PROVIDER_NOT_READY should be returned when evaluated via the client
234-
assertThrows(GeneralError.class, ()-> asyncInitUnleashProvider.getBooleanEvaluation("fail", false, new ImmutableContext()));
235-
assertThrows(GeneralError.class, ()-> asyncInitUnleashProvider.getStringEvaluation("fail", "", new ImmutableContext()));
236-
237-
asyncInitUnleashProvider.shutdown();
238-
}
239-
240206
@SneakyThrows
241207
@Test
242208
void contextTransformTest() {

Diff for: ‎tools/junit-openfeature/pom.xml

-7
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,6 @@
2626
</developers>
2727

2828
<dependencies>
29-
<dependency>
30-
<groupId>dev.openfeature</groupId>
31-
<artifactId>sdk</artifactId>
32-
<version>[1.4,2.0)</version>
33-
<scope>provided</scope>
34-
</dependency>
35-
3629
<dependency>
3730
<groupId>org.apache.commons</groupId>
3831
<artifactId>commons-lang3</artifactId>

0 commit comments

Comments
 (0)
Please sign in to comment.