Skip to content

Releases

1.0.0

Choose a tag to compare

@dirkjink dirkjink released this 24 Oct 20:57
60d0f55

Added

Modules - 2026-10-19

  • veredium-core: the stack-neutral part both client modules share - the mesh timeout ladder
    (app.mesh, eu.inqudium.veredium.core.mesh), the breaker verdicts (benign 4xx is a success, a
    client-side failure is ignored) and the Resilience4j wiring that installs them (one
    *ConfigCustomizer per mesh alias, the fail-fast startup guard, the ladder logger). Each client
    contributes only its exception vocabulary (RestClientVerdicts, WebClientVerdicts), which its
    auto-configuration hands to the core's wiring through its own MeshResilienceRegistrar subclass. ADR-0001; resolves finding 1 of the
    origin module's architecture review (tool-box, 2026-10-19).
  • veredium-restclient: the blocking client - Spring RestClient over Apache HttpClient 5, one
    resilience-wrapped client per mesh endpoint, the timeout ladder derived from one measured anchor,
    the Resilience4j verdicts and rungs installed through the library's customizers with a fail-fast
    startup guard, a bounded body read and legatium's exchange event. Ported from dhaase/tool-box.
  • veredium-webclient: the reactive sibling - Spring WebClient over Reactor Netty with the same
    mesh ladder, the same Resilience4j customizer wiring and legatium's exchange event. Ported from
    dhaase/tool-box.

Both client stacks in one host - 2026-10-23

  • Both client modules in one host (ADR-0003): app.mesh.endpoints[].stack (restclient / webclient) assigns an
    endpoint to the stack that serves it. Needed only when a host depends on both modules - with one, every endpoint
    belongs to it. Each stack's customizers, startup guard and factory cover its own endpoints only; a factory refuses
    the other stack's endpoint, and an engine override for it, naming the owner. MeshOwnershipCheck fails the start,
    before any registry or pool exists, for an endpoint both stacks or no stack would serve. veredium-examples has a
    mixed example with both clients in one context.

HTTP engines - 2026-10-21 to 2026-10-23

  • Selectable HTTP engine per client stack, with a per-backend override (engine.endpoints.<mesh-alias>):

    • veredium-restclient: app.restclient.engine.default takes apache (default), jdk, jetty or
      reactor-netty.
    • veredium-webclient: app.webclient.engine.default takes reactor-netty (default), jdk, jetty or
      apache.

    The setting applies to the module's own clients only. Boot's global spring.http.clients.* switches are
    neither read nor written, and no transport bean is registered. Boot's RestClient.Builder / WebClient.Builder
    bean is left untouched, because the engine is set on the module's clone of it. No process-global resource or
    system property is used. Isolation tests pin all of this against Boot's real HTTP-client auto-configuration.

    Each engine is created with the factory, shared by the backends that select it, and released on shutdown. The mesh
    ladder is mapped onto every engine as far as it allows. What an engine cannot apply, for example pool size
    and pending-acquire on the JDK client, is stated in a startup line and in the module guides, not silently
    ignored.

    The non-default engine libraries are optional dependencies: jetty-client and reactor-netty-http for the
    blocking client; jetty-client/jetty-reactive-httpclient and httpclient5/httpcore5-reactive for the
    reactive one.

    The start fails, naming the key:

    • for an override key that is not a mesh alias,
    • for an engine whose library is missing (with its Maven coordinates),
    • for jdk while the JDK would replace the backend's Host header. The host enables that header itself
      with -Djdk.httpclient.allowRestrictedHeaders=host.

    Cancellation (TimeLimiter expiry, interrupted caller, cancelled future or subscription) abandons the
    exchange on every engine. For Jetty and Reactor Netty on the blocking side, and for Apache on the reactive
    side, this closes gaps in Spring Framework 7.0.9's adapters.

Examples - 2026-10-24

  • veredium-examples: the decorator example shows the MDC hand-off. CorrelatedCustomerLookup puts a request id in
    the caller's MDC, and the adapter's line on the decorator's worker carries it, for decorate and decorateAsync
    alike. A fan-out over threads of the host's own hands the caller's MDC on with CallerMdc.with, because the
    decorator copies the MDC of the thread that calls it.

