Skip to content

Commit

Permalink
chore: allow to fail if unavailable (#225)
Browse files Browse the repository at this point in the history
  • Loading branch information
gastonfournier authored Nov 22, 2023
1 parent 2cf0127 commit b55056d
Show file tree
Hide file tree
Showing 3 changed files with 245 additions and 272 deletions.
23 changes: 11 additions & 12 deletions src/main/java/io/getunleash/repository/FeatureRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,9 @@ private void initCollections(UnleashScheduledExecutor executor) {
}

if (unleashConfig.isSynchronousFetchOnInitialisation()) {
updateFeatures(null).run();
updateFeatures(e -> {
throw e;
}).run();
}

if (!unleashConfig.isDisablePolling()) {
Expand All @@ -108,11 +110,7 @@ private void initCollections(UnleashScheduledExecutor executor) {
}
}

private Integer calculateMaxSkips(int fetchTogglesInterval) {
return Integer.max(20, 300 / Integer.max(fetchTogglesInterval, 1));
}

private Runnable updateFeatures(@Nullable final Consumer<UnleashException> handler) {
private Runnable updateFeatures(final Consumer<UnleashException> handler) {
return () -> {
if (throttler.performAction()) {
try {
Expand All @@ -129,7 +127,12 @@ private Runnable updateFeatures(@Nullable final Consumer<UnleashException> handl

featureBackupHandler.write(featureCollection);
} else if (response.getStatus() == ClientFeaturesResponse.Status.UNAVAILABLE) {
throttler.handleHttpErrorCodes(response.getHttpStatusCode());
if (!ready && unleashConfig.isSynchronousFetchOnInitialisation()) {
throw new UnleashException(String.format("Could not initialize Unleash, got response code %d", response.getHttpStatusCode()), null);
}
if (ready) {
throttler.handleHttpErrorCodes(response.getHttpStatusCode());
}
return;
}
throttler.decrementFailureCountAndResetSkips();
Expand All @@ -138,11 +141,7 @@ private Runnable updateFeatures(@Nullable final Consumer<UnleashException> handl
ready = true;
}
} catch (UnleashException e) {
if (handler != null) {
handler.accept(e);
} else {
throw e;
}
handler.accept(e);
}
} else {
throttler.skipped(); // We didn't do anything this iteration, just reduce the count
Expand Down
74 changes: 74 additions & 0 deletions src/test/java/io/getunleash/DefaultUnleashTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.getunleash;

import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
Expand All @@ -8,15 +10,23 @@
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.read.ListAppender;
import com.github.tomakehurst.wiremock.junit5.WireMockExtension;
import io.getunleash.event.EventDispatcher;
import io.getunleash.event.UnleashReady;
import io.getunleash.event.UnleashSubscriber;
import io.getunleash.integration.TestDefinition;
import io.getunleash.metric.UnleashMetricService;
import io.getunleash.repository.*;
import io.getunleash.strategy.DefaultStrategy;
import io.getunleash.strategy.Strategy;
import io.getunleash.util.UnleashConfig;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.slf4j.LoggerFactory;

class DefaultUnleashTest {
Expand All @@ -26,6 +36,13 @@ class DefaultUnleashTest {
private EventDispatcher eventDispatcher;
private UnleashMetricService metricService;

@RegisterExtension
static WireMockExtension serverMock =
WireMockExtension.newInstance()
.configureStaticDsl(true)
.options(wireMockConfig().dynamicPort().dynamicHttpsPort())
.build();

@BeforeEach
public void setup() {
UnleashConfig unleashConfig =
Expand Down Expand Up @@ -222,16 +239,66 @@ public void supports_failing_hard_on_multiple_instantiations() {

@Test
public void synchronous_fetch_on_initialisation_fails_on_initialization() {
IsReadyTestSubscriber readySubscriber = new IsReadyTestSubscriber();
UnleashConfig config =
UnleashConfig.builder()
.unleashAPI("http://wrong:4242")
.appName("wrong_upstream")
.apiKey("default:development:1234567890123456")
.instanceId("multiple_connection_exception")
.synchronousFetchOnInitialisation(true)
.subscriber(readySubscriber)
.build();

assertThatThrownBy(() -> new DefaultUnleash(config)).isInstanceOf(UnleashException.class);
assertThat(readySubscriber.ready).isFalse();
}

@Test
public void synchronous_fetch_on_initialisation_fails_on_non_200_response() throws URISyntaxException {
mockUnleashAPI(401);
IsReadyTestSubscriber readySubscriber = new IsReadyTestSubscriber();
UnleashConfig config =
UnleashConfig.builder()
.unleashAPI(new URI("http://localhost:" + serverMock.getPort() + "/api/"))
.appName("wrong_upstream")
.apiKey("default:development:1234567890123456")
.instanceId("non-200")
.synchronousFetchOnInitialisation(true)
.subscriber(readySubscriber)
.build();

assertThatThrownBy(() -> new DefaultUnleash(config)).isInstanceOf(UnleashException.class);
assertThat(readySubscriber.ready).isFalse();
}

@Test
public void synchronous_fetch_on_initialisation_switches_to_ready_on_200() throws URISyntaxException {
mockUnleashAPI(200);
IsReadyTestSubscriber readySubscriber = new IsReadyTestSubscriber();
UnleashConfig config =
UnleashConfig.builder()
.unleashAPI(new URI("http://localhost:" + serverMock.getPort() + "/api/"))
.appName("wrong_upstream")
.apiKey("default:development:1234567890123456")
.instanceId("with-success-response")
.synchronousFetchOnInitialisation(true)
.subscriber(readySubscriber)
.build();
new DefaultUnleash(config);
assertThat(readySubscriber.ready).isTrue();
}

private void mockUnleashAPI(int featuresStatusCode) {
stubFor(
get(urlEqualTo("/api/client/features"))
.withHeader("Accept", equalTo("application/json"))
.willReturn(
aResponse()
.withStatus(featuresStatusCode)
.withHeader("Content-Type", "application/json")
.withBody("{\"features\": []}")));
stubFor(post(urlEqualTo("/api/client/register")).willReturn(aResponse().withStatus(200)));
}

@Test
Expand Down Expand Up @@ -271,4 +338,11 @@ public void client_identifier_handles_api_key_being_null() {
assertThat(id)
.isEqualTo("f83eb743f4c8dc41294aafb96f454763e5a90b96db8b7040ddc505d636bdb243");
}

private static class IsReadyTestSubscriber implements UnleashSubscriber {
public boolean ready = false;
public void onReady(UnleashReady unleashReady) {
this.ready = true;
}
}
}
Loading

0 comments on commit b55056d

Please sign in to comment.