diff --git a/deployment/src/test/java/io/quarkiverse/unleash/ClientRegisteredUnleashSubscriber.java b/deployment/src/test/java/io/quarkiverse/unleash/ClientRegisteredUnleashSubscriber.java new file mode 100644 index 0000000..cb847cd --- /dev/null +++ b/deployment/src/test/java/io/quarkiverse/unleash/ClientRegisteredUnleashSubscriber.java @@ -0,0 +1,23 @@ +package io.quarkiverse.unleash; + +import jakarta.enterprise.context.ApplicationScoped; + +import io.getunleash.event.UnleashSubscriber; +import io.getunleash.metric.ClientRegistration; +import io.quarkus.arc.Unremovable; + +@ApplicationScoped +@Unremovable +public class ClientRegisteredUnleashSubscriber implements UnleashSubscriber { + + private boolean clientRegistered; + + @Override + public void clientRegistered(ClientRegistration clientRegistration) { + clientRegistered = true; + } + + public boolean isClientRegistered() { + return clientRegistered; + } +} diff --git a/deployment/src/test/java/io/quarkiverse/unleash/UnleashSubscriberTest.java b/deployment/src/test/java/io/quarkiverse/unleash/UnleashSubscriberTest.java new file mode 100644 index 0000000..92a6732 --- /dev/null +++ b/deployment/src/test/java/io/quarkiverse/unleash/UnleashSubscriberTest.java @@ -0,0 +1,25 @@ +package io.quarkiverse.unleash; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import jakarta.inject.Inject; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusUnitTest; + +public class UnleashSubscriberTest { + + @RegisterExtension + static final QuarkusUnitTest TEST = new QuarkusUnitTest() + .withApplicationRoot((jar) -> jar.addClasses(ClientRegisteredUnleashSubscriber.class)); + + @Inject + ClientRegisteredUnleashSubscriber unleashSubscriber; + + @Test + void test() { + assertTrue(unleashSubscriber.isClientRegistered()); + } +} diff --git a/docs/modules/ROOT/pages/index.adoc b/docs/modules/ROOT/pages/index.adoc index 4f45175..c183ccd 100644 --- a/docs/modules/ROOT/pages/index.adoc +++ b/docs/modules/ROOT/pages/index.adoc @@ -93,6 +93,57 @@ public class TestService { } ---- +=== Subscriber API + +This extension supports the https://docs.getunleash.io/reference/sdks/java#subscriber-api[Subscriber API] from the Unleash Client SDK for Java. +It can be used by implementing the `UnleashSubscriber` interface as shown below. + +[source,java] +---- +import static io.getunleash.repository.FeatureToggleResponse.Status.CHANGED; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import jakarta.enterprise.context.ApplicationScoped; + +import io.getunleash.FeatureToggle; +import io.getunleash.event.UnleashSubscriber; +import io.getunleash.repository.FeatureToggleResponse; +import io.quarkus.arc.Unremovable; +import io.quarkus.logging.Log; + +@ApplicationScoped // <1> +@Unremovable // <2> +public class ToggleChangedLogger implements UnleashSubscriber { + + private static final Set TOGGLE_NAMES = Set.of("my-toggle-1", "my-toggle-2"); + + private final Map toggleValues = new HashMap<>(); + + @Override + public void togglesFetched(FeatureToggleResponse toggleResponse) { + if (toggleResponse.getStatus() == CHANGED) { + for (String toggleName : TOGGLE_NAMES) { + FeatureToggle toggle = toggleResponse.getToggleCollection().getToggle(toggleName); + if (toggle != null) { + Boolean previousValue = toggleValues.put(toggleName, toggle.isEnabled()); + if (previousValue == null || previousValue != toggle.isEnabled()) { + String value = toggle.isEnabled() ? "enabled" : "disabled"; + Log.infof("Feature toggle %s was just %s", toggleName, value); + } + } else { + toggleValues.remove(toggleName); + } + } + } + } +} +---- +<1> The `UnleashSubscriber` implementation has to be a CDI bean. +<2> The bean will be considered unused and will be automatically removed if it is not annotated with `@Unremovable`. + === Testing To use the test extension, add this dependency to the project: diff --git a/runtime/src/main/java/io/quarkiverse/unleash/runtime/UnleashCreator.java b/runtime/src/main/java/io/quarkiverse/unleash/runtime/UnleashCreator.java index 4879386..ebe0ba2 100644 --- a/runtime/src/main/java/io/quarkiverse/unleash/runtime/UnleashCreator.java +++ b/runtime/src/main/java/io/quarkiverse/unleash/runtime/UnleashCreator.java @@ -2,7 +2,11 @@ import io.getunleash.DefaultUnleash; import io.getunleash.Unleash; +import io.getunleash.event.UnleashSubscriber; import io.getunleash.util.UnleashConfig; +import io.quarkus.arc.Arc; +import io.quarkus.arc.ArcContainer; +import io.quarkus.arc.InstanceHandle; public class UnleashCreator { @@ -28,6 +32,18 @@ public static Unleash createUnleash(UnleashRuntimeTimeConfig unleashRuntimeTimeC builder.disableMetrics(); } + /* + * The Arc container will be null in tests when @InjectUnleash is used. + * TODO Make the Unleash client managed by CDI when @InjectUnleash is used. + */ + ArcContainer arcContainer = Arc.container(); + if (arcContainer != null) { + InstanceHandle unleashSubscriber = arcContainer.instance(UnleashSubscriber.class); + if (unleashSubscriber.isAvailable()) { + builder.subscriber(unleashSubscriber.get()); + } + } + return new DefaultUnleash(builder.build()); } }