Skip to content
This repository was archived by the owner on May 30, 2024. It is now read-only.

Commit 42a5a37

Browse files
authored
Merge pull request #74 from launchdarkly/eb/ch18860/fail-fast-in-init
fail fast in initialization if there's a 401
2 parents 446ee7f + 66e88e6 commit 42a5a37

File tree

6 files changed

+53
-3
lines changed

6 files changed

+53
-3
lines changed

src/main/java/com/launchdarkly/client/LDClient.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ public LDClient(String sdkKey, LDConfig config) {
9797
} catch (Exception e) {
9898
logger.error("Exception encountered waiting for LaunchDarkly client initialization", e);
9999
}
100+
if (!updateProcessor.initialized()) {
101+
logger.warn("LaunchDarkly client was not successfully initialized");
102+
}
100103
}
101104
}
102105

src/main/java/com/launchdarkly/client/PollingProcessor.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ public void run() {
5858
} catch (FeatureRequestor.InvalidSDKKeyException e) {
5959
logger.error("Received 401 error, no further polling requests will be made since SDK key is invalid");
6060
scheduler.shutdown();
61+
initFuture.set(null); // if client is initializing, make it stop waiting; has no effect if already inited
6162
} catch (IOException e) {
6263
logger.error("Encountered exception in LaunchDarkly client when retrieving update", e);
6364
}

src/main/java/com/launchdarkly/client/StreamProcessor.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ public Action onConnectionError(Throwable t) {
6868
if ((t instanceof UnsuccessfulResponseException) &&
6969
((UnsuccessfulResponseException) t).getCode() == 401) {
7070
logger.error("Received 401 error, no further streaming connection will be made since SDK key is invalid");
71+
initFuture.set(null); // if client is initializing, make it stop waiting; has no effect if already inited
7172
return Action.SHUTDOWN;
7273
}
7374
return Action.PROCEED;

src/test/java/com/launchdarkly/client/LDClientTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ public void willWaitForUpdateProcessorIfWaitMillisIsNonZero() throws Exception {
109109

110110
expect(updateProcessor.start()).andReturn(initFuture);
111111
expect(initFuture.get(10L, TimeUnit.MILLISECONDS)).andReturn(null);
112-
expect(updateProcessor.initialized()).andReturn(false);
112+
expect(updateProcessor.initialized()).andReturn(false).anyTimes();
113113
replayAll();
114114

115115
client = createMockClient(config);
@@ -125,7 +125,7 @@ public void updateProcessorCanTimeOut() throws Exception {
125125

126126
expect(updateProcessor.start()).andReturn(initFuture);
127127
expect(initFuture.get(10L, TimeUnit.MILLISECONDS)).andThrow(new TimeoutException());
128-
expect(updateProcessor.initialized()).andReturn(false);
128+
expect(updateProcessor.initialized()).andReturn(false).anyTimes();
129129
replayAll();
130130

131131
client = createMockClient(config);
@@ -141,7 +141,7 @@ public void clientCatchesRuntimeExceptionFromUpdateProcessor() throws Exception
141141

142142
expect(updateProcessor.start()).andReturn(initFuture);
143143
expect(initFuture.get(10L, TimeUnit.MILLISECONDS)).andThrow(new RuntimeException());
144-
expect(updateProcessor.initialized()).andReturn(false);
144+
expect(updateProcessor.initialized()).andReturn(false).anyTimes();
145145
replayAll();
146146

147147
client = createMockClient(config);

src/test/java/com/launchdarkly/client/PollingProcessorTest.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,28 @@ public void testConnectionProblem() throws Exception {
5353
pollingProcessor.close();
5454
verifyAll();
5555
}
56+
57+
@Test
58+
public void signalsImmediateFailureOn401Error() throws Exception {
59+
FeatureRequestor requestor = createStrictMock(FeatureRequestor.class);
60+
PollingProcessor pollingProcessor = new PollingProcessor(LDConfig.DEFAULT, requestor, new InMemoryFeatureStore());
61+
62+
expect(requestor.getAllData())
63+
.andThrow(new FeatureRequestor.InvalidSDKKeyException())
64+
.once();
65+
replayAll();
66+
67+
long startTime = System.currentTimeMillis();
68+
Future<Void> initFuture = pollingProcessor.start();
69+
try {
70+
initFuture.get(10, TimeUnit.SECONDS);
71+
} catch (TimeoutException ignored) {
72+
fail("Should not have timed out");
73+
}
74+
assertTrue((System.currentTimeMillis() - startTime) < 9000);
75+
assertTrue(initFuture.isDone());
76+
assertFalse(pollingProcessor.initialized());
77+
pollingProcessor.close();
78+
verifyAll();
79+
}
5680
}

src/test/java/com/launchdarkly/client/StreamProcessorTest.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
import java.net.URI;
1515
import java.util.Collections;
1616
import java.util.concurrent.Future;
17+
import java.util.concurrent.TimeUnit;
18+
import java.util.concurrent.TimeoutException;
1719

1820
import static com.launchdarkly.client.TestUtil.specificFeatureStore;
1921
import static com.launchdarkly.client.VersionedDataKind.FEATURES;
@@ -23,6 +25,7 @@
2325
import static org.junit.Assert.assertFalse;
2426
import static org.junit.Assert.assertNull;
2527
import static org.junit.Assert.assertTrue;
28+
import static org.junit.Assert.fail;
2629

2730
import okhttp3.Headers;
2831

@@ -296,6 +299,24 @@ public void streamWillCloseAfterHttp401Error() throws Exception {
296299
assertEquals(ConnectionErrorHandler.Action.SHUTDOWN, action);
297300
}
298301

302+
@Test
303+
public void processorSignalsImmediateFailureAfter401Error() throws Exception {
304+
UnsuccessfulResponseException e = new UnsuccessfulResponseException(401);
305+
long startTime = System.currentTimeMillis();
306+
StreamProcessor sp = createStreamProcessor(SDK_KEY, configBuilder.build());
307+
Future<Void> initFuture = sp.start();
308+
309+
errorHandler.onConnectionError(e);
310+
try {
311+
initFuture.get(10, TimeUnit.SECONDS);
312+
} catch (TimeoutException ignored) {
313+
fail("Should not have timed out");
314+
}
315+
assertTrue((System.currentTimeMillis() - startTime) < 9000);
316+
assertTrue(initFuture.isDone());
317+
assertFalse(sp.initialized());
318+
}
319+
299320
private StreamProcessor createStreamProcessor(String sdkKey, LDConfig config) {
300321
return new StreamProcessor(sdkKey, config, mockRequestor, featureStore, new StubEventSourceCreator());
301322
}

0 commit comments

Comments
 (0)