From d5d0aeec7ae444978017e53206aaf6011015ac04 Mon Sep 17 00:00:00 2001 From: xstefank Date: Wed, 10 Jul 2024 16:48:35 +0200 Subject: [PATCH] Create new vertx context for blocking health checks --- ...kingChecksVertxContextDuplicationTest.java | 65 +++++++++++++++++++ .../QuarkusAsyncHealthCheckFactory.java | 19 +++++- .../runtime/SmallRyeHealthHandlerBase.java | 2 +- 3 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/BlockingChecksVertxContextDuplicationTest.java diff --git a/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/BlockingChecksVertxContextDuplicationTest.java b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/BlockingChecksVertxContextDuplicationTest.java new file mode 100644 index 0000000000000..6fd84159bd3f4 --- /dev/null +++ b/extensions/smallrye-health/deployment/src/test/java/io/quarkus/smallrye/health/test/BlockingChecksVertxContextDuplicationTest.java @@ -0,0 +1,65 @@ +package io.quarkus.smallrye.health.test; + +import static org.hamcrest.Matchers.is; + +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.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusUnitTest; +import io.restassured.RestAssured; +import io.restassured.parsing.Parser; +import io.vertx.core.Context; +import io.vertx.core.Vertx; + +class BlockingChecksVertxContextDuplicationTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .withApplicationRoot((jar) -> jar + .addClasses(ContextCaptureCheck1.class, ContextCaptureCheck2.class) + .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml")); + + @Test + void testBlockingChecksPropagateVertxContext() { + try { + RestAssured.defaultParser = Parser.JSON; + RestAssured.when().get("/q/health").then() + .body("status", is("UP"), + "checks.size()", is(2)); + + Assertions.assertNotEquals(ContextCaptureCheck1.capturedContext, ContextCaptureCheck2.capturedContext, + "Expected different contexts to be propagated into different blocking health checks"); + } finally { + RestAssured.reset(); + } + } + + @Liveness + public static class ContextCaptureCheck1 implements HealthCheck { + + public static Context capturedContext = null; + + @Override + public HealthCheckResponse call() { + capturedContext = Vertx.currentContext(); + return HealthCheckResponse.up("ContextCaptureCheck1"); + } + } + + @Liveness + public static class ContextCaptureCheck2 implements HealthCheck { + + public static Context capturedContext = null; + + @Override + public HealthCheckResponse call() { + capturedContext = Vertx.currentContext(); + return HealthCheckResponse.up("ContextCaptureCheck2"); + } + } +} 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 cfec52c933b1b..bd7c236dce2e2 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 @@ -1,14 +1,19 @@ package io.quarkus.smallrye.health.runtime; +import java.util.concurrent.Callable; +import java.util.concurrent.Executor; + import jakarta.inject.Singleton; import org.eclipse.microprofile.health.HealthCheck; import org.eclipse.microprofile.health.HealthCheckResponse; +import io.smallrye.common.vertx.VertxContext; import io.smallrye.health.AsyncHealthCheckFactory; import io.smallrye.health.api.AsyncHealthCheck; import io.smallrye.mutiny.Uni; import io.smallrye.mutiny.vertx.MutinyHelper; +import io.vertx.core.Context; import io.vertx.core.Vertx; /** @@ -27,7 +32,19 @@ public QuarkusAsyncHealthCheckFactory(Vertx vertx) { @Override public Uni callSync(HealthCheck healthCheck) { Uni healthCheckResponseUni = super.callSync(healthCheck); - return healthCheckResponseUni.runSubscriptionOn(MutinyHelper.blockingExecutor(vertx, false)); + return healthCheckResponseUni.runSubscriptionOn(new Executor() { + @Override + public void execute(Runnable command) { + Context duplicatedContext = VertxContext.createNewDuplicatedContext(vertx.getOrCreateContext()); + duplicatedContext.executeBlocking(new Callable() { + @Override + public Void call() throws Exception { + command.run(); + return null; + } + }, false); + } + }); } @Override 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 cc0bb85cce758..c35577a1d37d7 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 @@ -63,7 +63,7 @@ private void doHandle(RoutingContext ctx, ManagedContext requestContext) { .set(HttpHeaders.CONTENT_TYPE, "application/json; charset=UTF-8") .set(HttpHeaders.CACHE_CONTROL, "no-store"); Buffer buffer = Buffer.buffer(256); // this size seems to cover the basic health checks - try (BufferOutputStream outputStream = new BufferOutputStream(buffer);) { + try (BufferOutputStream outputStream = new BufferOutputStream(buffer)) { reporter.reportHealth(outputStream, health); resp.end(buffer); } catch (IOException e) {