Skip to content

Reject duplicate segment names before batch push - #19947

Closed
xiangfu0 wants to merge 4 commits into
apache:masterfrom
xiangfu0:xiangfu0/codex1/duplicate-segment-validation
Closed

xiangfu0 wants to merge 4 commits into
apache:masterfrom
xiangfu0:xiangfu0/codex1/duplicate-segment-validation

Conversation

@xiangfu0

@xiangfu0 xiangfu0 commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Backward incompatible: Batch pushes reject selected archives with the same logical segment name before replacement or upload, preventing arbitrary overwrites from recursive output directories. This applies across gzip, Zstd, and LZ4. Selected names also enforce the existing illegal-character validation (\ / : * ? " < > |).

Reproduce with segment.tar.gz and 2022/segment.tar.gz under one output directory: the push reports the first conflicting pair. Remove stale output or select one cohort with pushFileNamePattern: "glob:**/2022/*.tar.gz". After rebasing onto master with #19898, Hadoop/Spark use the shared selection rules: honor pushFileNamePattern and skip .metadata.tar.gz sidecars.

Spark 3 metadata pushes preserve empty consistent REFRESH replacement without dispatching uploads. An omitted output directory now preserves the supplied segment URI when no prefix/suffix is configured; prefix rewriting remains supported. Shared offline fixtures now wait for every generated segment in the broker required-routing view: SSE row-count readiness can pass while MSE still omits optional segments, matching the recurring WindowFunnelTest 36/40-group failure. Validation: 74 targeted JDK 25 reactor tests (including all 38 WindowFunnelTest cases), affected-module formatting/license/style checks, and independent code review passed.

PR flow

Batch push now lists output files, maps them to segment URIs/tar paths with duplicate name validation, then pushes tar, metadata, or URIs accordingly.

flowchart TD
  N0["List files under outputDirURI #40;F2#44; F3#44; F4#44; F7#44; F8#44; F9#41;"]:::stUnchanged
  N1["Get segment URI to tar path map and validate unique names #40;F2#44; F3#44; F4#44; F6#44; F7#44; F8#44; F9#44; F10#41;"]:::stModified
  N2["Push tar segments#58; extract paths#44; validate in pushSegments#44; upload #40;F3#44; F8#44; F10#41;"]:::stModified
  N3["Push metadata#58; pass map#44; validate in sendSegmentUriAndMetadata#44; upload #40;F2#44; F6#44; F10#41;"]:::stModified
  N4["Push URIs#58; extract URIs#44; validate in sendSegmentUris#44; upload #40;F4#44; F9#44; F10#41;"]:::stModified
  N0 --> N1
  N1 --> N2
  N1 --> N3
  N1 --> N4
  classDef stAdded fill:#dafbe1,stroke:#1a7f37,color:#1f2328,stroke-width:2px
  classDef stModified fill:#fff8c5,stroke:#9a6700,color:#1f2328,stroke-width:2px
  classDef stRemoved fill:#ffebe9,stroke:#cf222e,color:#1f2328,stroke-width:2px
  classDef stUnchanged fill:#f6f8fa,stroke:#656d76,color:#1f2328,stroke-width:1px
Loading

AI-generated · Green: added · Yellow: modified · Red: removed · Gray: existing

Diff evidence
  • F2: pinot-plugins/pinot-batch-ingestion/pinot-batch-ingestion-hadoop/src/main/java/org/apache/pinot/plugin/ingestion/batch/hadoop/HadoopSegmentMetadataPushJobRunner.java — before · after
  • F3: pinot-plugins/pinot-batch-ingestion/pinot-batch-ingestion-hadoop/src/main/java/org/apache/pinot/plugin/ingestion/batch/hadoop/HadoopSegmentTarPushJobRunner.java — before · after
  • F4: pinot-plugins/pinot-batch-ingestion/pinot-batch-ingestion-hadoop/src/main/java/org/apache/pinot/plugin/ingestion/batch/hadoop/HadoopSegmentUriPushJobRunner.java — before · after
  • F6: pinot-plugins/pinot-batch-ingestion/pinot-batch-ingestion-spark-3/src/main/java/org/apache/pinot/plugin/ingestion/batch/spark3/SparkSegmentMetadataPushJobRunner.java — before · after
  • F7: pinot-plugins/pinot-batch-ingestion/pinot-batch-ingestion-spark-base/src/main/java/org/apache/pinot/plugin/ingestion/batch/spark/common/BaseSparkSegmentMetadataPushJobRunner.java — before · after
  • F8: pinot-plugins/pinot-batch-ingestion/pinot-batch-ingestion-spark-base/src/main/java/org/apache/pinot/plugin/ingestion/batch/spark/common/BaseSparkSegmentTarPushJobRunner.java — before · after
  • F9: pinot-plugins/pinot-batch-ingestion/pinot-batch-ingestion-spark-base/src/main/java/org/apache/pinot/plugin/ingestion/batch/spark/common/BaseSparkSegmentUriPushJobRunner.java — before · after
  • F10: pinot-segment-local/src/main/java/org/apache/pinot/segment/local/utils/SegmentPushUtils.java — before · after
  • Regenerate PR flow

Current hosted validation

Current head 6208e67e9d2e passed all 16 hosted checks. Completed Unit workflow 40053061761 and Integration workflow 40053061800 logs confirm 74 relevant invocations with no failures, errors or skips: 29 segment-push, three duplicate-output Spark, four Spark3 empty-output and 38 WindowFunnel ingestion cases. The tested checkout tree matches this PR head exactly.

Independent review covered all eight changed files, including URI handling and selected archive-name identity across common/Spark/minion push paths. All seven review threads are answered and resolved. No new source change was needed for this readiness check; formal maintainer approval remains separate.

@xiangfu0 xiangfu0 added release-notes Referenced by PRs that need attention when compiling the next release notes ingestion Related to data ingestion pipeline backward-incompat Introduces a backward-incompatible API or behavior change labels Oct 19, 2026

@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.

Reviewed all 11 changed files at fa60242. Leaving two findings as a non-blocking review: one P1 for empty consistent REFRESH behavior and one P2 for nullable output-directory handling. Static review only; no local tests run.

@codecov-commenter

codecov-commenter commented Oct 19, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 81.25000% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 69.83%. Comparing base (083f293) to head (6208e67).

Files with missing lines Patch % Lines
...he/pinot/segment/local/utils/SegmentPushUtils.java 86.66% 2 Missing ⚠️
...gestion/batch/common/BaseSegmentPushJobRunner.java 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff            @@
##             master   #19947   +/-   ##
=========================================
  Coverage     69.82%   69.83%           
  Complexity     1519     1519           
=========================================
  Files          3558     3558           
  Lines        235843   235859   +16     
  Branches      37848    37851    +3     
=========================================
+ Hits         164678   164705   +27     
+ Misses        58464    58449   -15     
- Partials      12701    12705    +4     
Flag Coverage Δ
integration 100.00% <ø> (ø)
integration1 100.00% <ø> (ø)
integration2 0.00% <ø> (ø)
java-25 69.83% <81.25%> (+<0.01%) ⬆️
lane-a 100.00% <ø> (ø)
lane-b 0.00% <ø> (ø)
temurin 69.83% <81.25%> (+<0.01%) ⬆️
unittests 69.82% <81.25%> (+<0.01%) ⬆️
unittests1 59.06% <0.00%> (-0.01%) ⬇️
unittests2 41.56% <81.25%> (+<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.

@xiangfu0
xiangfu0 force-pushed the xiangfu0/codex1/duplicate-segment-validation branch from fa60242 to c411786 Compare October 20, 2026 05:06

@xiangfu0 xiangfu0 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Review: Reject duplicate segment names before batch push

I reviewed the duplicate-detection logic, the empty-batch / consistent-push paths, error messaging, and push back-compat across the Hadoop, Spark, and SegmentPushUtils changes. Overall this looks solid and well tested: the duplicate check runs on the full un-deduped path list (so same-named archives in different directories are caught even though the URI map would otherwise hide one), empty REFRESH snapshots still replace, and the data-provider / expectThrows tests cover the key cases.

A couple of minor, non-blocking observations are inline. Decision: this is an approve on the merits -- the only remaining items are minor. (Submitting as a review comment rather than a formal Approve because GitHub blocks approving from this account, which it treats as the PR owner.)

@xiangfu0
xiangfu0 force-pushed the xiangfu0/codex1/duplicate-segment-validation branch from c411786 to 14be3d6 Compare October 22, 2026 09:57

@xiangfu0 xiangfu0 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Reviewed correctness, back-compat, and coverage; built and ran the touched unit tests (SegmentPushUtilsTest, 18/18 green). The change looks good — rejecting duplicate segment names before any HTTP/replacement starts is a real improvement, and routing the Hadoop/Spark runners through getSegmentUriToTarPathMap is a clean consolidation that aligns them with the standard push runner. Only minor/nit observations below, nothing blocking.

(Posting as a comment rather than an approval since GitHub blocks approving your own PR.)

@xiangfu0
xiangfu0 force-pushed the xiangfu0/codex1/duplicate-segment-validation branch from 14be3d6 to a8dbb60 Compare October 23, 2026 22:54
@xiangfu0
xiangfu0 requested a review from Jackie-Jiang October 24, 2026 01:48
Fail before upload or replacement when selected archives share a segment name. Apply the push pattern first so excluded archives do not cause false conflicts.
Empty consistent REFRESH snapshots still complete replacement, and METADATA uploads accept an omitted output directory with a URI prefix.
Reproduce with empty REFRESH output or a local METADATA push using only push.segmentUriPrefix.
Reproduce by mapping an archive without an output directory or URI prefix; the missing directory caused an NPE. Keep the input URI unchanged and cover mixed-codec duplicate rejection.
Reproduce by querying WindowFunnelTest while a newly uploaded segment is still optional: MSE can return 36 instead of 40 groups. Wait for all fixture segments in the broker required-routing view before running assertions.
@xiangfu0
xiangfu0 force-pushed the xiangfu0/codex1/duplicate-segment-validation branch from a8dbb60 to 6208e67 Compare October 24, 2026 02:10

@xiangfu0 xiangfu0 left a comment •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

(Please ignore — this review was posted by an automated session probe in error and does not represent a review. Apologies for the noise.)

@xiangfu0

Copy link
Copy Markdown
Contributor Author

Closing to keep this work focused on loading performance. Duplicate-name rejection is a separate correctness change and is not required by the performance improvements.

@xiangfu0 xiangfu0 closed this Oct 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backward-incompat Introduces a backward-incompatible API or behavior change ingestion Related to data ingestion pipeline release-notes Referenced by PRs that need attention when compiling the next release notes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants