diff --git a/extensions/smallrye-health/deployment/pom.xml b/extensions/smallrye-health/deployment/pom.xml
index 500367c3c058d2..809b86543156c7 100644
--- a/extensions/smallrye-health/deployment/pom.xml
+++ b/extensions/smallrye-health/deployment/pom.xml
@@ -51,6 +51,11 @@
quarkus-junit5-internal
test
+
+ io.quarkus
+ quarkus-scheduler-deployment
+ test
+
io.rest-assured
rest-assured
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 3899c03b691693..69d292bd816340 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
@@ -5,7 +5,6 @@
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
-import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
@@ -217,7 +216,6 @@ public void defineHealthRoutes(BuildProducer routes,
.routeConfigKey("quarkus.smallrye-health.root-path")
.handler(new SmallRyeHealthHandler())
.displayOnNotFoundPage()
- .blockingRoute()
.build());
// Register the liveness handler
@@ -226,7 +224,6 @@ public void defineHealthRoutes(BuildProducer routes,
.nestedRoute(healthConfig.rootPath, healthConfig.livenessPath)
.handler(new SmallRyeLivenessHandler())
.displayOnNotFoundPage()
- .blockingRoute()
.build());
// Register the readiness handler
@@ -235,29 +232,14 @@ public void defineHealthRoutes(BuildProducer routes,
.nestedRoute(healthConfig.rootPath, healthConfig.readinessPath)
.handler(new SmallRyeReadinessHandler())
.displayOnNotFoundPage()
- .blockingRoute()
.build());
- // Find all health groups
- Set healthGroups = new HashSet<>();
- // with simple @HealthGroup annotations
- for (AnnotationInstance healthGroupAnnotation : index.getAnnotations(HEALTH_GROUP)) {
- healthGroups.add(healthGroupAnnotation.value().asString());
- }
- // with @HealthGroups repeatable annotations
- for (AnnotationInstance healthGroupsAnnotation : index.getAnnotations(HEALTH_GROUPS)) {
- for (AnnotationInstance healthGroupAnnotation : healthGroupsAnnotation.value().asNestedArray()) {
- healthGroups.add(healthGroupAnnotation.value().asString());
- }
- }
-
// Register the health group handlers
routes.produce(nonApplicationRootPathBuildItem.routeBuilder()
.management("quarkus.smallrye-health.management.enabled")
.nestedRoute(healthConfig.rootPath, healthConfig.groupPath)
.handler(new SmallRyeHealthGroupHandler())
.displayOnNotFoundPage()
- .blockingRoute()
.build());
SmallRyeIndividualHealthGroupHandler handler = new SmallRyeIndividualHealthGroupHandler();
@@ -266,7 +248,6 @@ public void defineHealthRoutes(BuildProducer routes,
.nestedRoute(healthConfig.rootPath, healthConfig.groupPath + "/*")
.handler(handler)
.displayOnNotFoundPage()
- .blockingRoute()
.build());
// Register the wellness handler
@@ -275,7 +256,6 @@ public void defineHealthRoutes(BuildProducer routes,
.nestedRoute(healthConfig.rootPath, healthConfig.wellnessPath)
.handler(new SmallRyeWellnessHandler())
.displayOnNotFoundPage()
- .blockingRoute()
.build());
// Register the startup handler
@@ -284,7 +264,6 @@ public void defineHealthRoutes(BuildProducer routes,
.nestedRoute(healthConfig.rootPath, healthConfig.startupPath)
.handler(new SmallRyeStartupHandler())
.displayOnNotFoundPage()
- .blockingRoute()
.build());
}
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
new file mode 100644
index 00000000000000..05b4da5bc36117
--- /dev/null
+++ b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/BlockingNonBlockingTest.java
@@ -0,0 +1,106 @@
+package io.quarkus.smallrye.health.test;
+
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+
+import org.eclipse.microprofile.health.HealthCheck;
+import org.eclipse.microprofile.health.HealthCheckResponse;
+import org.eclipse.microprofile.health.Liveness;
+import org.jboss.shrinkwrap.api.asset.EmptyAsset;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import io.quarkus.scheduler.Scheduled;
+import io.quarkus.test.InMemoryLogHandler;
+import io.quarkus.test.QuarkusUnitTest;
+import io.restassured.RestAssured;
+import io.restassured.parsing.Parser;
+import io.smallrye.health.SmallRyeHealthReporter;
+
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+public class BlockingNonBlockingTest {
+
+ private static final java.util.logging.Logger rootLogger = java.util.logging.LogManager.getLogManager()
+ .getLogger("io.vertx.core");
+ private static final InMemoryLogHandler inMemoryLogHandler = new InMemoryLogHandler(
+ record -> record.getLevel().intValue() >= java.util.logging.Level.WARNING.intValue());
+
+ @BeforeEach
+ public void setLogHandler() {
+ inMemoryLogHandler.getRecords().clear();
+ rootLogger.addHandler(inMemoryLogHandler);
+ }
+
+ @RegisterExtension
+ static final QuarkusUnitTest config = new QuarkusUnitTest()
+ .withApplicationRoot((jar) -> jar
+ .addClasses(BlockingHealthCheck.class, SchedulerBean.class)
+ .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml"));
+
+ @Test
+ public void testRegisterHealthOnBlockingThreadStep1() {
+ // wait for the initial scheduler call to finish
+ try {
+ Thread.sleep(5000);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+
+ try {
+ RestAssured.defaultParser = Parser.JSON;
+ // repeat the call a few times since the block isn't always logged
+ 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"));
+ }
+ } finally {
+ RestAssured.reset();
+ }
+
+ if (!inMemoryLogHandler.getRecords().isEmpty()) {
+ LogRecord logRecord = inMemoryLogHandler.getRecords().get(0);
+ assertEquals(Level.WARNING, logRecord.getLevel());
+ assertFalse(logRecord.getMessage().contains("has been blocked for"),
+ "The blocking health check ran on eventloop thread");
+ }
+ }
+
+ @Liveness
+ static final class BlockingHealthCheck implements HealthCheck {
+ @Override
+ public HealthCheckResponse call() {
+ // block for 3s which is more than allowed default blocking duration of eventloop (2s)
+ try {
+ Thread.sleep(3000);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ return HealthCheckResponse.up("blocking");
+ }
+ }
+
+ @ApplicationScoped
+ static final class SchedulerBean {
+
+ @Inject
+ SmallRyeHealthReporter smallRyeHealthReporter;
+
+ @Scheduled(every = "20s")
+ public void registerHealth() {
+ smallRyeHealthReporter.getHealth();
+ }
+ }
+}
diff --git a/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/QuarkusAsyncHealthCheckFactory.java b/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/QuarkusAsyncHealthCheckFactory.java
index de343b4f38b85e..cfec52c933b1b3 100644
--- a/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/QuarkusAsyncHealthCheckFactory.java
+++ b/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/QuarkusAsyncHealthCheckFactory.java
@@ -5,7 +5,6 @@
import org.eclipse.microprofile.health.HealthCheck;
import org.eclipse.microprofile.health.HealthCheckResponse;
-import io.quarkus.runtime.BlockingOperationControl;
import io.smallrye.health.AsyncHealthCheckFactory;
import io.smallrye.health.api.AsyncHealthCheck;
import io.smallrye.mutiny.Uni;
@@ -28,14 +27,12 @@ public QuarkusAsyncHealthCheckFactory(Vertx vertx) {
@Override
public Uni callSync(HealthCheck healthCheck) {
Uni healthCheckResponseUni = super.callSync(healthCheck);
- return BlockingOperationControl.isBlockingAllowed() ? healthCheckResponseUni
- : healthCheckResponseUni.runSubscriptionOn(MutinyHelper.blockingExecutor(vertx, false));
+ return healthCheckResponseUni.runSubscriptionOn(MutinyHelper.blockingExecutor(vertx, false));
}
@Override
public Uni callAsync(AsyncHealthCheck asyncHealthCheck) {
Uni healthCheckResponseUni = super.callAsync(asyncHealthCheck);
- return !BlockingOperationControl.isBlockingAllowed() ? healthCheckResponseUni
- : healthCheckResponseUni.runSubscriptionOn(MutinyHelper.executor(vertx));
+ return healthCheckResponseUni.runSubscriptionOn(MutinyHelper.executor(vertx));
}
}
diff --git a/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeHealthGroupHandler.java b/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeHealthGroupHandler.java
index 84c5c6fa62d0cb..95b87746c1b088 100644
--- a/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeHealthGroupHandler.java
+++ b/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeHealthGroupHandler.java
@@ -2,12 +2,13 @@
import io.smallrye.health.SmallRyeHealth;
import io.smallrye.health.SmallRyeHealthReporter;
+import io.smallrye.mutiny.Uni;
import io.vertx.ext.web.RoutingContext;
public class SmallRyeHealthGroupHandler extends SmallRyeHealthHandlerBase {
@Override
- protected SmallRyeHealth getHealth(SmallRyeHealthReporter reporter, RoutingContext ctx) {
- return reporter.getHealthGroups();
+ protected Uni getHealth(SmallRyeHealthReporter reporter, RoutingContext ctx) {
+ return reporter.getHealthGroupsAsync();
}
}
diff --git a/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeHealthHandler.java b/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeHealthHandler.java
index 6960bb284bce9b..6d9d33066e8fbd 100644
--- a/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeHealthHandler.java
+++ b/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeHealthHandler.java
@@ -2,12 +2,13 @@
import io.smallrye.health.SmallRyeHealth;
import io.smallrye.health.SmallRyeHealthReporter;
+import io.smallrye.mutiny.Uni;
import io.vertx.ext.web.RoutingContext;
public class SmallRyeHealthHandler extends SmallRyeHealthHandlerBase {
@Override
- protected SmallRyeHealth getHealth(SmallRyeHealthReporter reporter, RoutingContext ctx) {
- return reporter.getHealth();
+ protected Uni getHealth(SmallRyeHealthReporter reporter, RoutingContext ctx) {
+ return reporter.getHealthAsync();
}
}
diff --git a/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeHealthHandlerBase.java b/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeHealthHandlerBase.java
index fff1485398fbc1..e9993754187690 100644
--- a/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeHealthHandlerBase.java
+++ b/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeHealthHandlerBase.java
@@ -10,7 +10,11 @@
import io.quarkus.vertx.http.runtime.security.QuarkusHttpUser;
import io.smallrye.health.SmallRyeHealth;
import io.smallrye.health.SmallRyeHealthReporter;
+import io.smallrye.mutiny.Uni;
+import io.smallrye.mutiny.vertx.MutinyHelper;
+import io.vertx.core.Context;
import io.vertx.core.Handler;
+import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpHeaders;
import io.vertx.core.http.HttpServerResponse;
@@ -18,7 +22,7 @@
abstract class SmallRyeHealthHandlerBase implements Handler {
- protected abstract SmallRyeHealth getHealth(SmallRyeHealthReporter reporter, RoutingContext routingContext);
+ protected abstract Uni getHealth(SmallRyeHealthReporter reporter, RoutingContext routingContext);
@Override
public void handle(RoutingContext ctx) {
@@ -41,19 +45,21 @@ private void doHandle(RoutingContext ctx) {
Arc.container().instance(CurrentIdentityAssociation.class).get().setIdentity(user.getSecurityIdentity());
}
SmallRyeHealthReporter reporter = Arc.container().instance(SmallRyeHealthReporter.class).get();
- SmallRyeHealth health = getHealth(reporter, ctx);
- HttpServerResponse resp = ctx.response();
- if (health.isDown()) {
- resp.setStatusCode(503);
- }
- resp.headers().set(HttpHeaders.CONTENT_TYPE, "application/json; charset=UTF-8");
- Buffer buffer = Buffer.buffer(256); // this size seems to cover the basic health checks
- try (BufferOutputStream outputStream = new BufferOutputStream(buffer);) {
- reporter.reportHealth(outputStream, health);
- resp.end(buffer);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
+ Context context = Vertx.currentContext();
+ getHealth(reporter, ctx).emitOn(MutinyHelper.executor(context))
+ .subscribe().with(health -> {
+ HttpServerResponse resp = ctx.response();
+ if (health.isDown()) {
+ resp.setStatusCode(503);
+ }
+ resp.headers().set(HttpHeaders.CONTENT_TYPE, "application/json; charset=UTF-8");
+ Buffer buffer = Buffer.buffer(256); // this size seems to cover the basic health checks
+ try (BufferOutputStream outputStream = new BufferOutputStream(buffer);) {
+ reporter.reportHealth(outputStream, health);
+ resp.end(buffer);
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ });
}
-
}
diff --git a/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeIndividualHealthGroupHandler.java b/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeIndividualHealthGroupHandler.java
index 66f960791ad8d8..e0c7ba38744399 100644
--- a/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeIndividualHealthGroupHandler.java
+++ b/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeIndividualHealthGroupHandler.java
@@ -2,13 +2,14 @@
import io.smallrye.health.SmallRyeHealth;
import io.smallrye.health.SmallRyeHealthReporter;
+import io.smallrye.mutiny.Uni;
import io.vertx.ext.web.RoutingContext;
public class SmallRyeIndividualHealthGroupHandler extends SmallRyeHealthHandlerBase {
@Override
- protected SmallRyeHealth getHealth(SmallRyeHealthReporter reporter, RoutingContext ctx) {
+ protected Uni getHealth(SmallRyeHealthReporter reporter, RoutingContext ctx) {
String group = ctx.normalizedPath().substring(ctx.normalizedPath().lastIndexOf("/") + 1);
- return reporter.getHealthGroup(group);
+ return reporter.getHealthGroupAsync(group);
}
}
diff --git a/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeLivenessHandler.java b/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeLivenessHandler.java
index a5cf3dd904cbe9..ad33e824ff3d71 100644
--- a/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeLivenessHandler.java
+++ b/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeLivenessHandler.java
@@ -2,12 +2,13 @@
import io.smallrye.health.SmallRyeHealth;
import io.smallrye.health.SmallRyeHealthReporter;
+import io.smallrye.mutiny.Uni;
import io.vertx.ext.web.RoutingContext;
public class SmallRyeLivenessHandler extends SmallRyeHealthHandlerBase {
@Override
- protected SmallRyeHealth getHealth(SmallRyeHealthReporter reporter, RoutingContext ctx) {
- return reporter.getLiveness();
+ protected Uni getHealth(SmallRyeHealthReporter reporter, RoutingContext ctx) {
+ return reporter.getLivenessAsync();
}
}
diff --git a/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeReadinessHandler.java b/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeReadinessHandler.java
index a23a3e1f9d5383..18c652bd673bd7 100644
--- a/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeReadinessHandler.java
+++ b/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeReadinessHandler.java
@@ -2,12 +2,13 @@
import io.smallrye.health.SmallRyeHealth;
import io.smallrye.health.SmallRyeHealthReporter;
+import io.smallrye.mutiny.Uni;
import io.vertx.ext.web.RoutingContext;
public class SmallRyeReadinessHandler extends SmallRyeHealthHandlerBase {
@Override
- protected SmallRyeHealth getHealth(SmallRyeHealthReporter reporter, RoutingContext routingContext) {
- return reporter.getReadiness();
+ protected Uni getHealth(SmallRyeHealthReporter reporter, RoutingContext ctx) {
+ return reporter.getReadinessAsync();
}
}
diff --git a/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeStartupHandler.java b/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeStartupHandler.java
index c450430735ecb8..cd1ae14846cc97 100644
--- a/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeStartupHandler.java
+++ b/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeStartupHandler.java
@@ -2,12 +2,13 @@
import io.smallrye.health.SmallRyeHealth;
import io.smallrye.health.SmallRyeHealthReporter;
+import io.smallrye.mutiny.Uni;
import io.vertx.ext.web.RoutingContext;
public class SmallRyeStartupHandler extends SmallRyeHealthHandlerBase {
@Override
- protected SmallRyeHealth getHealth(SmallRyeHealthReporter reporter, RoutingContext routingContext) {
- return reporter.getStartup();
+ protected Uni getHealth(SmallRyeHealthReporter reporter, RoutingContext ctx) {
+ return reporter.getStartupAsync();
}
}
diff --git a/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeWellnessHandler.java b/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeWellnessHandler.java
index 84ca3860c1caed..e2131f51de416e 100644
--- a/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeWellnessHandler.java
+++ b/extensions/smallrye-health/runtime/src/main/java/io/quarkus/smallrye/health/runtime/SmallRyeWellnessHandler.java
@@ -2,12 +2,13 @@
import io.smallrye.health.SmallRyeHealth;
import io.smallrye.health.SmallRyeHealthReporter;
+import io.smallrye.mutiny.Uni;
import io.vertx.ext.web.RoutingContext;
public class SmallRyeWellnessHandler extends SmallRyeHealthHandlerBase {
@Override
- protected SmallRyeHealth getHealth(SmallRyeHealthReporter reporter, RoutingContext routingContext) {
- return reporter.getWellness();
+ protected Uni getHealth(SmallRyeHealthReporter reporter, RoutingContext ctx) {
+ return reporter.getWellnessAsync();
}
}