Skip to content

Commit b90f393

Browse files
committed
use lombok delegate, add tests and fix codestyle
Signed-off-by: christian.lutnik <[email protected]>
1 parent 56e66a5 commit b90f393

File tree

6 files changed

+92
-56
lines changed

6 files changed

+92
-56
lines changed

src/main/java/dev/openfeature/sdk/EventProvider.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import dev.openfeature.sdk.internal.TriConsumer;
44

5-
import javax.annotation.Nullable;
65

76
/**
87
* Abstract EventProvider. Providers must extend this class to support events.
@@ -17,9 +16,9 @@
1716
* @see FeatureProvider
1817
*/
1918
public abstract class EventProvider implements FeatureProvider {
20-
private @Nullable EventProviderListener eventProviderListener;
19+
private EventProviderListener eventProviderListener;
2120

22-
void setEventProviderListener(@Nullable EventProviderListener eventProviderListener) {
21+
void setEventProviderListener(EventProviderListener eventProviderListener) {
2322
this.eventProviderListener = eventProviderListener;
2423
}
2524

src/main/java/dev/openfeature/sdk/FeatureProvider.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,16 +56,15 @@ default void shutdown() {
5656
}
5757

5858
/**
59-
* @deprecated State is handled by the SDK internally.
60-
* <p>
6159
* Returns a representation of the current readiness of the provider.
6260
* If the provider needs to be initialized, it should return {@link ProviderState#NOT_READY}.
6361
* If the provider is in an error state, it should return {@link ProviderState#ERROR}.
6462
* If the provider is functioning normally, it should return {@link ProviderState#READY}.
65-
*
63+
*
6664
* <p><i>Providers which do not implement this method are assumed to be ready immediately.</i></p>
67-
*
65+
*
6866
* @return ProviderState
67+
* @deprecated The state is handled by the SDK internally. Query the state from the {@link Client} instead.
6968
*/
7069
@Deprecated
7170
default ProviderState getState() {

src/main/java/dev/openfeature/sdk/FeatureProviderWrapper.java

Lines changed: 16 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
11
package dev.openfeature.sdk;
22

33
import dev.openfeature.sdk.exceptions.OpenFeatureError;
4+
import lombok.experimental.Delegate;
45

5-
import java.util.List;
66
import java.util.concurrent.atomic.AtomicBoolean;
77

8-
public class FeatureProviderWrapper implements FeatureProvider, EventProviderListener {
8+
class FeatureProviderWrapper implements FeatureProvider, EventProviderListener {
9+
10+
private interface ExcludeFromDelegate {
11+
void initialize(EvaluationContext evaluationContext) throws Exception;
12+
13+
void shutdown();
14+
15+
ProviderState getState();
16+
}
17+
18+
@Delegate(excludes = ExcludeFromDelegate.class)
919
private final FeatureProvider delegate;
1020
private final AtomicBoolean isInitialized = new AtomicBoolean();
1121
private ProviderState state = ProviderState.NOT_READY;
@@ -17,41 +27,6 @@ public FeatureProviderWrapper(FeatureProvider delegate) {
1727
}
1828
}
1929

20-
@Override
21-
public Metadata getMetadata() {
22-
return delegate.getMetadata();
23-
}
24-
25-
@Override
26-
public List<Hook> getProviderHooks() {
27-
return delegate.getProviderHooks();
28-
}
29-
30-
@Override
31-
public ProviderEvaluation<Boolean> getBooleanEvaluation(String key, Boolean defaultValue, EvaluationContext ctx) {
32-
return delegate.getBooleanEvaluation(key, defaultValue, ctx);
33-
}
34-
35-
@Override
36-
public ProviderEvaluation<String> getStringEvaluation(String key, String defaultValue, EvaluationContext ctx) {
37-
return delegate.getStringEvaluation(key, defaultValue, ctx);
38-
}
39-
40-
@Override
41-
public ProviderEvaluation<Integer> getIntegerEvaluation(String key, Integer defaultValue, EvaluationContext ctx) {
42-
return delegate.getIntegerEvaluation(key, defaultValue, ctx);
43-
}
44-
45-
@Override
46-
public ProviderEvaluation<Double> getDoubleEvaluation(String key, Double defaultValue, EvaluationContext ctx) {
47-
return delegate.getDoubleEvaluation(key, defaultValue, ctx);
48-
}
49-
50-
@Override
51-
public ProviderEvaluation<Value> getObjectEvaluation(String key, Value defaultValue, EvaluationContext ctx) {
52-
return delegate.getObjectEvaluation(key, defaultValue, ctx);
53-
}
54-
5530
@Override
5631
public void initialize(EvaluationContext evaluationContext) throws Exception {
5732
if (isInitialized.getAndSet(true)) {
@@ -94,7 +69,9 @@ public int hashCode() {
9469

9570
@Override
9671
public boolean equals(Object obj) {
97-
if (this == obj) return true;
72+
if (this == obj) {
73+
return true;
74+
}
9875
if (obj instanceof FeatureProviderWrapper) {
9976
return delegate.equals(((FeatureProviderWrapper) obj).delegate);
10077
}
@@ -112,7 +89,7 @@ public void onEmit(ProviderEvent event, ProviderEventDetails details) {
11289
}
11390
}
11491

115-
FeatureProvider getDelegate(){
92+
FeatureProvider getDelegate() {
11693
return delegate;
11794
}
11895
}

src/main/java/dev/openfeature/sdk/OpenFeatureAPI.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -275,13 +275,6 @@ public FeatureProvider getProvider() {
275275
return providerRepository.getProvider();
276276
}
277277

278-
/**
279-
* Return the state of the default provider.
280-
*/
281-
public ProviderState getProviderState() {
282-
return providerRepository.getProviderState();
283-
}
284-
285278
/**
286279
* Fetch a provider for a domain. If not found, return the default.
287280
*
@@ -292,6 +285,13 @@ public FeatureProvider getProvider(String domain) {
292285
return providerRepository.getProvider(domain);
293286
}
294287

288+
/**
289+
* Return the state of the default provider.
290+
*/
291+
public ProviderState getProviderState() {
292+
return providerRepository.getProviderState();
293+
}
294+
295295
/**
296296
* Get the state of the provider for a domain. If no provider with the domain is found, returns the state of the
297297
* default provider.

src/main/java/dev/openfeature/sdk/ProviderRepository.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
class ProviderRepository {
2222

2323
private final Map<String, FeatureProviderWrapper> providers = new ConcurrentHashMap<>();
24-
private final AtomicReference<FeatureProviderWrapper> defaultProvider = new AtomicReference<>(new FeatureProviderWrapper(new NoOpProvider()));
24+
private final AtomicReference<FeatureProviderWrapper> defaultProvider = new AtomicReference<>(
25+
new FeatureProviderWrapper(new NoOpProvider())
26+
);
2527
private final ExecutorService taskExecutor = Executors.newCachedThreadPool(runnable -> {
2628
final Thread thread = new Thread(runnable);
2729
thread.setDaemon(true);
@@ -148,10 +150,18 @@ private void initializeProvider(FeatureProviderWrapper newProvider,
148150
}
149151
shutDownOld(oldProvider, afterShutdown);
150152
} catch (OpenFeatureError e) {
151-
log.error("Exception when initializing feature provider {}", newProvider.getDelegate().getClass().getName(), e);
153+
log.error(
154+
"Exception when initializing feature provider {}",
155+
newProvider.getDelegate().getClass().getName(),
156+
e
157+
);
152158
afterError.accept(newProvider.getDelegate(), e);
153159
} catch (Exception e) {
154-
log.error("Exception when initializing feature provider {}", newProvider.getDelegate().getClass().getName(), e);
160+
log.error(
161+
"Exception when initializing feature provider {}",
162+
newProvider.getDelegate().getClass().getName(),
163+
e
164+
);
155165
afterError.accept(newProvider.getDelegate(), new GeneralError(e));
156166
}
157167
}

src/test/java/dev/openfeature/sdk/DeveloperExperienceTest.java

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import java.util.*;
1010

11+
import static org.assertj.core.api.Assertions.assertThat;
1112
import static org.junit.jupiter.api.Assertions.assertEquals;
1213
import static org.junit.jupiter.api.Assertions.assertFalse;
1314
import static org.mockito.ArgumentMatchers.any;
@@ -121,4 +122,54 @@ public Optional before(HookContext ctx, Map hints) {
121122
String noOpValue = client.getStringValue("val", defaultValue);
122123
assertEquals(noOpValue, defaultValue);
123124
}
125+
126+
@Test
127+
void setProviderAndWaitShouldPutTheProviderInReadyState() {
128+
String domain = "domain";
129+
OpenFeatureAPI api = OpenFeatureAPI.getInstance();
130+
api.setProviderAndWait(domain, new TestEventsProvider());
131+
Client client = api.getClient(domain);
132+
assertThat(client.getProviderState()).isEqualTo(ProviderState.READY);
133+
}
134+
135+
@Specification(number = "5.3.5", text = "If the provider emits an event, the value of the client's provider status MUST be updated accordingly.")
136+
@Test
137+
void shouldPutTheProviderInStateErrorAfterEmittingErrorEvent() {
138+
String domain = "domain";
139+
OpenFeatureAPI api = OpenFeatureAPI.getInstance();
140+
TestEventsProvider provider = new TestEventsProvider();
141+
api.setProviderAndWait(domain, provider);
142+
Client client = api.getClient(domain);
143+
assertThat(client.getProviderState()).isEqualTo(ProviderState.READY);
144+
provider.emitProviderError(ProviderEventDetails.builder().build());
145+
assertThat(client.getProviderState()).isEqualTo(ProviderState.ERROR);
146+
}
147+
148+
@Specification(number = "5.3.5", text = "If the provider emits an event, the value of the client's provider status MUST be updated accordingly.")
149+
@Test
150+
void shouldPutTheProviderInStateStaleAfterEmittingStaleEvent() {
151+
String domain = "domain";
152+
OpenFeatureAPI api = OpenFeatureAPI.getInstance();
153+
TestEventsProvider provider = new TestEventsProvider();
154+
api.setProviderAndWait(domain, provider);
155+
Client client = api.getClient(domain);
156+
assertThat(client.getProviderState()).isEqualTo(ProviderState.READY);
157+
provider.emitProviderStale(ProviderEventDetails.builder().build());
158+
assertThat(client.getProviderState()).isEqualTo(ProviderState.STALE);
159+
}
160+
161+
@Specification(number = "5.3.5", text = "If the provider emits an event, the value of the client's provider status MUST be updated accordingly.")
162+
@Test
163+
void shouldPutTheProviderInStateReadyAfterEmittingReadyEvent() {
164+
String domain = "domain";
165+
OpenFeatureAPI api = OpenFeatureAPI.getInstance();
166+
TestEventsProvider provider = new TestEventsProvider();
167+
api.setProviderAndWait(domain, provider);
168+
Client client = api.getClient(domain);
169+
assertThat(client.getProviderState()).isEqualTo(ProviderState.READY);
170+
provider.emitProviderStale(ProviderEventDetails.builder().build());
171+
assertThat(client.getProviderState()).isEqualTo(ProviderState.STALE);
172+
provider.emitProviderReady(ProviderEventDetails.builder().build());
173+
assertThat(client.getProviderState()).isEqualTo(ProviderState.READY);
174+
}
124175
}

0 commit comments

Comments
 (0)