Skip to content

Commit ee1d18b

Browse files
committed
fix: setProviderAndWait must throw
Signed-off-by: Todd Baert <[email protected]>
1 parent 302f168 commit ee1d18b

File tree

6 files changed

+45
-23
lines changed

6 files changed

+45
-23
lines changed

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

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -131,14 +131,14 @@ public void setProvider(String clientName, FeatureProvider provider) {
131131
/**
132132
* Set the default provider and wait for initialization to finish.
133133
*/
134-
public void setProviderAndWait(FeatureProvider provider) {
134+
public void setProviderAndWait(FeatureProvider provider) throws RuntimeException {
135135
try (AutoCloseableLock __ = lock.writeLockAutoCloseable()) {
136136
providerRepository.setProvider(
137137
provider,
138138
this::attachEventProvider,
139139
this::emitReady,
140140
this::detachEventProvider,
141-
this::emitError,
141+
this::emitErrorAndThrow,
142142
true);
143143
}
144144
}
@@ -149,14 +149,14 @@ public void setProviderAndWait(FeatureProvider provider) {
149149
* @param clientName The name of the client.
150150
* @param provider The provider to set.
151151
*/
152-
public void setProviderAndWait(String clientName, FeatureProvider provider) {
152+
public void setProviderAndWait(String clientName, FeatureProvider provider) throws RuntimeException {
153153
try (AutoCloseableLock __ = lock.writeLockAutoCloseable()) {
154154
providerRepository.setProvider(clientName,
155155
provider,
156156
this::attachEventProvider,
157157
this::emitReady,
158158
this::detachEventProvider,
159-
this::emitError,
159+
this::emitErrorAndThrow,
160160
true);
161161
}
162162
}
@@ -179,9 +179,14 @@ private void detachEventProvider(FeatureProvider provider) {
179179
}
180180
}
181181

182-
private void emitError(FeatureProvider provider, String message) {
182+
private void emitError(FeatureProvider provider, Exception exception) {
183183
runHandlersForProvider(provider, ProviderEvent.PROVIDER_ERROR,
184-
ProviderEventDetails.builder().message(message).build());
184+
ProviderEventDetails.builder().message(exception.getMessage()).build());
185+
}
186+
187+
private void emitErrorAndThrow(FeatureProvider provider, RuntimeException exception) throws RuntimeException {
188+
this.emitError(provider, exception);
189+
throw exception;
185190
}
186191

187192
/**

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

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public void setProvider(FeatureProvider provider,
6666
Consumer<FeatureProvider> afterSet,
6767
Consumer<FeatureProvider> afterInit,
6868
Consumer<FeatureProvider> afterShutdown,
69-
BiConsumer<FeatureProvider, String> afterError,
69+
BiConsumer<FeatureProvider, RuntimeException> afterError,
7070
boolean waitForInit) {
7171
if (provider == null) {
7272
throw new IllegalArgumentException("Provider cannot be null");
@@ -83,12 +83,12 @@ public void setProvider(FeatureProvider provider,
8383
* Otherwise, initialization happens in the background.
8484
*/
8585
public void setProvider(String clientName,
86-
FeatureProvider provider,
87-
Consumer<FeatureProvider> afterSet,
88-
Consumer<FeatureProvider> afterInit,
89-
Consumer<FeatureProvider> afterShutdown,
90-
BiConsumer<FeatureProvider, String> afterError,
91-
boolean waitForInit) {
86+
FeatureProvider provider,
87+
Consumer<FeatureProvider> afterSet,
88+
Consumer<FeatureProvider> afterInit,
89+
Consumer<FeatureProvider> afterShutdown,
90+
BiConsumer<FeatureProvider, RuntimeException> afterError,
91+
boolean waitForInit) {
9292
if (provider == null) {
9393
throw new IllegalArgumentException("Provider cannot be null");
9494
}
@@ -103,7 +103,7 @@ private void prepareAndInitializeProvider(@Nullable String clientName,
103103
Consumer<FeatureProvider> afterSet,
104104
Consumer<FeatureProvider> afterInit,
105105
Consumer<FeatureProvider> afterShutdown,
106-
BiConsumer<FeatureProvider, String> afterError,
106+
BiConsumer<FeatureProvider, RuntimeException> afterError,
107107
boolean waitForInit) {
108108

109109
if (!isProviderRegistered(newProvider)) {
@@ -129,17 +129,20 @@ private void prepareAndInitializeProvider(@Nullable String clientName,
129129
private void initializeProvider(FeatureProvider newProvider,
130130
Consumer<FeatureProvider> afterInit,
131131
Consumer<FeatureProvider> afterShutdown,
132-
BiConsumer<FeatureProvider, String> afterError,
132+
BiConsumer<FeatureProvider, RuntimeException> afterError,
133133
FeatureProvider oldProvider) {
134134
try {
135135
if (ProviderState.NOT_READY.equals(newProvider.getState())) {
136136
newProvider.initialize(OpenFeatureAPI.getInstance().getEvaluationContext());
137137
afterInit.accept(newProvider);
138138
}
139139
shutDownOld(oldProvider, afterShutdown);
140+
} catch (RuntimeException e) {
141+
log.error("Exception when initializing feature provider {}", newProvider.getClass().getName(), e);
142+
afterError.accept(newProvider, e);
140143
} catch (Exception e) {
141144
log.error("Exception when initializing feature provider {}", newProvider.getClass().getName(), e);
142-
afterError.accept(newProvider, e.getMessage());
145+
afterError.accept(newProvider, new RuntimeException(e));
143146
}
144147
}
145148

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import static org.junit.jupiter.api.Assertions.assertNotNull;
99
import static org.junit.jupiter.api.Assertions.assertNull;
1010
import static org.junit.jupiter.api.Assertions.assertSame;
11+
import static org.junit.jupiter.api.Assertions.assertThrows;
1112
import static org.junit.jupiter.api.Assertions.assertTrue;
1213
import static org.mockito.ArgumentMatchers.any;
1314
import static org.mockito.Mockito.mock;
@@ -31,6 +32,7 @@
3132
import org.slf4j.Logger;
3233

3334
import dev.openfeature.sdk.exceptions.FlagNotFoundError;
35+
import dev.openfeature.sdk.exceptions.GeneralError;
3436
import dev.openfeature.sdk.fixtures.HookFixtures;
3537
import dev.openfeature.sdk.testutils.FeatureProviderTestUtils;
3638

@@ -87,6 +89,17 @@ void getApiInstance() {
8789
assertThat(api.getProvider(providerName).getState()).isEqualTo(ProviderState.READY);
8890
}
8991

92+
@SneakyThrows
93+
@Specification(number="1.1.8", text="The API SHOULD provide functions to set a provider and wait for the initialize function to return or throw.")
94+
@Test void providerAndWaitError() {
95+
FeatureProvider provider1 = new TestEventsProvider(500, true, "fake error");
96+
assertThrows(GeneralError.class, () -> api.setProviderAndWait(provider1));
97+
98+
FeatureProvider provider2 = new TestEventsProvider(500, true, "fake error");
99+
String providerName = "providerAndWaitError";
100+
assertThrows(GeneralError.class, () -> api.setProviderAndWait(providerName, provider2));
101+
}
102+
90103
@Specification(number="2.4.5", text="The provider SHOULD indicate an error if flag resolution is attempted before the provider is ready.")
91104
@Test void shouldReturnNotReadyIfNotInitialized() {
92105
FeatureProvider provider = new InMemoryProvider(new HashMap<>()) {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ void namedProviderOverwrittenTest() {
4545
}
4646

4747
@Test
48-
void providerToMultipleNames() {
48+
void providerToMultipleNames() throws Exception {
4949
FeatureProvider inMemAsEventingProvider = new InMemoryProvider(Collections.EMPTY_MAP);
5050
FeatureProvider noOpAsNonEventingProvider = new NoOpProvider();
5151

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ void shouldRunLambdasOnSuccessful() {
253253
Consumer<FeatureProvider> afterSet = mock(Consumer.class);
254254
Consumer<FeatureProvider> afterInit = mock(Consumer.class);
255255
Consumer<FeatureProvider> afterShutdown = mock(Consumer.class);
256-
BiConsumer<FeatureProvider, String> afterError = mock(BiConsumer.class);
256+
BiConsumer<FeatureProvider, RuntimeException> afterError = mock(BiConsumer.class);
257257

258258
FeatureProvider oldProvider = providerRepository.getProvider();
259259
FeatureProvider featureProvider1 = createMockedProvider();
@@ -274,7 +274,7 @@ void shouldRunLambdasOnError() throws Exception {
274274
Consumer<FeatureProvider> afterSet = mock(Consumer.class);
275275
Consumer<FeatureProvider> afterInit = mock(Consumer.class);
276276
Consumer<FeatureProvider> afterShutdown = mock(Consumer.class);
277-
BiConsumer<FeatureProvider, String> afterError = mock(BiConsumer.class);
277+
BiConsumer<FeatureProvider, RuntimeException> afterError = mock(BiConsumer.class);
278278

279279
FeatureProvider errorFeatureProvider = createMockedErrorProvider();
280280

@@ -310,7 +310,7 @@ private void setFeatureProvider(FeatureProvider provider) {
310310

311311
private void setFeatureProvider(FeatureProvider provider, Consumer<FeatureProvider> afterSet,
312312
Consumer<FeatureProvider> afterInit, Consumer<FeatureProvider> afterShutdown,
313-
BiConsumer<FeatureProvider, String> afterError) {
313+
BiConsumer<FeatureProvider, RuntimeException> afterError) {
314314
providerRepository.setProvider(provider, afterSet, afterInit, afterShutdown,
315315
afterError, false);
316316
waitForSettingProviderHasBeenCompleted(ProviderRepository::getProvider, provider);
@@ -348,8 +348,8 @@ private Consumer<FeatureProvider> mockAfterShutdown() {
348348
};
349349
}
350350

351-
private BiConsumer<FeatureProvider, String> mockAfterError() {
352-
return (fp, message) -> {
351+
private BiConsumer<FeatureProvider, RuntimeException> mockAfterError() {
352+
return (fp, ex) -> {
353353
};
354354
}
355355

src/test/java/dev/openfeature/sdk/testutils/TestEventsProvider.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import dev.openfeature.sdk.ProviderEventDetails;
99
import dev.openfeature.sdk.ProviderState;
1010
import dev.openfeature.sdk.Value;
11+
import dev.openfeature.sdk.exceptions.GeneralError;
1112

1213
public class TestEventsProvider extends EventProvider {
1314

@@ -63,7 +64,7 @@ public void initialize(EvaluationContext evaluationContext) throws Exception {
6364
Thread.sleep(initTimeoutMs);
6465
if (this.initError) {
6566
this.state = ProviderState.ERROR;
66-
throw new Exception(initErrorMessage);
67+
throw new GeneralError(initErrorMessage);
6768
}
6869
this.state = ProviderState.READY;
6970
}

0 commit comments

Comments
 (0)