HDDS-11646. Intermittent timeout in TestXceiverClientMetrics - #11029
HDDS-11646. Intermittent timeout in TestXceiverClientMetrics#11029shuan1026 wants to merge 2 commits into
Conversation
chihsuan
left a comment
There was a problem hiding this comment.
Thanks for digging into this one @shuan1026! Overall looks good.
I left a few inline comments, mainly about two behaviours the old test had that this version drops.
I also considered making this deterministic, but that seems to require a test hook in XceiverClientGrpc or the datanode. That feels beyond this Jira, so I think this direction is reasonable.
|
|
||
| for (int i = 0; i < numSenderThreads; i++) { | ||
| Thread sendThread = new Thread(() -> { | ||
| try { |
There was a problem hiding this comment.
I wonder if we should keep the try inside the loop? With the current structure, the first transient error permanently stops the sender, whereas the previous code retried.
There was a problem hiding this comment.
Done. try/catch is back inside the while loop.
| } | ||
|
|
||
| Thread.sleep(1000); | ||
| } catch (Exception ignored) { |
There was a problem hiding this comment.
Since we are already touching this block, would it make sense to keep the first failure somewhere and surface it if the wait times out? Right now, nothing is logged.
There was a problem hiding this comment.
Done. the first sender exception is kept in an AtomicReference.
| getLongCounter("numPendingPutSmallFile", metric); | ||
|
|
||
| if (pendingOps > 0 && pendingPutSmallFileOps > 0) { | ||
| if (clientMetrics.getPendingContainerOpCountMetrics( |
There was a problem hiding this comment.
The old predicate required both pendingOps > 0 and numPendingPutSmallFile > 0 but now only the per-type counter is checked. So a regression that stops incrementing the aggregate while still incrementing the per-type counter would pass. Should we keep both?
There was a problem hiding this comment.
Done. restored PendingOps > 0 && numPendingPutSmallFile > 0 via getMetrics(SOURCE_NAME), same as the original test.
The getSource NPE problem (the comment in HDDS-11646) only appears if this method is re-entered in the same JVM after close(), which was a side effect of the timeout + test-flaky rerun. With the flaky timeout fixed that path should not run, so I kept the original snapshot API. We can follow up on the metrics unregister lifecycle separately.
|
|
||
| GenericTestUtils.waitFor(() -> | ||
| clientMetrics.getPendingContainerOpCountMetrics( | ||
| ContainerProtos.Type.PutSmallFile) == 0, 10, 5000); |
There was a problem hiding this comment.
What do you think about waiting for both PendingOps and numPendingPutSmallFile to reach zero? We assert both below, and this avoids relying on their internal decrement order.
There was a problem hiding this comment.
Done. the drain waitFor now waits for both counters to reach 0.
…ks in TestXceiverClientMetrics
What changes were proposed in this pull request?
TestXceiverClientMetrics#testMetricswas tagged@Flaky("HDDS-11646")because of an intermittentwaitForTimeoutException.Root cause: with the default
STAND_ALONEpipeline, writes go throughXceiverClientGrpc, whosesendCommandAsyncalready blocks the caller until the response arrives (shouldBlockAndWaitAsyncReplyreturnstruefor non-read-only requests). The test used a single background thread that fired 10 "async" writes serially and then slept 1s, so at most 1 request was ever in flight at a time,PendingOpsfloated back to 0 for most of each cycle, and the main thread's 100ms poll frequently missed the narrow non-zero window, causing the observed timeout.This PR fixes the root cause by:
Replaces the single serialized sender thread with 10 concurrent sender threads, each continuously sending blocking writes until the pending spike is observed. With genuine concurrent in-flight requests,
PendingOpsstays non-zero for a sustained window instead of spiking for microseconds, so the poll reliably catches it.computeResultsis wrapped inCollections.synchronizedListfor thread-safe concurrent writes, and each sender thread now calls countDown() on the shared CountDownLatch in afinallyblock solatch.await()can't hang if a thread exits via an exception.The pending count increased poll now reads
XceiverClientManager.getXceiverClientMetrics().getPendingContainerOpCountMetrics(...)directly instead of going throughMetricsAsserts.getMetrics(SOURCE_NAME)on every tick; the poll interval is also tightened from 100ms to 10ms.Adds a short retry before the final
PendingOps == 0/numPendingPutSmallFile == 0assertions, absorbing the small window between a response future completing and its pending-metric decrement (two separate, non-atomic steps inXceiverClientGrpc's gRPC callback).What is the link to the Apache JIRA
https://issues.apache.org/jira/browse/HDDS-11646
How was this patch tested?
.github/workflows/intermittent-test-check.ymlall green https://github.com/shuan1026/ozone/actions/runs/31959022505