Build and project setup - 2026-10-19 to 2026-10-23

  • A new build-only module, veredium-examples, shows a host using both clients: one Spring Boot
    application per calling style - blocking and asynchronous on the RestClient, reactive on the WebClient - each
    with an adapter over two backends and the configuration it needs, and one that bounds a native Apache HttpClient 4
    call with the core's BlockingResilienceDecorator. Its tests start each
    application against a WireMock stand-in for the sidecar, so an example that stops working fails the build. Like
    veredium-coverage and veredium-test-support it is never published; all three have a README that says why
    each is a module of its own.
  • A new build-only module, veredium-test-support, holds the test helpers both client modules
    share - the raw-socket backends, the thread-safe log capture, eventually, the WireMock arrival listener, the
    configuration-file binding, the test payloads and the customized registries - in place of the copies that had
    drifted apart in each module. Like veredium-coverage it is never published.
  • The veredium-core module, the build (Maven, Kotlin, Spring Boot parent,
    JaCoCo, ktlint, Dokka, CycloneDX, reproducible jars), the CI, CodeQL, Scorecard, Docs, Fuzz
    and Release workflows, and the documentation site - set up from the sibling project
    Legatium.

Fixed

Most entries resolve the findings of the defect analyses in docs/assessment/
(DEFECT_ANALYSIS-2026-10-21T20-14-02.md, -2026-10-22T14-01-49.md, -2026-10-23T05-20-01.md,
-2026-10-24T10-08-59.md, -2026-10-24T19-38-36.md).

Shutdown and engine release - 2026-10-22 to 2026-10-24

  • veredium-webclient: on the Reactor Netty engine, a shutdown thread that was interrupted no longer fails the
    engine's release. Its wait for the pool's disposal was a block(), which answers an interrupt with an exception:
    the event loops were never scheduled for disposal and outlived the context, calls in flight ran until their
    response timeout, and the log showed "failed to release its resources" with a stack trace. The wait now ends on
    the interrupt with the shared drain line ("because the shutdown thread was interrupted"), keeps the flag, and the
    loops go in any case. The interrupted-shutdown case now runs on every reactive engine.

  • veredium-webclient: the Reactor Netty engine's drain line names the drain window, as every engine's does,
    instead of the part of the shared deadline that was left when its turn came.

  • veredium-restclient: on the Reactor Netty engine, a head wait that finished just as the worker was interrupted
    has its response closed, instead of holding its pooled connection.

  • veredium-restclient: on the Reactor Netty engine, a call still waiting for its response head when a shutdown
    past its deadline disposed the event loops could hang until its TimeLimiter budget. Spring's wait for the head
    is a block() without a time bound, and the response timeout is a timer on those loops. Seen once on CI; not
    reproduced locally. The wait now runs on the engine's hand-off executor, like each body read already did, and
    the shutdown's shutdownNow of that executor ends it at once with an IOException. A unit test pins the
    hand-off.

  • veredium-webclient: the Apache engine's release no longer fails a call that is still waiting for a
    connection. It shut the I/O reactor down at once, and a reactor in SHUTTING_DOWN opens no connection, so a
    call queued behind max-connections failed with an IOReactorShutdownException as soon as the connection it
    waited for came free, although the drain deadline left it all the time it needed. The release now waits for
    the engine's exchanges in flight first, as Jetty's does, and shuts the reactor down after. A per-engine test
    of a call waiting for a connection pins it; on Apache it failed after 0.6 s of a 5 s deadline before the fix.
    The "in-flight exchange finishes" case, before on Jetty only, now runs on every reactive engine.

  • veredium-webclient: the Reactor Netty engine's release no longer fails a call that is still waiting for a
    connection either. Its pool was disposed without a disposeTimeout, which is no graceful shutdown: pending
    acquires failed at once with a PoolShutdownException. The pool is now built with the factory's drain bound as
    its disposeTimeout, so its disposal serves the waiting calls and completes once every connection came back;
    the release now waits for in-flight calls on every reactive engine alike.

  • veredium-webclient: the JDK and Apache engines' release WARN names an interrupted shutdown thread as the
    reason, as Jetty's and the blocking module's do.

  • veredium-restclient: the factory's shutdown releases every engine even when one of them throws, reporting
    the failure in a WARN line; a Reactor Netty disposal past its wait is reported instead of thrown out of the
    destroy callback; a Jetty client stopped from an interrupted shutdown thread no longer blocks the shutdown.
    Engines created before one that fails to construct are shut down before the failure is rethrown.

  • veredium-restclient: create() after shutdown() is refused with an IllegalStateException instead of
    building a client on a closed engine.

  • veredium-restclient: the Apache pool's gauges (restclient.pool.*) leave the host's registry on shutdown,
    as Reactor Netty's do.

  • veredium-webclient: shutdown() releases all e...

Read more