diff --git a/core/runtime/src/main/java/io/quarkus/runtime/shutdown/ShutdownConfig.java b/core/runtime/src/main/java/io/quarkus/runtime/shutdown/ShutdownConfig.java index 8c83803e98103f..b35101c2a533d6 100644 --- a/core/runtime/src/main/java/io/quarkus/runtime/shutdown/ShutdownConfig.java +++ b/core/runtime/src/main/java/io/quarkus/runtime/shutdown/ShutdownConfig.java @@ -18,8 +18,21 @@ public class ShutdownConfig { @ConfigItem public Optional<Duration> timeout; + /** + * Delay between shutdown being requested and actually initiated. Also called the pre-shutdown phase. + * In pre-shutdown, the server continues working as usual, except a readiness probe starts reporting "down" + * (if the {@code smallrye-health} extension is present). This gives the infrastructure time to detect + * that the application instance is shutting down and stop routing traffic to it. + */ + @ConfigItem + public Optional<Duration> delay; + public boolean isShutdownTimeoutSet() { return timeout.isPresent() && timeout.get().toMillis() > 0; } + public boolean isDelaySet() { + return delay.isPresent() && delay.get().toMillis() > 0; + } + } diff --git a/core/runtime/src/main/java/io/quarkus/runtime/shutdown/ShutdownRecorder.java b/core/runtime/src/main/java/io/quarkus/runtime/shutdown/ShutdownRecorder.java index debd3a06ab6583..914aaa533523cd 100644 --- a/core/runtime/src/main/java/io/quarkus/runtime/shutdown/ShutdownRecorder.java +++ b/core/runtime/src/main/java/io/quarkus/runtime/shutdown/ShutdownRecorder.java @@ -1,6 +1,5 @@ package io.quarkus.runtime.shutdown; -import java.time.Duration; import java.util.List; import java.util.Optional; import java.util.concurrent.CountDownLatch; @@ -16,43 +15,52 @@ public class ShutdownRecorder { private static final Logger log = Logger.getLogger(ShutdownRecorder.class); private static volatile List<ShutdownListener> shutdownListeners; - private static volatile Optional<Duration> waitTime; - - final ShutdownConfig shutdownConfig; + private static volatile ShutdownConfig shutdownConfig; public ShutdownRecorder(ShutdownConfig shutdownConfig) { - this.shutdownConfig = shutdownConfig; + ShutdownRecorder.shutdownConfig = shutdownConfig; } public void setListeners(List<ShutdownListener> listeners) { - shutdownListeners = listeners; - waitTime = shutdownConfig.timeout; + shutdownListeners = Optional.ofNullable(listeners).orElseGet(List::of); } public static void runShutdown() { - if (shutdownListeners == null) { - return; - } - log.debug("Attempting to gracefully shutdown."); try { - CountDownLatch preShutdown = new CountDownLatch(shutdownListeners.size()); - for (ShutdownListener i : shutdownListeners) { - i.preShutdown(new LatchShutdownNotification(preShutdown)); - } + executePreShutdown(); + waitForDelay(); + executeShutdown(); + } catch (Throwable e) { + log.error("Graceful shutdown failed", e); + } + } - preShutdown.await(); - CountDownLatch shutdown = new CountDownLatch(shutdownListeners.size()); - for (ShutdownListener i : shutdownListeners) { - i.shutdown(new LatchShutdownNotification(shutdown)); - } - if (waitTime.isPresent()) { - if (!shutdown.await(waitTime.get().toMillis(), TimeUnit.MILLISECONDS)) { - log.error("Timed out waiting for graceful shutdown, shutting down anyway."); - } + private static void executePreShutdown() throws InterruptedException { + CountDownLatch preShutdown = new CountDownLatch(shutdownListeners.size()); + for (ShutdownListener i : shutdownListeners) { + i.preShutdown(new LatchShutdownNotification(preShutdown)); + } + preShutdown.await(); + } + + private static void waitForDelay() { + if (shutdownConfig.isDelaySet()) { + try { + Thread.sleep(shutdownConfig.delay.get().toMillis()); + } catch (InterruptedException e) { + log.error("Interrupted while waiting for delay, continuing to shutdown immediately"); } + } + } - } catch (Throwable e) { - log.error("Graceful shutdown failed", e); + private static void executeShutdown() throws InterruptedException { + CountDownLatch shutdown = new CountDownLatch(shutdownListeners.size()); + for (ShutdownListener i : shutdownListeners) { + i.shutdown(new LatchShutdownNotification(shutdown)); + } + if (shutdownConfig.isShutdownTimeoutSet() + && !shutdown.await(shutdownConfig.timeout.get().toMillis(), TimeUnit.MILLISECONDS)) { + log.error("Timed out waiting for graceful shutdown, shutting down anyway."); } } diff --git a/extensions/smallrye-health/deployment/src/main/java/io/quarkus/smallrye/health/deployment/SmallRyeHealthProcessor.java b/extensions/smallrye-health/deployment/src/main/java/io/quarkus/smallrye/health/deployment/SmallRyeHealthProcessor.java index 69d292bd816340..b6444f1cf34830 100644 --- a/extensions/smallrye-health/deployment/src/main/java/io/quarkus/smallrye/health/deployment/SmallRyeHealthProcessor.java +++ b/extensions/smallrye-health/deployment/src/main/java/io/quarkus/smallrye/health/deployment/SmallRyeHealthProcessor.java @@ -9,7 +9,6 @@ import java.util.Optional; import java.util.Set; import java.util.function.BooleanSupplier; -import java.util.stream.Collectors; import java.util.stream.Stream; import org.eclipse.microprofile.config.Config; @@ -54,6 +53,7 @@ import io.quarkus.runtime.configuration.ConfigurationException; import io.quarkus.smallrye.health.deployment.spi.HealthBuildItem; import io.quarkus.smallrye.health.runtime.QuarkusAsyncHealthCheckFactory; +import io.quarkus.smallrye.health.runtime.ShutdownReadinessCheck; import io.quarkus.smallrye.health.runtime.ShutdownReadinessListener; import io.quarkus.smallrye.health.runtime.SmallRyeHealthGroupHandler; import io.quarkus.smallrye.health.runtime.SmallRyeHealthHandler; @@ -82,6 +82,8 @@ class SmallRyeHealthProcessor { private static final Logger LOG = Logger.getLogger(SmallRyeHealthProcessor.class); + private static final String CONFIG_KEY_HEALTH_MANAGEMENT_ENABLED = "quarkus.smallrye-health.management.enabled"; + private static final DotName LIVENESS = DotName.createSimple(Liveness.class.getName()); private static final DotName READINESS = DotName.createSimple(Readiness.class.getName()); private static final DotName STARTUP = DotName.createSimple(Startup.class.getName()); @@ -132,7 +134,7 @@ List<HotDeploymentWatchedFileBuildItem> brandingFiles() { BRANDING_LOGO_MODULE, BRANDING_STYLE_MODULE, BRANDING_FAVICON_MODULE).map(HotDeploymentWatchedFileBuildItem::new) - .collect(Collectors.toList()); + .toList(); } @BuildStep @@ -211,7 +213,7 @@ public void defineHealthRoutes(BuildProducer<RouteBuildItem> routes, // Register the health handler routes.produce(nonApplicationRootPathBuildItem.routeBuilder() - .management("quarkus.smallrye-health.management.enabled") + .management(CONFIG_KEY_HEALTH_MANAGEMENT_ENABLED) .route(healthConfig.rootPath) .routeConfigKey("quarkus.smallrye-health.root-path") .handler(new SmallRyeHealthHandler()) @@ -220,7 +222,7 @@ public void defineHealthRoutes(BuildProducer<RouteBuildItem> routes, // Register the liveness handler routes.produce(nonApplicationRootPathBuildItem.routeBuilder() - .management("quarkus.smallrye-health.management.enabled") + .management(CONFIG_KEY_HEALTH_MANAGEMENT_ENABLED) .nestedRoute(healthConfig.rootPath, healthConfig.livenessPath) .handler(new SmallRyeLivenessHandler()) .displayOnNotFoundPage() @@ -228,7 +230,7 @@ public void defineHealthRoutes(BuildProducer<RouteBuildItem> routes, // Register the readiness handler routes.produce(nonApplicationRootPathBuildItem.routeBuilder() - .management("quarkus.smallrye-health.management.enabled") + .management(CONFIG_KEY_HEALTH_MANAGEMENT_ENABLED) .nestedRoute(healthConfig.rootPath, healthConfig.readinessPath) .handler(new SmallRyeReadinessHandler()) .displayOnNotFoundPage() @@ -236,7 +238,7 @@ public void defineHealthRoutes(BuildProducer<RouteBuildItem> routes, // Register the health group handlers routes.produce(nonApplicationRootPathBuildItem.routeBuilder() - .management("quarkus.smallrye-health.management.enabled") + .management(CONFIG_KEY_HEALTH_MANAGEMENT_ENABLED) .nestedRoute(healthConfig.rootPath, healthConfig.groupPath) .handler(new SmallRyeHealthGroupHandler()) .displayOnNotFoundPage() @@ -244,7 +246,7 @@ public void defineHealthRoutes(BuildProducer<RouteBuildItem> routes, SmallRyeIndividualHealthGroupHandler handler = new SmallRyeIndividualHealthGroupHandler(); routes.produce(nonApplicationRootPathBuildItem.routeBuilder() - .management("quarkus.smallrye-health.management.enabled") + .management(CONFIG_KEY_HEALTH_MANAGEMENT_ENABLED) .nestedRoute(healthConfig.rootPath, healthConfig.groupPath + "/*") .handler(handler) .displayOnNotFoundPage() @@ -252,7 +254,7 @@ public void defineHealthRoutes(BuildProducer<RouteBuildItem> routes, // Register the wellness handler routes.produce(nonApplicationRootPathBuildItem.routeBuilder() - .management("quarkus.smallrye-health.management.enabled") + .management(CONFIG_KEY_HEALTH_MANAGEMENT_ENABLED) .nestedRoute(healthConfig.rootPath, healthConfig.wellnessPath) .handler(new SmallRyeWellnessHandler()) .displayOnNotFoundPage() @@ -260,7 +262,7 @@ public void defineHealthRoutes(BuildProducer<RouteBuildItem> routes, // Register the startup handler routes.produce(nonApplicationRootPathBuildItem.routeBuilder() - .management("quarkus.smallrye-health.management.enabled") + .management(CONFIG_KEY_HEALTH_MANAGEMENT_ENABLED) .nestedRoute(healthConfig.rootPath, healthConfig.startupPath) .handler(new SmallRyeStartupHandler()) .displayOnNotFoundPage() @@ -314,10 +316,9 @@ private void warnIfJaxRsPathUsed(IndexView index, DotName healthAnnotation) { if (target.asClass().declaredAnnotation(JAX_RS_PATH) != null) { containsPath = true; } - } else if (target.kind() == Kind.METHOD) { - if (target.asMethod().hasAnnotation(JAX_RS_PATH)) { - containsPath = true; - } + } else if (target.kind() == Kind.METHOD && target.asMethod().hasAnnotation(JAX_RS_PATH)) { + containsPath = true; + } if (containsPath) { LOG.warnv( @@ -355,6 +356,14 @@ public void kubernetes(NonApplicationRootPathBuildItem nonApplicationRootPathBui healthConfig.startupPath))); } + @BuildStep + AdditionalBeanBuildItem shutdownHealthCheck() { + return AdditionalBeanBuildItem.builder() + .addBeanClass(ShutdownReadinessCheck.class) + .setUnremovable() + .build(); + } + @BuildStep ShutdownListenerBuildItem shutdownListener() { return new ShutdownListenerBuildItem(new ShutdownReadinessListener()); @@ -413,7 +422,6 @@ void registerHealthUiHandler( LaunchModeBuildItem launchMode, SmallRyeHealthConfig healthConfig, BuildProducer<SmallRyeHealthBuildItem> smallryeHealthBuildProducer, ShutdownContextBuildItem shutdownContext) { - WebJarResultsBuildItem.WebJarResult result = webJarResultsBuildItem.byArtifactKey(HEALTH_UI_WEBJAR_ARTIFACT_KEY); if (result == null) { return; @@ -428,7 +436,7 @@ void registerHealthUiHandler( healthUiPath, result.getWebRootConfigurations(), runtimeConfig, shutdownContext); routeProducer.produce(nonApplicationRootPathBuildItem.routeBuilder() - .management("quarkus.smallrye-health.management.enabled") + .management(CONFIG_KEY_HEALTH_MANAGEMENT_ENABLED) .route(healthConfig.ui.rootPath) .displayOnNotFoundPage("Health UI") .routeConfigKey("quarkus.smallrye-health.ui.root-path") @@ -436,7 +444,7 @@ void registerHealthUiHandler( .build()); routeProducer.produce(nonApplicationRootPathBuildItem.routeBuilder() - .management("quarkus.smallrye-health.management.enabled") + .management(CONFIG_KEY_HEALTH_MANAGEMENT_ENABLED) .route(healthConfig.ui.rootPath + "*") .handler(handler) .build()); diff --git a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/AdditionalJsonPropertiesConfigTest.java b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/AdditionalJsonPropertiesConfigTest.java index 9ad98853197c6b..42f7ddbe6b8f08 100644 --- a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/AdditionalJsonPropertiesConfigTest.java +++ b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/AdditionalJsonPropertiesConfigTest.java @@ -1,6 +1,6 @@ package io.quarkus.smallrye.health.test; -import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.hasItems; import static org.hamcrest.Matchers.is; import org.jboss.shrinkwrap.api.asset.EmptyAsset; @@ -11,7 +11,7 @@ import io.restassured.RestAssured; import io.restassured.parsing.Parser; -public class AdditionalJsonPropertiesConfigTest { +class AdditionalJsonPropertiesConfigTest { @RegisterExtension static final QuarkusUnitTest config = new QuarkusUnitTest() @@ -22,14 +22,14 @@ public class AdditionalJsonPropertiesConfigTest { .overrideConfigKey("quarkus.smallrye-health.additional.property.testProp2", "testValue2"); @Test - public void testAdditionalJsonPropertyInclusions() { + void testAdditionalJsonPropertyInclusions() { try { RestAssured.defaultParser = Parser.JSON; RestAssured.when().get("/q/health").then() .body("status", is("UP"), - "checks.size()", is(1), - "checks.status", contains("UP"), - "checks.name", contains("basic"), + "checks.size()", is(2), + "checks.status", hasItems("UP", "UP"), + "checks.name", hasItems("basic", "Graceful Shutdown"), "testProp1", is("testValue1"), "testProp2", is("testValue2")); } finally { diff --git a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/AsyncDispatchedThreadTest.java b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/AsyncDispatchedThreadTest.java index 5030989f53c5e6..873a438c2b50cf 100644 --- a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/AsyncDispatchedThreadTest.java +++ b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/AsyncDispatchedThreadTest.java @@ -1,6 +1,7 @@ package io.quarkus.smallrye.health.test; import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.hasItems; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.stringContainsInOrder; @@ -20,7 +21,7 @@ import io.smallrye.health.api.AsyncHealthCheck; import io.smallrye.mutiny.Uni; -public class AsyncDispatchedThreadTest { +class AsyncDispatchedThreadTest { @RegisterExtension static final QuarkusUnitTest config = new QuarkusUnitTest() @@ -29,7 +30,7 @@ public class AsyncDispatchedThreadTest { .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml")); @Test - public void check() { + void check() { RestAssured.when().get("/q/health/live").then() .body("status", is("UP"), "checks.status", contains("UP"), @@ -40,11 +41,14 @@ public void check() { RestAssured.when().get("/q/health/ready").then() .body("status", is("UP"), - "checks.status", contains("UP"), - "checks.name", contains("my-readiness-check"), - "checks.data.thread[0]", stringContainsInOrder("loop"), - "checks.data.thread[0]", not(stringContainsInOrder("executor-thread")), - "checks.data.request[0]", is(true)); + "checks.size()", is(2), + "checks.status", hasItems("UP", "UP"), + "checks.name", hasItems("my-readiness-check", "Graceful Shutdown"), + "checks.findAll { it.name == 'my-readiness-check' }.size()", is(1), + "checks.findAll { it.name = 'my-readiness-check' }.data.thread[0]", stringContainsInOrder("loop"), + "checks.findAll { it.name = 'my-readiness-check' }.data.thread[0]", + not(stringContainsInOrder("executor-thread")), + "checks.findAll { it.name = 'my-readiness-check' }.data.request[0]", is(true)); } @ApplicationScoped diff --git a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/BlockingNonBlockingTest.java b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/BlockingNonBlockingTest.java index d1ef2e076d5935..ebbbb336bb1aea 100644 --- a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/BlockingNonBlockingTest.java +++ b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/BlockingNonBlockingTest.java @@ -1,7 +1,7 @@ package io.quarkus.smallrye.health.test; import static io.restassured.RestAssured.given; -import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.hasItems; import static org.hamcrest.Matchers.is; import java.time.Duration; @@ -24,7 +24,7 @@ import io.smallrye.health.SmallRyeHealthReporter; import io.smallrye.mutiny.Uni; -public class BlockingNonBlockingTest { +class BlockingNonBlockingTest { @RegisterExtension static final QuarkusUnitTest config = new QuarkusUnitTest() @@ -33,7 +33,7 @@ public class BlockingNonBlockingTest { .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml")); @Test - public void testRegisterHealthOnBlockingThreadStep1() { + void testRegisterHealthOnBlockingThreadStep1() { // initial startup health blocking call on worker thread given() .when().get("/start-health") @@ -45,8 +45,8 @@ public void testRegisterHealthOnBlockingThreadStep1() { for (int i = 0; i < 3; i++) { RestAssured.when().get("/q/health").then() .body("status", is("UP"), - "checks.status", contains("UP"), - "checks.name", contains("blocking")); + "checks.status", hasItems("UP", "UP"), + "checks.name", hasItems("blocking", "Graceful Shutdown")); } } finally { RestAssured.reset(); diff --git a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/DefaultHealthGroupTest.java b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/DefaultHealthGroupTest.java index a750c84e234b4c..cfa65cba1a1afe 100644 --- a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/DefaultHealthGroupTest.java +++ b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/DefaultHealthGroupTest.java @@ -13,7 +13,7 @@ import io.restassured.RestAssured; import io.restassured.parsing.Parser; -public class DefaultHealthGroupTest { +class DefaultHealthGroupTest { @RegisterExtension static final QuarkusUnitTest config = new QuarkusUnitTest() @@ -23,14 +23,14 @@ public class DefaultHealthGroupTest { .overrideConfigKey("quarkus.smallrye-health.default-health-group", "my-default-health-group"); @Test - public void testDefaultHealthGroup() { + void testDefaultHealthGroup() { try { RestAssured.defaultParser = Parser.JSON; RestAssured.when().get("/q/health/group/my-default-health-group").then() .body("status", is("UP"), - "checks.size()", is(1), - "checks.status", contains("UP"), - "checks.name", contains("basic")); + "checks.size()", is(2), + "checks.status", hasItems("UP", "UP"), + "checks.name", hasItems("basic", "Graceful Shutdown")); RestAssured.when().get("/q/health/group/test-group").then() .body("status", is("UP"), @@ -40,9 +40,9 @@ public void testDefaultHealthGroup() { RestAssured.when().get("/q/health/group").then() .body("status", is("UP"), - "checks.size()", is(2), - "checks.status", hasItems("UP", "UP"), - "checks.name", hasItems("basic", HealthGroupCheck.class.getName())); + "checks.size()", is(3), + "checks.status", hasItems("UP", "UP", "UP"), + "checks.name", hasItems("basic", HealthGroupCheck.class.getName(), "Graceful Shutdown")); } finally { RestAssured.reset(); } diff --git a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/DisableHealthCheckTest.java b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/DisableHealthCheckTest.java index b24269014ab808..1e3321ce06d803 100644 --- a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/DisableHealthCheckTest.java +++ b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/DisableHealthCheckTest.java @@ -1,5 +1,6 @@ package io.quarkus.smallrye.health.test; +import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.is; import org.jboss.shrinkwrap.api.asset.EmptyAsset; @@ -10,7 +11,7 @@ import io.restassured.RestAssured; import io.restassured.parsing.Parser; -public class DisableHealthCheckTest { +class DisableHealthCheckTest { @RegisterExtension static final QuarkusUnitTest config = new QuarkusUnitTest() @@ -21,12 +22,13 @@ public class DisableHealthCheckTest { + BasicHealthCheck.class.getName() + "\".enabled", "false"); @Test - public void testHealthCheckDisabled() { + void testHealthCheckDisabled() { try { RestAssured.defaultParser = Parser.JSON; RestAssured.when().get("/q/health").then() .body("status", is("UP"), - "checks.size()", is(0)); + "checks.size()", is(1), + "checks.name", contains("Graceful Shutdown")); } finally { RestAssured.reset(); } diff --git a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/DispatchedThreadTest.java b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/DispatchedThreadTest.java index b36e48a87b1f75..863efe6fb7e500 100644 --- a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/DispatchedThreadTest.java +++ b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/DispatchedThreadTest.java @@ -1,6 +1,7 @@ package io.quarkus.smallrye.health.test; import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.hasItems; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.stringContainsInOrder; @@ -19,7 +20,7 @@ import io.quarkus.test.QuarkusUnitTest; import io.restassured.RestAssured; -public class DispatchedThreadTest { +class DispatchedThreadTest { @RegisterExtension static final QuarkusUnitTest config = new QuarkusUnitTest() @@ -28,7 +29,7 @@ public class DispatchedThreadTest { .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml")); @Test - public void check() { + void check() { RestAssured.when().get("/q/health/live").then() .body("status", is("UP"), "checks.status", contains("UP"), @@ -39,11 +40,13 @@ public void check() { RestAssured.when().get("/q/health/ready").then() .body("status", is("UP"), - "checks.status", contains("UP"), - "checks.name", contains("my-readiness-check"), - "checks.data.thread[0]", stringContainsInOrder("executor-thread"), - "checks.data.thread[0]", not(stringContainsInOrder("loop")), - "checks.data.request[0]", is(true)); + "checks.size()", is(2), + "checks.status", hasItems("UP", "UP"), + "checks.name", hasItems("my-readiness-check", "Graceful Shutdown"), + "checks.findAll { it.name == 'my-readiness-check' }.data.thread[0]", + stringContainsInOrder("executor-thread"), + "checks.findAll { it.name == 'my-readiness-check' }.data.thread[0]", not(stringContainsInOrder("loop")), + "checks.findAll { it.name == 'my-readiness-check' }.data.request[0]", is(true)); } @ApplicationScoped diff --git a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/ExpectedBeansUnitTest.java b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/ExpectedBeansUnitTest.java index 54239eb3f9862e..495c742bd41a97 100644 --- a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/ExpectedBeansUnitTest.java +++ b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/ExpectedBeansUnitTest.java @@ -1,6 +1,5 @@ package io.quarkus.smallrye.health.test; -import jakarta.enterprise.inject.Any; import jakarta.enterprise.inject.Instance; import jakarta.inject.Inject; @@ -14,10 +13,11 @@ import org.junit.jupiter.api.extension.RegisterExtension; import io.quarkus.test.QuarkusUnitTest; +import io.smallrye.common.annotation.Identifier; import io.smallrye.health.SmallRyeHealthReporter; import io.smallrye.health.api.HealthGroup; -public class ExpectedBeansUnitTest { +class ExpectedBeansUnitTest { @RegisterExtension static final QuarkusUnitTest config = new QuarkusUnitTest() @@ -25,8 +25,8 @@ public class ExpectedBeansUnitTest { .addClasses(FailingHealthCheck.class) .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml")); @Inject - @Any - Instance<HealthCheck> checks; + @Identifier("failing") + Instance<HealthCheck> failingChecks; @Inject Instance<SmallRyeHealthReporter> reporters; @@ -39,7 +39,7 @@ private boolean isUnique(Instance<?> instances) { * Test that SmallRye Health Reporter is registered and unique */ @Test - public void testReporterIsUnique() { + void testReporterIsUnique() { Assertions.assertTrue(isUnique(reporters)); } @@ -47,40 +47,40 @@ public void testReporterIsUnique() { * Test that HealthCheck procedure beans are registered once */ @Test - public void testHealthCheckIsUnique() { - Assertions.assertTrue(isUnique(checks)); + void testHealthCheckIsUnique() { + Assertions.assertTrue(isUnique(failingChecks)); } /** * Test metadata on HealthCheck procedure beans */ @Test - public void testHealthCheckMetadata() { + void testHealthCheckMetadata() { Instance<HealthCheck> selects; - selects = checks.select(Liveness.Literal.INSTANCE); + selects = failingChecks.select(Liveness.Literal.INSTANCE); Assertions.assertTrue(isUnique(selects)); - selects = checks.select(Readiness.Literal.INSTANCE); + selects = failingChecks.select(Readiness.Literal.INSTANCE, Identifier.Literal.of("failing")); Assertions.assertTrue(isUnique(selects)); - selects = checks.select(Startup.Literal.INSTANCE); + selects = failingChecks.select(Startup.Literal.INSTANCE); Assertions.assertTrue(isUnique(selects)); - selects = checks.select(HealthGroup.Literal.of("group1")); + selects = failingChecks.select(HealthGroup.Literal.of("group1")); Assertions.assertTrue(isUnique(selects)); - selects = checks.select(HealthGroup.Literal.of("group2")); + selects = failingChecks.select(HealthGroup.Literal.of("group2")); Assertions.assertTrue(isUnique(selects)); - selects = checks.select(Liveness.Literal.INSTANCE, + selects = failingChecks.select(Liveness.Literal.INSTANCE, Readiness.Literal.INSTANCE, Startup.Literal.INSTANCE, HealthGroup.Literal.of("group1"), HealthGroup.Literal.of("group2")); Assertions.assertTrue(isUnique(selects)); - Assertions.assertTrue(checks.select(HealthGroup.Literal.of("group3")).isUnsatisfied()); + Assertions.assertTrue(failingChecks.select(HealthGroup.Literal.of("group3")).isUnsatisfied()); } diff --git a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/FailingHealthCheck.java b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/FailingHealthCheck.java index 0c49c56be7b76d..8612ccd5a7af35 100644 --- a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/FailingHealthCheck.java +++ b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/FailingHealthCheck.java @@ -12,6 +12,7 @@ import org.eclipse.microprofile.health.Readiness; import org.eclipse.microprofile.health.Startup; +import io.smallrye.common.annotation.Identifier; import io.smallrye.health.api.HealthGroup; @Dependent @@ -20,6 +21,7 @@ @Startup @HealthGroup("group1") @HealthGroup("group2") +@Identifier("failing") public class FailingHealthCheck implements HealthCheck { @Override diff --git a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/FailingUnitTest.java b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/FailingUnitTest.java index 4c069818555f92..30114de37ed3f8 100644 --- a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/FailingUnitTest.java +++ b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/FailingUnitTest.java @@ -17,20 +17,25 @@ import io.quarkus.test.QuarkusUnitTest; import io.restassured.RestAssured; +import io.smallrye.common.annotation.Identifier; -public class FailingUnitTest { +class FailingUnitTest { @RegisterExtension static final QuarkusUnitTest config = new QuarkusUnitTest() .withApplicationRoot((jar) -> jar .addClasses(FailingHealthCheck.class) .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml")); + @Inject + @Identifier("failing") + Instance<HealthCheck> failingChecks; + @Inject @Any - Instance<HealthCheck> checks; + Instance<HealthCheck> anyChecks; @Test - public void testHealthServlet() { + void testHealthServlet() { RestAssured.when().get("/q/health/live").then().statusCode(503); RestAssured.when().get("/q/health/ready").then().statusCode(503); RestAssured.when().get("/q/health/started").then().statusCode(503); @@ -38,12 +43,17 @@ public void testHealthServlet() { } @Test - public void testHealthBeans() { - List<HealthCheck> check = new ArrayList<>(); - for (HealthCheck i : checks) { - check.add(i); + void testHealthBeans() { + List<HealthCheck> failing = new ArrayList<>(); + for (HealthCheck i : failingChecks) { + failing.add(i); + } + assertEquals(1, failing.size()); + List<HealthCheck> any = new ArrayList<>(); + assertEquals(HealthCheckResponse.Status.DOWN, failing.get(0).call().getStatus()); + for (HealthCheck i : anyChecks) { + any.add(i); } - assertEquals(1, check.size()); - assertEquals(HealthCheckResponse.Status.DOWN, check.get(0).call().getStatus()); + assertEquals(2, any.size()); } } diff --git a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthCheckContextPropagationTest.java b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthCheckContextPropagationTest.java index 0d843d56cb9011..30961ca0fd2d20 100644 --- a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthCheckContextPropagationTest.java +++ b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthCheckContextPropagationTest.java @@ -1,7 +1,7 @@ package io.quarkus.smallrye.health.test; import static io.restassured.RestAssured.when; -import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.hasItems; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; @@ -23,7 +23,7 @@ import io.restassured.RestAssured; import io.restassured.parsing.Parser; -public class HealthCheckContextPropagationTest { +class HealthCheckContextPropagationTest { @RegisterExtension static final QuarkusUnitTest config = new QuarkusUnitTest() @@ -32,22 +32,25 @@ public class HealthCheckContextPropagationTest { .addClasses(RequestScopedBean.class, ContextualHC.class)); @Test - public void testContextPropagatedToHealthChecks() { + void testContextPropagatedToHealthChecks() { try { RestAssured.defaultParser = Parser.JSON; String firstResponse = when().get("/q/health").then() .body("status", is("UP"), - "checks.status", contains("UP"), - "checks.name", contains(ContextualHC.class.getName()), - "checks.data", is(notNullValue())) + "checks.size()", is(2), + "checks.status", hasItems("UP", "UP"), + "checks.name", hasItems(ContextualHC.class.getName(), "Graceful Shutdown"), + "checks.findAll { it.name == '" + ContextualHC.class.getName() + "' }.data", is(notNullValue())) .extract().response().jsonPath().getString("checks.data.request-scoped-instance"); String secondResponse = when().get("/q/health").then() - .extract().response().jsonPath().getString("checks.data.request-scoped-instance"); + .extract().response().jsonPath().getString("checks.findAll { it.name == '" + ContextualHC.class.getName() + + "' }.data.request-scoped-instance"); String thirdResponse = when().get("/q/health").then() - .extract().response().jsonPath().getString("checks.data.request-scoped-instance"); + .extract().response().jsonPath().getString("checks.findAll { it.name == '" + ContextualHC.class.getName() + + "' }.data.request-scoped-instance"); Assertions.assertNotEquals(firstResponse, secondResponse, getMessage("first", "second")); Assertions.assertNotEquals(firstResponse, thirdResponse, getMessage("first", "third")); diff --git a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthCheckDefaultScopeTest.java b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthCheckDefaultScopeTest.java index 7aac837a9b72f7..f01f8774125dc5 100644 --- a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthCheckDefaultScopeTest.java +++ b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthCheckDefaultScopeTest.java @@ -5,12 +5,12 @@ import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.hasItems; import static org.hamcrest.Matchers.is; import java.lang.annotation.Retention; import java.lang.annotation.Target; +import java.util.concurrent.atomic.AtomicInteger; import jakarta.enterprise.inject.Stereotype; import jakarta.inject.Named; @@ -25,7 +25,7 @@ import io.restassured.RestAssured; import io.restassured.parsing.Parser; -public class HealthCheckDefaultScopeTest { +class HealthCheckDefaultScopeTest { @RegisterExtension static final QuarkusUnitTest config = new QuarkusUnitTest() @@ -33,18 +33,18 @@ public class HealthCheckDefaultScopeTest { .addClasses(NoScopeCheck.class, NoScopeStereotypeWithoutScopeCheck.class, MyStereotype.class)); @Test - public void testHealth() { + void testHealth() { // the health check does not set a content type, so we need to force the parser try { RestAssured.defaultParser = Parser.JSON; when().get("/q/health/live").then() .body("status", is("UP"), - "checks.status", contains("UP", "UP"), - "checks.name", containsInAnyOrder("noScope", "noScopeStereotype")); + "checks.status", hasItems("UP", "UP"), + "checks.name", hasItems("noScope", "noScopeStereotype")); when().get("/q/health/live").then() .body("status", is("DOWN"), - "checks.status", contains("DOWN", "DOWN"), - "checks.name", containsInAnyOrder("noScope", "noScopeStereotype")); + "checks.status", hasItems("DOWN", "DOWN"), + "checks.name", hasItems("noScope", "noScopeStereotype")); } finally { RestAssured.reset(); } @@ -54,11 +54,11 @@ public void testHealth() { @Liveness static class NoScopeCheck implements HealthCheck { - volatile int counter = 0; + AtomicInteger counter = new AtomicInteger(0); @Override public HealthCheckResponse call() { - if (++counter > 1) { + if (counter.incrementAndGet() > 1) { return HealthCheckResponse.builder().down().name("noScope").build(); } return HealthCheckResponse.builder().up().name("noScope").build(); @@ -70,11 +70,11 @@ public HealthCheckResponse call() { @Liveness static class NoScopeStereotypeWithoutScopeCheck implements HealthCheck { - volatile int counter = 0; + AtomicInteger counter = new AtomicInteger(0); @Override public HealthCheckResponse call() { - if (++counter > 1) { + if (counter.incrementAndGet() > 1) { return HealthCheckResponse.builder().down().name("noScopeStereotype").build(); } return HealthCheckResponse.builder().up().name("noScopeStereotype").build(); diff --git a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthCheckOnManagementInterfaceDisabledTest.java b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthCheckOnManagementInterfaceDisabledTest.java index 33f48e3d16cbbc..4bde45df2a98ac 100644 --- a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthCheckOnManagementInterfaceDisabledTest.java +++ b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthCheckOnManagementInterfaceDisabledTest.java @@ -2,9 +2,11 @@ import static io.restassured.RestAssured.when; import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.hasItems; import static org.hamcrest.Matchers.is; +import java.util.concurrent.atomic.AtomicInteger; + import org.eclipse.microprofile.health.HealthCheck; import org.eclipse.microprofile.health.HealthCheckResponse; import org.eclipse.microprofile.health.Liveness; @@ -15,7 +17,7 @@ import io.restassured.RestAssured; import io.restassured.parsing.Parser; -public class HealthCheckOnManagementInterfaceDisabledTest { +class HealthCheckOnManagementInterfaceDisabledTest { @RegisterExtension static final QuarkusUnitTest config = new QuarkusUnitTest() @@ -24,17 +26,17 @@ public class HealthCheckOnManagementInterfaceDisabledTest { .overrideConfigKey("quarkus.management.enabled", "false"); @Test - public void testHealth() { + void testHealth() { try { RestAssured.defaultParser = Parser.JSON; when().get("/q/health/live").then() .body("status", is("UP"), "checks.status", contains("UP"), - "checks.name", containsInAnyOrder("my-check")); + "checks.name", hasItems("my-check")); when().get("/q/health/live").then() .body("status", is("DOWN"), "checks.status", contains("DOWN"), - "checks.name", containsInAnyOrder("my-check")); + "checks.name", hasItems("my-check")); } finally { RestAssured.reset(); } @@ -43,11 +45,11 @@ public void testHealth() { @Liveness static class MyCheck implements HealthCheck { - volatile int counter = 0; + AtomicInteger counter = new AtomicInteger(0); @Override public HealthCheckResponse call() { - if (++counter > 1) { + if (counter.incrementAndGet() > 1) { return HealthCheckResponse.builder().down().name("my-check").build(); } return HealthCheckResponse.builder().up().name("my-check").build(); diff --git a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthCheckOnManagementInterfaceTest.java b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthCheckOnManagementInterfaceTest.java index 8a5a168ff3597b..377c923a19523f 100644 --- a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthCheckOnManagementInterfaceTest.java +++ b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthCheckOnManagementInterfaceTest.java @@ -1,11 +1,11 @@ package io.quarkus.smallrye.health.test; -import static io.restassured.RestAssured.get; import static io.restassured.RestAssured.when; import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.is; +import java.util.concurrent.atomic.AtomicInteger; + import org.eclipse.microprofile.health.HealthCheck; import org.eclipse.microprofile.health.HealthCheckResponse; import org.eclipse.microprofile.health.Liveness; @@ -16,7 +16,7 @@ import io.restassured.RestAssured; import io.restassured.parsing.Parser; -public class HealthCheckOnManagementInterfaceTest { +class HealthCheckOnManagementInterfaceTest { @RegisterExtension static final QuarkusUnitTest config = new QuarkusUnitTest() @@ -25,17 +25,17 @@ public class HealthCheckOnManagementInterfaceTest { .overrideConfigKey("quarkus.management.enabled", "true"); @Test - public void testHealth() { + void testHealth() { try { RestAssured.defaultParser = Parser.JSON; when().get("http://0.0.0.0:9001/q/health/live").then() .body("status", is("UP"), "checks.status", contains("UP"), - "checks.name", containsInAnyOrder("my-check")); + "checks.name", contains("my-check")); when().get("http://0.0.0.0:9001/q/health/live").then() .body("status", is("DOWN"), "checks.status", contains("DOWN"), - "checks.name", containsInAnyOrder("my-check")); + "checks.name", contains("my-check")); } finally { RestAssured.reset(); } @@ -44,11 +44,11 @@ public void testHealth() { @Liveness static class MyCheck implements HealthCheck { - volatile int counter = 0; + AtomicInteger counter = new AtomicInteger(0); @Override public HealthCheckResponse call() { - if (++counter > 1) { + if (counter.incrementAndGet() > 1) { return HealthCheckResponse.builder().down().name("my-check").build(); } return HealthCheckResponse.builder().up().name("my-check").build(); diff --git a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthCheckOnManagementInterfaceWithAbsoluteRootPathTest.java b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthCheckOnManagementInterfaceWithAbsoluteRootPathTest.java index eac5c437bcc6e7..04d715ab3560d2 100644 --- a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthCheckOnManagementInterfaceWithAbsoluteRootPathTest.java +++ b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthCheckOnManagementInterfaceWithAbsoluteRootPathTest.java @@ -2,9 +2,10 @@ import static io.restassured.RestAssured.when; import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.is; +import java.util.concurrent.atomic.AtomicInteger; + import org.eclipse.microprofile.health.HealthCheck; import org.eclipse.microprofile.health.HealthCheckResponse; import org.eclipse.microprofile.health.Liveness; @@ -15,7 +16,7 @@ import io.restassured.RestAssured; import io.restassured.parsing.Parser; -public class HealthCheckOnManagementInterfaceWithAbsoluteRootPathTest { +class HealthCheckOnManagementInterfaceWithAbsoluteRootPathTest { @RegisterExtension static final QuarkusUnitTest config = new QuarkusUnitTest() @@ -25,17 +26,17 @@ public class HealthCheckOnManagementInterfaceWithAbsoluteRootPathTest { .overrideConfigKey("quarkus.smallrye-health.root-path", "/sante"); @Test - public void testHealth() { + void testHealth() { try { RestAssured.defaultParser = Parser.JSON; when().get("http://0.0.0.0:9001/sante/live").then() .body("status", is("UP"), "checks.status", contains("UP"), - "checks.name", containsInAnyOrder("my-check")); + "checks.name", contains("my-check")); when().get("http://0.0.0.0:9001/sante/live").then() .body("status", is("DOWN"), "checks.status", contains("DOWN"), - "checks.name", containsInAnyOrder("my-check")); + "checks.name", contains("my-check")); } finally { RestAssured.reset(); } @@ -44,11 +45,11 @@ public void testHealth() { @Liveness static class MyCheck implements HealthCheck { - volatile int counter = 0; + AtomicInteger counter = new AtomicInteger(0); @Override public HealthCheckResponse call() { - if (++counter > 1) { + if (counter.incrementAndGet() > 1) { return HealthCheckResponse.builder().down().name("my-check").build(); } return HealthCheckResponse.builder().up().name("my-check").build(); diff --git a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthCheckOnManagementInterfaceWithRelativeRootPathTest.java b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthCheckOnManagementInterfaceWithRelativeRootPathTest.java index 24143522a39bdf..be6c4ea75715b0 100644 --- a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthCheckOnManagementInterfaceWithRelativeRootPathTest.java +++ b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthCheckOnManagementInterfaceWithRelativeRootPathTest.java @@ -2,9 +2,10 @@ import static io.restassured.RestAssured.when; import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.is; +import java.util.concurrent.atomic.AtomicInteger; + import org.eclipse.microprofile.health.HealthCheck; import org.eclipse.microprofile.health.HealthCheckResponse; import org.eclipse.microprofile.health.Liveness; @@ -15,7 +16,7 @@ import io.restassured.RestAssured; import io.restassured.parsing.Parser; -public class HealthCheckOnManagementInterfaceWithRelativeRootPathTest { +class HealthCheckOnManagementInterfaceWithRelativeRootPathTest { @RegisterExtension static final QuarkusUnitTest config = new QuarkusUnitTest() @@ -26,17 +27,17 @@ public class HealthCheckOnManagementInterfaceWithRelativeRootPathTest { .overrideConfigKey("quarkus.smallrye-health.root-path", "sante"); @Test - public void testHealth() { + void testHealth() { try { RestAssured.defaultParser = Parser.JSON; when().get("http://0.0.0.0:9001/management/sante/live").then() .body("status", is("UP"), "checks.status", contains("UP"), - "checks.name", containsInAnyOrder("my-check")); + "checks.name", contains("my-check")); when().get("http://0.0.0.0:9001/management/sante/live").then() .body("status", is("DOWN"), "checks.status", contains("DOWN"), - "checks.name", containsInAnyOrder("my-check")); + "checks.name", contains("my-check")); } finally { RestAssured.reset(); } @@ -45,11 +46,11 @@ public void testHealth() { @Liveness static class MyCheck implements HealthCheck { - volatile int counter = 0; + AtomicInteger counter = new AtomicInteger(0); @Override public HealthCheckResponse call() { - if (++counter > 1) { + if (counter.incrementAndGet() > 1) { return HealthCheckResponse.builder().down().name("my-check").build(); } return HealthCheckResponse.builder().up().name("my-check").build(); diff --git a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthCheckProducerDefaultScopeTest.java b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthCheckProducerDefaultScopeTest.java index dadbfee2acc6cf..7a56672f55a3f7 100644 --- a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthCheckProducerDefaultScopeTest.java +++ b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthCheckProducerDefaultScopeTest.java @@ -1,8 +1,7 @@ package io.quarkus.smallrye.health.test; import static io.restassured.RestAssured.when; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.hasItems; import static org.hamcrest.Matchers.is; import java.util.concurrent.atomic.AtomicInteger; @@ -19,7 +18,7 @@ import io.restassured.RestAssured; import io.restassured.parsing.Parser; -public class HealthCheckProducerDefaultScopeTest { +class HealthCheckProducerDefaultScopeTest { @RegisterExtension static final QuarkusUnitTest config = new QuarkusUnitTest() @@ -27,18 +26,18 @@ public class HealthCheckProducerDefaultScopeTest { .addClasses(HealthCheckProducers.class)); @Test - public void testHealth() { + void testHealth() { // the health check does not set a content type, so we need to force the parser try { RestAssured.defaultParser = Parser.JSON; when().get("/q/health/ready").then() .body("status", is("UP"), - "checks.status", contains("UP", "UP"), - "checks.name", containsInAnyOrder("alpha1", "bravo1")); + "checks.status", hasItems("UP", "UP", "UP"), + "checks.name", hasItems("alpha1", "bravo1", "Graceful Shutdown")); when().get("/q/health/ready").then() .body("status", is("UP"), - "checks.status", contains("UP", "UP"), - "checks.name", containsInAnyOrder("alpha1", "bravo2")); + "checks.status", hasItems("UP", "UP", "UP"), + "checks.name", hasItems("alpha1", "bravo2", "Graceful Shutdown")); } finally { RestAssured.reset(); } @@ -51,6 +50,7 @@ static class HealthCheckProducers { // No scope - @Singleton is used by default @Readiness + @SuppressWarnings("unused") HealthCheck alpha() { int idx = ALPHA_COUNTER.incrementAndGet(); return () -> HealthCheckResponse.builder().up().name("alpha" + idx).build(); @@ -58,6 +58,7 @@ HealthCheck alpha() { @RequestScoped @Readiness + @SuppressWarnings("unused") HealthCheck bravo() { int idx = BRAVO_COUNTER.incrementAndGet(); return () -> HealthCheckResponse.builder().up().name("bravo" + idx).build(); diff --git a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthOpenAPITest.java b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthOpenAPITest.java index dd69013e68ddda..b0b33b1ccc1897 100644 --- a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthOpenAPITest.java +++ b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthOpenAPITest.java @@ -9,7 +9,7 @@ import io.quarkus.test.QuarkusUnitTest; import io.restassured.RestAssured; -public class HealthOpenAPITest { +class HealthOpenAPITest { private static final String OPEN_API_PATH = "/q/openapi"; @@ -22,7 +22,7 @@ public class HealthOpenAPITest { .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml")); @Test - public void testOpenApiPathAccessResource() { + void testOpenApiPathAccessResource() { RestAssured.given().header("Accept", "application/json") .when().get(OPEN_API_PATH) diff --git a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthUnitTest.java b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthUnitTest.java index a5a4a42002b528..6fa2b86c6010b7 100644 --- a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthUnitTest.java +++ b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/HealthUnitTest.java @@ -11,7 +11,7 @@ import io.restassured.RestAssured; import io.restassured.parsing.Parser; -public class HealthUnitTest { +class HealthUnitTest { @RegisterExtension static final QuarkusUnitTest config = new QuarkusUnitTest() @@ -20,7 +20,7 @@ public class HealthUnitTest { .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml")); @Test - public void testHealth() { + void testHealth() { // the health check does not set a content type, so we need to force the parser try { RestAssured.defaultParser = Parser.JSON; diff --git a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/MaxHealthGroupTest.java b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/MaxHealthGroupTest.java index 7074da671b85d2..1e953008b4fedf 100644 --- a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/MaxHealthGroupTest.java +++ b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/MaxHealthGroupTest.java @@ -11,7 +11,7 @@ import io.restassured.RestAssured; import io.restassured.parsing.Parser; -public class MaxHealthGroupTest { +class MaxHealthGroupTest { @RegisterExtension static final QuarkusUnitTest config = new QuarkusUnitTest() @@ -21,7 +21,7 @@ public class MaxHealthGroupTest { .overrideConfigKey("quarkus.smallrye-health.max-group-registries-count", "3"); @Test - public void testMaxGroupRegistriesCreations() { + void testMaxGroupRegistriesCreations() { try { RestAssured.defaultParser = Parser.JSON; diff --git a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/StartedHealthCheckTest.java b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/StartedHealthCheckTest.java index 01008c1f9b3f39..603b11065a54a8 100644 --- a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/StartedHealthCheckTest.java +++ b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/StartedHealthCheckTest.java @@ -14,7 +14,7 @@ import io.restassured.RestAssured; import io.restassured.parsing.Parser; -public class StartedHealthCheckTest { +class StartedHealthCheckTest { @RegisterExtension static final QuarkusUnitTest config = new QuarkusUnitTest() @@ -22,7 +22,7 @@ public class StartedHealthCheckTest { .addClasses(StartupHC.class)); @Test - public void testStartup() { + void testStartup() { try { RestAssured.defaultParser = Parser.JSON; when().get("/q/health/started").then() diff --git a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/WellnessHealthCheckTest.java b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/WellnessHealthCheckTest.java index a138ceb7caaa3d..04f6d99dfc4579 100644 --- a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/WellnessHealthCheckTest.java +++ b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/WellnessHealthCheckTest.java @@ -14,7 +14,7 @@ import io.restassured.parsing.Parser; import io.smallrye.health.api.Wellness; -public class WellnessHealthCheckTest { +class WellnessHealthCheckTest { @RegisterExtension static final QuarkusUnitTest config = new QuarkusUnitTest() @@ -22,7 +22,7 @@ public class WellnessHealthCheckTest { .addClasses(WellnessHC.class)); @Test - public void testWellness() { + void testWellness() { try { RestAssured.defaultParser = Parser.JSON; when().get("/q/health/well").then() diff --git a/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/ShutdownReadinessListener.java b/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/ShutdownReadinessListener.java index 3a012853908b0e..2fd4a8c3938521 100644 --- a/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/ShutdownReadinessListener.java +++ b/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/ShutdownReadinessListener.java @@ -8,23 +8,18 @@ import io.quarkus.runtime.shutdown.ShutdownListener; /** - * listener that changes the readiness probe on pre-shudown + * listener that changes the readiness probe on pre-shutdown. * * Note that unless there is another preShutdown listener present * this will generally have no real effect, as after pre-shutdown * the HTTP endpoint will return service unavailable. - * - * TODO: We may want a timeout here, so the readiness probe will be down for a set timeout before shutdown continues */ public class ShutdownReadinessListener implements ShutdownListener { - @Override public void preShutdown(ShutdownNotification notification) { Instance<ShutdownReadinessCheck> instance = CDI.current().select(ShutdownReadinessCheck.class, Readiness.Literal.INSTANCE); - if (!instance.isUnsatisfied()) { - instance.get().shutdown(); - } + instance.get().shutdown(); notification.done(); } }