ykisana opened a new pull request, #20552:
URL: https://github.com/apache/druid/pull/20552

   Fixes #20550.
   
   ### Description
   
   `QueryVirtualStorageTest.testQueryTooMuchData` runs a `count(*)` over ~3.7MB 
of segments against a 1MiB virtual storage cache and expects the query to fail 
for lack of space. The query does fail as intended, but the test only accepted 
the bundle-reservation message (`Unable to reserve bundle[...]`). Which 
reservation runs out of space first depends on load thread timing, so the test 
occasionally saw a different, equally correct `CAPACITY_EXCEEDED` error and 
failed at `QueryVirtualStorageTest.java:166`.
   
   #### Why the error message varies
   
   Native queries acquire segments with `AcquireMode.FULL` in a loop in 
`ServerManager#getOrLoadSegmentReferences`. Each `acquireSegment` call 
synchronously reserves the segment's partial metadata 
(`SegmentLocalCacheManager#reservePartial`, sized by 
`virtualStorageMetadataReservationEstimate`, 2KiB in this test) and then hands 
the bundle downloads to the load threads, which reserve bundles concurrently.
   
   - Usually the space left over when a bundle fails to fit is larger than the 
metadata estimate. Every metadata reservation succeeds and the reported error 
is `Unable to reserve bundle[...] for segment[...]; ensure enough disk space 
has been allocated to load all segments involved in the query`.
   - Occasionally, depending on which bundles the load threads win, the 
leftover is smaller than the estimate. The next metadata reservation fails with 
`Unable to reserve partial metadata for segment[...]; ensure enough disk space 
has been allocated`. That error is thrown from the acquire loop itself, so it 
is the one reported. It fails both of the old assertions, since it is not the 
bundle message and it does not end with "...to load all segments involved in 
the query".
   
   I confirmed this locally. Raising the test's metadata estimate to 120KiB 
makes the partial-metadata outcome happen on every run. Under that setting the 
unchanged test fails with `expected: <true> but was: <false>` at line 166 (the 
same signature as the CI failure), and passes with this change. With the real 
2KiB config the full class passes (4/4).
   
   #### Relaxed the assertion in `QueryVirtualStorageTest`
   
   `testQueryTooMuchData` now asserts on `ensure enough disk space has been 
allocated`, the text shared by every virtual storage capacity error (partial 
metadata, bundle, and full segment load). It still fails if the query errors 
for an unrelated reason, such as a timeout or a download failure. The assertion 
now passes `t.getMessage()` as its failure message. The CI failure only showed 
`expected: <true> but was: <false>`, which is why the actual error had to be 
reproduced locally.
   
   Alternatives considered:
   - Assert on the `CAPACITY_EXCEEDED` category. Not viable: by the time the 
error reaches the broker's HTTP response it is reported as 
`"category":"UNCATEGORIZED"`, so only the message text is available to the test.
   - Make the ordering deterministic, e.g. `virtualStorageLoadThreads=1`. 
Metadata is reserved on the query thread while bundles are reserved by load 
tasks, so this doesn't remove the race, and it would change the shared cluster 
that `testQueryPartials` relies on for its load-count expectations.
   - Change the partial metadata message to end with "...to load all segments 
involved in the query" like the other two. That would be a user-facing message 
change made only to satisfy a test, so I left production code alone.
   
   #### Added a unit test for the partial metadata capacity failure
   
   
`SegmentLocalCacheManagerPartialAcquireTest#testFullAcquireFailsWhenPartialMetadataCannotBeReserved`
 builds a manager whose only location is smaller than the metadata reservation 
estimate and checks that `acquireSegment(..., AcquireMode.FULL)`:
   - throws a `CAPACITY_EXCEEDED` `DruidException`;
   - uses the `Unable to reserve partial metadata for segment[...]` message, 
including the shared "ensure enough disk space has been allocated" text the 
embedded test now relies on;
   - leaves no cache entry behind.
   
   No existing unit test covered this path. It is deterministic and runs in 
milliseconds, unlike the embedded race.
   
   #### Release note
   
   No user-facing changes. This PR only changes tests.
   
   <hr>
   
   ##### Key changed/added classes in this PR
    * `QueryVirtualStorageTest`
    * `SegmentLocalCacheManagerPartialAcquireTest`
   
   <hr>
   
   This PR has:
   
   - [x] been self-reviewed.
   - [x] added comments explaining the "why" and the intent of the code 
wherever would not be obvious for an unfamiliar reader.
   - [x] added unit tests or modified existing tests to cover new code paths, 
ensuring the threshold for [code 
coverage](https://github.com/apache/druid/blob/master/dev/code-review/code-coverage.md)
 is met.
   
   #### Generative AI usage
   
   Generated by: Claude Opus 5.5
   Fix written by and all code manually reviewed by @ykisana.
   Tests, PR description, and comments by Claude.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to