Update mockserver-netty to 7.4.0#5373
Merged
Merged
Conversation
This was referenced Jul 7, 2026
adamw
added a commit
that referenced
this pull request
Jul 7, 2026
…angs) (#5383) ## Problem The Vert.x 4 → 5 upgrade (80c5e37, 2026-06-10) changed `HttpServerRequestImpl.pause()`/`fetch()`/`resume()` semantics: they now `checkEnded()` and **throw** `IllegalStateException("Request has already been read")` once the request body END event has been delivered. In Vert.x 4 these calls were safe no-ops after end. Tapir's vertx streaming bridge invokes `pause()`/`resume()` from fire-and-forget fibers and Vert.x callbacks: - `server/vertx-server/cats/src/main/scala/sttp/tapir/server/vertx/cats/streams/fs2.scala` — back-pressure loop in a started-and-never-joined fiber - `server/vertx-server/zio/src/main/scala/sttp/tapir/server/vertx/zio/streams/zio.scala` — same pattern, `forkDaemon`-ed - `server/vertx-server/src/main/scala/sttp/tapir/server/vertx/streams/Pipe.scala` — drain handlers / pipe start - `server/vertx-server/src/main/scala/sttp/tapir/server/vertx/handlers/package.scala` — `streamPauseHandler` for every streaming/WS endpoint Under CI load, a `pause`/`resume` racing the END event now throws, silently killing the back-pressure fiber (or skipping cleanup such as `socket.close()`), leaving stream consumers waiting forever. This is the suspected root cause of the intermittent **silent hangs** in the vertx cats/zio suites seen on dependency PRs #5373 / #5362, where CI went quiet until the 15-minute retry timeout. ## Fix Restore Vert.x 4 semantics at tapir's call sites by ignoring the post-end `IllegalStateException`: after END there is nothing left to pause/resume, so dropping the call is semantically correct. No fibers/streams were restructured — only the pause/resume calls on the request/read-stream are guarded (`.attempt.void` in fs2, `.ignore` in zio, a small `ignoringReadEnded` helper in `Pipe.scala`, and a try/catch in `streamPauseHandler`). Companion PR: #5382 adds defensive timeouts + a thread-dump watchdog on the CI side; this PR is the root-cause side. ## Verification All variants compile (2.12 / 2.13 / 3): `vertxServer{,2_12,3}`, `vertxServerCats{,2_12,3}`, `vertxServerZio{,2_12,3}`. Test suites: - `vertxServerCats2_12/test`: Tests: succeeded 292, failed 0 — all passed - `vertxServerZio3/test`: Tests: succeeded 295, failed 0 — all passed - `vertxServer/test` (2.13): Tests: succeeded 554, failed 0 — all passed Stress run of the formerly racy path — `vertxServerCats2_12/testOnly sttp.tapir.server.vertx.cats.CatsVertxServerTest` 5 times in a loop: 5/5 passed (285 tests each). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
adamw
added a commit
that referenced
this pull request
Jul 7, 2026
## Problem The test `properly update metrics when a request times out` (in `NettyFutureRequestTimeoutTests`, and its sync counterpart in `NettySyncRequestTimeoutTests`) is flaky on CI, failing intermittently with `1 was not equal to 0` at the `activeRequests.get() shouldBe 0` assertion. It failed on three dependency-update PRs in the week of 2026-07-06 alone (runs for #5379, #5376 and #5373). The root cause is a race in the test, not in production code: the metrics are only decremented when the endpoint's logic completes, which for the Future-based server happens ~1 second *after* the 503 timeout response is received (the `Future` running the logic is not interruptible). The test used a fixed `Thread.sleep(1100)`, leaving only a ~100 ms margin before asserting — not enough on a loaded CI machine. The sync test had an even tighter fixed `Thread.sleep(100)`. ## Fix Replace the fixed sleeps with `eventually { ... }` and a widened patience config (15 s timeout / 150 ms interval) — the same idiom already used for the same reason in `ServerMetricsTest`. This asserts eventual consistency instead of racing the asynchronous metrics update. No production code is changed. ## Verification Ran locally: - `sbt "nettyServer/testOnly sttp.tapir.server.netty.NettyFutureServerTest -- -z \"properly update metrics\""` — passed - `sbt "nettyServerSync3/testOnly sttp.tapir.server.netty.sync.NettySyncServerTest -- -z \"properly update metrics\""` — passed 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
adamw
added a commit
that referenced
this pull request
Jul 7, 2026
) ## Problem CI test runs intermittently hang: the build goes silent for ~9 minutes until the 15-minute `nick-fields/retry` timeout kills sbt, and the second attempt then frequently times out the same way, failing the job after ~30 minutes. This was observed on dependency PRs #5373, #5362 and #5376 during the week of 2026-06-27..2026-07-07. The suspected trigger is the Vert.x 5 upgrade — a follow-up PR will address the Vert.x-side cause; this PR makes the test infrastructure resilient and adds diagnostics. Two failure modes: * **(A)** a single test hangs mid-suite (often the vertx cats/zio suites — WebSocket/streaming waits with no timeout). Tests are not forked and run one suite at a time, so one hung test stalls the entire run. * **(B)** all tests pass, but `TestSuite.afterAll` blocks forever in an unbounded `release.unsafeRunSync()` (e.g. a wedged `Vertx.close`), so sbt never finishes. ## Changes * **`DefaultCreateServerTest`**: each test's `IO` gets `.timeout(3.minutes)` before `.unsafeToFuture()` — a hung test is cancelled (running the server-close finalizer) instead of hanging the suite. * **`TestSuite` (JVM)**: * every registered test is wrapped in a 4-minute safety-net timeout (`IO.fromFuture(...).timeout(4.minutes)`), catching `Test`s constructed outside `DefaultCreateServerTest`; * suite resource acquisition (`tests.allocated`) is bounded to 2 minutes; * `afterAll` bounds `release` and `shutdownDispatcher` to 1 minute each, so a wedged backend close fails loudly instead of hanging the non-forked sbt JVM forever. * **`CatsVertxServerTest`**: the suite-level `vertx.close` wait is bounded to 30 seconds; on timeout/failure it logs and continues. * **CI workflow (JVM Test step only)**: a background watchdog checks `output.log`'s mtime every 30 seconds; if the build has been silent for >240 seconds it appends `jcmd <pid> Thread.print` dumps of all JVMs to `thread-dumps.log`, which is uploaded as an artifact (`if-no-files-found: ignore`). The sbt exit code and the existing `tee output.log` + leak-grep behaviour are preserved. ## Verification * `sbt "serverTests/Test/compile" "tests/Test/compile"` — compiles. * `sbt "vertxServerCats2_12/testOnly sttp.tapir.server.vertx.cats.CatsVertxServerTest"` — all 285 tests pass through the new timeout wrappers and the bounded vertx close. * `sbt "nettyServer/testOnly sttp.tapir.server.netty.NettyFutureServerTest"` — 278/279 pass (incl. the 5s graceful-shutdown and request-timeout metrics tests), confirming the timeout wrappers don't regress longer-running tests. The single failure (`bind(..) failed: Address already in use` in the leak test, which uses the default port 8080) is environmental — running the same suite on unmodified master on the same machine fails identically. * `python3 -c "import yaml; yaml.safe_load(open('.github/workflows/ci.yml'))"` — workflow YAML valid. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
adamw
added a commit
that referenced
this pull request
Jul 7, 2026
) ## The leak In `Http4sRequestBody`, the `RawBodyType.FileBody` case creates a temp file via `serverOptions.createFile` and then compiles the body stream into it. If the stream fails mid-write — e.g. with `StreamMaxLengthExceededException` when the configured max content length is exceeded (resulting in a 413) — the `RawValue(FileRange(file), ...)` is never produced. The interpreter's body-cleanup logic only deletes files that were registered as raw values, so the temp file is never deleted. The leak happens on **every** over-limit file upload, making it a disk-fill DoS vector: a client can fill the server's temp directory simply by repeatedly sending oversized bodies to a file-body (or multipart file) endpoint. #5335 fixed exactly this in the akka, pekko, jdk-http, netty (cats/future/sync/zio) and zio-http backends, but missed http4s. ## Why the shared test only catches it intermittently The shared test `checks payload limit and returns 413 on exceeded max content length (request)` (`ServerBasicTests`) polls for leftover temp files containing the test's marker bytes. Whether the leaked file contains those bytes depends on how the HTTP client chunks the request and how much of the body was written before the limit interrupt — in local runs the leaked file is often 0 bytes, so the marker check misses it (and the oversized-request send may also end in the `SttpClientException` recover path). The leak itself is deterministic; only its detection is chunking-dependent. This is the source of the flaky `Http4sServerTest` 413 failure seen e.g. on #5373's CI. ## The fix Attach an `onError` handler to the stream compilation that deletes the file via `serverOptions.deleteFile`. `onError` rethrows the original error after running the handler, and the handler swallows its own failures (`.attempt.void`) so a failing delete cannot mask the original error. Since `toRawFromStream` is also used for multipart parts and by the http4s-zio interpreter, those are covered too. ## Verification - Baseline (unmodified master): `http4sServer/testOnly sttp.tapir.server.http4s.Http4sServerTest -- -z 413` passes (5/5) but leaves 1 leaked `/tmp/tapir*tmp` file (0 bytes — confirming why the marker-based detection is intermittent). - With the fix: the same 413 subset run 3 times — all green, 0 leaked temp files after each run. - `http4sServer2_12/compile`, `http4sServer3/compile`, `http4sServerZio/compile`, `http4sServerZio3/compile` all succeed. - Full `Http4sServerTest` suite: 302 tests, all passed, 0 leaked temp files. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
About this PR
📦 Updates org.mock-server:mockserver-netty from
7.3.0to7.4.0Usage
✅ Please merge!
I'll automatically update this PR to resolve conflicts as long as you don't change it yourself.
If you'd like to skip this version, you can just close this PR. If you have any feedback, just mention me in the comments below.
Configure Scala Steward for your repository with a
.scala-steward.conffile.Have a fantastic day writing Scala!
⚙ Adjust future updates
Add this to your
.scala-steward.conffile to ignore future updates of this dependency:Or, add this to slow down future updates of this dependency: