Fix Finatra test server lifecycle - #12272
Conversation
This comment has been minimized.
This comment has been minimized.
🟢 Java Benchmark SLOs — All performance SLOs passed
PR vs. master results
Commit: Load and DaCapo benchmarks can be triggered manually in the GitLab pipeline. Results will appear in the Benchmarking Platform UI after completion. |
9b63609 to
ed7915e
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 200604d8c4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
More details
The static review finds no reportable defect. The lifecycle changes keep server failures inside the test process and make the older-version suite use Finatra 20.6.x.
🤖 Datadog Autotest · Commit 200604d · What is Autotest? · @DataDog review to ask questions · Any feedback? Reach out in #autotest
Run the embedded Finatra test servers with nonExitingMain instead of the production main wrapper, and surface lifecycle errors as ordinary test failures instead of losing the Gradle test worker to System.exit(1). Also enable the latestPre207 suite, which until now compiled but ran nothing and resolved to the same Finatra version as the base test suite. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
200604d to
5c8f18f
Compare
What Does This Do
nonExitingMaininstead of the productionmainwrapper, so a lifecycle error can no longer callSystem.exit(1)inside the Gradle test worker.FutureTask, so a startup or graceful-shutdown failure is rethrown as an ordinary test failure with its original stack trace.FinatraServer.awaitStartreturn whether the latch actually fired instead of silently discarding the result.latestPre207Testsuite tolatestPre207ForkedTestand pins it to[20.6.0,20.7.0)so it actually runs — see below.Motivation
The Finatra Java 8 forked test intermittently completed its V1 JUnit suite successfully and then lost the Gradle test worker with exit code 1:
The corresponding
FinatraServerV1ForkedTestreport was already complete with 72 tests, 0 failures, 0 errors — so the process died after the suite finished, not because of an instrumentation assertion.The tests were invoking Twitter Util's production
App.main, which turns any lifecycle error into a process exit (util-app,com/twitter/app/App.scala):Because the server ran inside the Gradle worker, an intermittent graceful-shutdown error terminated the whole worker and hid the underlying exception from the test runner.
nonExitingMainpreserves the identical application lifecycle but lets the harness capture the failure.Note this improves diagnosability rather than guaranteeing the flake disappears: if the intermittent shutdown error is inherent (e.g. a close timeout under CI load), the suite will now fail in
cleanupSpecwith a real stack trace instead of vanishing. If that turns out to be the case, the follow-up knob issuppressGracefulShutdownErrorson the test server.Implementation Notes
The server thread's outcome is carried by a
FutureTask, which provides exception capture, a bounded join, and rethrow-with-cause in one construct — noAtomicReference, no manualtry/catch, nojoin+ liveness assertion:In the latest-dependency test the existing
Observeralready delivers startup failures throughstartupPromise.setException(...), so no extra handling is needed there.The
latestPre207SuiteWhile validating the fix on older Finatra versions, the
latestPre207Testsuite turned out to be inert in two independent ways onmaster:dd-trace-java.configure-tests.gradle.ktsexcludes**/*ForkedTest*from any task not namedforkedTest*/*ForkedTest, and both concrete classes insrc/testareFinatraServerV0ForkedTest/FinatraServerV1ForkedTest.test, which declares a staticfinatra-http_2.11:19.12.0; that version satisfies[,20.7.0), so conflict resolution kept it:This is visible in
master's lockfile, where19.12.0is listed for bothtestCompileClasspathandlatestPre207TestCompileClasspath.Renaming the suite alone would only have added 72 duplicate tests against the same jar
forkedTestalready covers, so the dependency is now declared as[20.6.0,20.7.0). The lower bound excludes19.12.0from the range, which flips conflict resolution:The range (rather than a hard pin) keeps the suite tracking any future
20.6.xrelease. The lockfile was regenerated withresolveAndLockAll --write-locks; no dependency coordinate was dropped, andallLatestDepTestsstill picks the renamed suite up.Validation
./gradlew :dd-java-agent:instrumentation:finatra-2.9:forkedTest :dd-java-agent:instrumentation:finatra-2.9:latestDepTest -PtestJvm=8(latestDepTestisfinalizedBy latestPre207ForkedTest):forkedTest— V0 / V1latestDepTest—FinatraServer270TestlatestPre207ForkedTest— V0 / V143 of the 72 are pre-existing
assumeTrueskips forHttpServerTestfeatures this integration does not opt into (AppSec blocking, IG body callbacks, websockets, RUM); that count is unchanged frommaster../gradlew :dd-java-agent:instrumentation:finatra-2.9:spotlessCheckpasses.This changes test behaviour only; production Finatra applications and tracer instrumentation are unaffected.
Contributor Checklist
type:and (comp:orinst:) labels in addition to any other useful labelsclose,fix, or any linking keywords when referencing an issueUse
solvesinstead, and assign the PR milestone to the issueJira ticket: N/A