Skip to content

Do not rely on assert for null/empty check on realtime commit temp folder - #19261

Open
dkranchii wants to merge 1 commit into
apache:masterfrom
dkranchii:fix/realtime-segment-data-manager-assert
Open

Do not rely on assert for null/empty check on realtime commit temp folder#19261
dkranchii wants to merge 1 commit into
apache:masterfrom
dkranchii:fix/realtime-segment-data-manager-assert

Conversation

@dkranchii

Copy link
Copy Markdown
Contributor

Summary

RealtimeSegmentDataManager.buildSegmentInternal used a Java assert before indexing into tempSegmentFolder.listFiles():

File[] tempFiles = tempSegmentFolder.listFiles();
assert tempFiles != null;
File tempIndexDir = tempFiles[0];

Java assert is a no-op unless the JVM is started with -ea, and Pinot's service processes do not run with assertions enabled. If listFiles() returned null (I/O error, folder gone) or an empty array (race with cleanup), production would raise NullPointerException / ArrayIndexOutOfBoundsException instead of the typed SegmentBuildFailureException that the caller and the Helix state machine already handle. That leaves the realtime segment commit in an ambiguous state.

Change

  • Extract a small @VisibleForTesting static helper pickTempIndexDir(File) that performs the null/empty check and throws SegmentBuildFailureException("Temp segment folder is empty or unreadable: ...").
  • Caller in buildSegmentInternal funnels the failure through reportSegmentBuildFailure(msg, null) before rethrowing — matching the pattern already used a few lines down for the missing-metadata / missing-creation-meta branches.

No behavior change on the happy path. No config, SPI, wire-format, or metric-name change.

Tests

Added three unit tests to RealtimeSegmentDataManagerTest:

  • testPickTempIndexDirReturnsFirstEntry — happy path, folder with one entry returns that entry.
  • testPickTempIndexDirThrowsWhenFolderIsEmpty — empty folder → SegmentBuildFailureException.
  • testPickTempIndexDirThrowsWhenFolderIsMissing — non-existent folder (listFiles() returns null) → SegmentBuildFailureException. This is the exact scenario the old assert masked.

Run:

./mvnw -pl pinot-core -am -Dtest=RealtimeSegmentDataManagerTest test

Scope

Single-file production change in pinot-core/src/main/java/org/apache/pinot/core/data/manager/realtime/RealtimeSegmentDataManager.java, plus tests in the adjacent test file.

Release note

none (turns a rare NPE / AIOOBE on the segment-commit path into the typed SegmentBuildFailureException that Helix handling already anticipates)

@codecov-commenter

codecov-commenter commented Aug 15, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 44.44444% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 67.10%. Comparing base (bff2f5d) to head (2232c42).

Files with missing lines Patch % Lines
...a/manager/realtime/RealtimeSegmentDataManager.java 44.44% 5 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##             master   #19261      +/-   ##
============================================
- Coverage     67.11%   67.10%   -0.02%     
  Complexity     1423     1423              
============================================
  Files          3457     3457              
  Lines        219284   219290       +6     
  Branches      34864    34864              
============================================
- Hits         147167   147149      -18     
- Misses        60346    60363      +17     
- Partials      11771    11778       +7     
Flag Coverage Δ
integration 100.00% <ø> (ø)
integration1 100.00% <ø> (ø)
integration2 0.00% <ø> (ø)
java-25 67.10% <44.44%> (-0.02%) ⬇️
lane-a 100.00% <ø> (ø)
lane-b 0.00% <ø> (ø)
temurin 67.10% <44.44%> (-0.02%) ⬇️
unittests 67.09% <44.44%> (-0.02%) ⬇️
unittests1 57.81% <44.44%> (-0.03%) ⬇️
unittests2 39.14% <0.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@dkranchii
dkranchii force-pushed the fix/realtime-segment-data-manager-assert branch from 66d7535 to 9c04105 Compare August 16, 2026 02:00
…timeSegmentDataManager

`buildSegmentInternal` used `assert tempFiles != null;` before indexing into
`tempFiles[0]` to pick the built segment's temp index directory. Java `assert`
is a no-op unless the JVM is started with `-ea`, and Pinot does not run its
service processes with assertions enabled — so if `tempSegmentFolder.listFiles()`
returned `null` (I/O error, folder gone) or an empty array (racy cleanup),
production would throw `NullPointerException` or `ArrayIndexOutOfBoundsException`
from a segment-commit path instead of the typed `SegmentBuildFailureException`
the caller and Helix state machine already expect.

Extract a small `@VisibleForTesting` static helper `pickTempIndexDir(...)`
that performs the check and throws `SegmentBuildFailureException` with a clear
message. The caller in `buildSegmentInternal` continues to funnel the failure
through `reportSegmentBuildFailure` (metric + error info), matching the pattern
already used for the "metadata file missing" / "creation meta missing"
branches further down in the same method.

Add unit tests for the helper covering:
  - happy path: folder with one entry returns that entry
  - empty folder: throws `SegmentBuildFailureException`
  - non-existent folder (`listFiles()` returns `null`): throws
    `SegmentBuildFailureException`

No behavior change on the happy path. No config, SPI, or wire-format change.

Co-authored-by: Cursor <cursoragent@cursor.com>
@dkranchii
dkranchii force-pushed the fix/realtime-segment-data-manager-assert branch from 9c04105 to 2232c42 Compare August 16, 2026 05:09

@Jackie-Jiang Jackie-Jiang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch

File[] tempFiles = tempSegmentFolder.listFiles();
assert tempFiles != null;
File tempIndexDir = tempFiles[0];
File tempIndexDir;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest just inline the change. I feel it is more readable that way. It is okay to not have test if it is hard to add

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants