Compatibility
MicroProfile Fault Tolerance
Goblin is designed to work with Fault Tolerance, not against it, at every layer:
-
Service layer (SERVICE) — the interceptor runs at
@Priority(4100), inside the SmallRye Fault Tolerance interceptor (4010), so the injected fault is what your@Retry,@CircuitBreaker,@Timeout,@Bulkheadand@Fallbackannotations are supposed to absorb. A latency within the armed range exercises@Timeout/@Bulkhead; a thrown exception makes@Retryre-invoke the boundary or@Fallbackanswer. The first attempt uses the per-request decision; each further attempt drawslevelagain, so atlevel = 100every attempt fails (and@Fallbackanswers) while a lower level lets some retries recover. Only the outermost intercepted call is assaulted: a bean calling another bean never multiplies the fault. -
HTTP layer (HTTP_IN) — endpoint-level assaults apply to the JAX-RS boundary of unprotected endpoints only; fault-tolerant resources are hit before their annotations can react, which is the wrong place to validate them. The classic workflow below remains the recommended approach for HTTP_IN.
-
Outgoing layer (HTTP_OUT) — client-side latency/exceptions simulate a downstream service failing, the usual trigger for
@Retry/@Fallbackon data-source calls.
The classic HTTP-level workflow:
-
Configure chaos on unprotected endpoints (default behavior).
-
Exclude fault-tolerant endpoints via
quarkus.goblin.target.exclude-annotations. -
Verify that the unprotected endpoints fail as expected.
-
Remove the exclusion and arm the
SERVICE(orDATABASE) layer to confirm@Timeoutand@Fallbacktrigger correctly: at theHTTP_INlayer the fault would hit the endpoint before its annotations can react.
To exercise the resilience chain end-to-end today, arm the SERVICE layer and switch the HTTP_IN / HTTP_OUT
layers off: the fault is then injected directly on the business bean and propagates through the fault-tolerance
machinery, while the HTTP_IN filter stands down. A bean method excluded by quarkus.goblin.target.exclude-annotations
is not woven, so keep the Fault Tolerance annotations out of that property for this workflow. The service decision is
bound to the request thread: @Asynchronous methods and ManagedExecutor tasks are not covered yet, and for a method
returning Uni / CompletionStage only the synchronous part of the call is. On a Vert.x event-loop thread the latency
assaults that would block are skipped (a WARN is logged once) rather than blocking the loop; only the WebClient latency,
which uses a Vert.x timer, still applies there.
|
Agroal / Hibernate ORM / Panache
The DATABASE layer is an Agroal pool interceptor, installed on every JDBC datasource when quarkus-agroal is present
(which Hibernate ORM and Panache use). It is not registered in production builds, and applications without a datasource
never load the Agroal API. Hibernate Reactive and the reactive SQL clients are not covered.
Quarkus Messaging
The MESSAGING layer is a CDI interceptor woven on @Incoming consumer methods when quarkus-messaging is present,
whatever the connector (Kafka, AMQP, in-memory…). It relies on no messaging API at runtime. Only the synchronous part
of a consumer is covered, and latency requires a blocking consumer. Outgoing messages (Emitter, @Outgoing) are not
assaulted.
Quarkus REST (RESTEasy Reactive)
Goblin uses standard JAX-RS ContainerRequestFilter / ContainerResponseFilter and targets Quarkus REST (quarkus-rest, formerly RESTEasy Reactive), which the extension is built and tested against. The classic RESTEasy runtime (quarkus-resteasy) is not tested and not supported.
MicroProfile REST Client / Quarkus REST Client
Client-side assaults are implemented as a standard JAX-RS ClientRequestFilter registered as a global provider. They apply to any client built with quarkus-rest-client (the RESTEasy Reactive-based MicroProfile REST Client implementation). The filter is inert in production builds and, being opt-in, off by default, so it has no effect unless you enable the client-side toggles.
Vert.x WebClient
The same client-side assaults apply to outgoing io.vertx.ext.web.client.WebClient calls, but Vert.x 4.x exposes no public interceptor hook on WebClient. Goblin therefore attaches its interceptor explicitly, at the point where the application creates its client, via GoblinWebClient.enable(webClient). The interceptor relies on Vert.x’s internal WebClientInternal.addInterceptor mechanism (the same one used by Vert.x’s own OAuth2WebClient, CachingWebClient and WebClientSession decorators), so it works with any client backed by Vert.x’s default WebClientImpl; a custom decorator that does not extend the base client fails fast with an IllegalArgumentException. A plain WebClient is protected by Goblin’s opt-in default: without enable(…) it is never touched.
WebClientInternal, HttpContext and ClientPhase live in io.vertx.ext.web.client.impl and carry no
compatibility guarantee. They are the only way to intercept a Vert.x 4 WebClient today; GoblinWebClientTest pins
the behaviour, so a Vert.x upgrade that changes them fails the build rather than silently disabling the assaults. The
integration will move to a public API when Vert.x provides one.
|
Micrometer / Prometheus
Observability is opt-in through the quarkus-goblin-metrics module (see Metrics (Micrometer / Prometheus)). It depends on
quarkus-micrometer (API only) and registers the assault metrics against the application’s MeterRegistry: add the
registry of your choice (e.g. quarkus-micrometer-registry-prometheus for /q/metrics). It co-exists with any other
Micrometer-based monitoring and is inert when absent from the classpath.
OpenTelemetry
The quarkus-goblin-opentelemetry module (see Tracing (OpenTelemetry)) emits one goblin.assault span per assault
through the same observer SPI, without touching the engine. It brings in quarkus-opentelemetry and reuses whatever
exporter your application already configures, so the assault spans appear in your existing tracing backend; both
optional modules can be present at the same time and neither interferes with the other.