v5.0.2
clean-teardownAn interrupt from your test harness no longer turns into a mystery Kafka failure — and no client close can hang the test JVM.
Highlights
- 01
Interrupts are named, not laundered
An interrupt arriving from elsewhere in a run — a preemptive
@Timeout,assertTimeoutPreemptively, a cancelled Awaitility poller — used to surface as a bafflingInterruptExceptionthree frames deep in your code, or silently as a produce that never happened. wiretap never interrupts a thread; it now fails at the interrupt site with a diagnostic that names the likely origin, and warns the moment a test worker thread arrives already interrupted. - 02
The topic reader survives cancellation
await().untilAsserted(assertThatTopic(...))cancels its poll thread with an interrupt when the outer wait times out. The reader now closes its consumer cleanly under a set flag instead of aborting mid-leave-group and leaking one consumer per retry — and still propagates the interrupt the caller's machinery needs to see. - 03
No client close can hang the test JVM
Every Kafka client wiretap opens now closes with a bound (producer 30s, AdminClient and consumer 10s), so an unresponsive broker — or a call abandoned by an interrupt — can no longer stall a test for the client's unbounded default. Each close is best-effort, so a close failure never masks the operation's own result.
Full notes
Changed
- An interrupt that lands during per-method cleanup now surfaces as an
afterEachfailure (and the class's declared seed state is not reapplied for that method on the interrupted thread) rather than passing silently. This is intended — a compromised thread should fail loudly and locally — but is a visible behavior change for suites that run under a preemptive timeout which fires during cleanup.
Fixed
- Interrupt-flag hygiene:
TopicCleanerno longer swallowsInterruptExceptionduring per-method cleanup (which, because that exception re-sets the interrupt flag, used to hand a poisoned thread to the next test and make its first blocking Kafka call fail instantly). It now fails at the interrupt site with a diagnostic naming the likely origin, and preserves the flag as the harness's signal. KafkaTopicReadercloses its consumer interrupt-or-not — the flag is taken off for a bounded close and restored exactly as found — so a cancelled read (e.g. an Awaitility timeout) no longer leaks a consumer per retry; a diagnostic names the cancellation, including the footgun that wiretap reads already wait internally, so an outer await shorter than the read window is guaranteed to interrupt it.- The broker-facing assertions (
exists(),doesNotExist(),hasPartitionCount()) preserve the interrupt flag when failing on interruption instead of discarding it. - The JUnit extension warns at
beforeAll/beforeEachwhen the test worker thread arrives already interrupted, naming the common origins — so the root cause is greppable in the log instead of surfacing as a Kafka error deep in user code. - Bounded client closes throughout:
KafkaTestPublisher's producer close (behind everysend/sendValue/sendBatch, previously unbounded atLong.MAX_VALUE) is now 30s, andWiretapTopicProvisioner's AdminClient close (the per-test-class startup path, previously unbounded at ~365 days) is now 10s. An unresponsive broker can no longer hang the test JVM at these sites.