yihua opened a new pull request, #19388:
URL: https://github.com/apache/hudi/pull/19388

   ### Describe the issue this Pull Request addresses
   
   When schema conflict resolution is enabled and a writer commits a batch 
whose writer schema is the Avro null schema (for example, an ingestion round 
that writes no data), 
`SimpleSchemaConflictResolutionStrategy.resolveConcurrentSchemaEvolution` 
resolves the table schema at the current transaction's owner instant. At 
pre-commit time that instant is inflight and has no completion time, so the 
completion-time filter in 
`ConcurrentSchemaEvolutionTableSchemaGetter.getLastCommitMetadataWithValidSchemaFromTimeline`
 calls `String.compareTo(null)`, and the commit fails:
   
   ```
   Caused by: org.apache.hudi.exception.HoodieException: Unable to get table 
schema
        at 
org.apache.hudi.client.transaction.SimpleSchemaConflictResolutionStrategy.getTableSchemaAtInstant(SimpleSchemaConflictResolutionStrategy.java:173)
        at 
org.apache.hudi.client.transaction.SimpleSchemaConflictResolutionStrategy.resolveConcurrentSchemaEvolution(SimpleSchemaConflictResolutionStrategy.java:74)
        ...
   Caused by: java.lang.NullPointerException
        at java.lang.String.compareTo(String.java:1155)
        at 
org.apache.hudi.common.table.timeline.InstantComparison.lambda$static$3(InstantComparison.java:34)
        at 
org.apache.hudi.common.table.timeline.InstantComparison.compareTimestamps(InstantComparison.java:38)
        at 
org.apache.hudi.client.transaction.ConcurrentSchemaEvolutionTableSchemaGetter.lambda$getLastCommitMetadataWithValidSchemaFromTimeline$3(ConcurrentSchemaEvolutionTableSchemaGetter.java:175)
   ```
   
   The defect is twofold, and Hudi 1.x writes both table versions:
   
   - On table version 6, ordering the schema evolution timeline by completion 
time is wrong to begin with: version 6 does not record completion time on disk 
(the in-memory value is synthesized from the meta file modification time), and 
0.x writers concurrently writing the same table order the timeline by requested 
time. Requested-time ordering restores 0.x parity and also removes the NPE on 
this version, since every instant carries a requested time.
   - On table version 8 and above, completion-time ordering is correct, but the 
same NPE fires for an empty-batch commit: the current transaction's owner 
instant is not completed yet and has no completion time.
   
   A transaction with a null writer schema does not evolve the schema, so the 
resolution should adopt the current table schema.
   
   ### Summary and Changelog
   
   - The per-timeline-version instant ordering is exposed as a first-class API 
on `InstantComparator`: `orderingComparator()` / `getOrderingTime(instant)` 
(requested-time based in v1, completion-time based in v2), so version handling 
lives in the timeline layer rather than in callers.
   - `ConcurrentSchemaEvolutionTableSchemaGetter`: sorts and bounds the schema 
evolution timeline with that ordering (completion time for table version 8 and 
above, requested time for earlier versions, matching 0.x). A target instant 
without an ordering time (not completed yet, on table version 8 and above) does 
not bound the lookup instead of throwing NPE.
   - `SimpleSchemaConflictResolutionStrategy`: the null-writer-schema path 
adopts the table schema as of the current transaction's owner instant. On table 
version 6 the lookup is bounded by the instant's requested time (matching 0.x 
behavior); on table version 8 and above the inflight instant carries no 
completion time, so the latest table schema is resolved. The prior-instant 
lookup for the transaction start snapshot also uses the version-appropriate 
ordering time.
   - Tests: `TestSimpleSchemaConflictResolutionStrategy` gains the 
inflight-instant NPE regression plus table-version-6 cases proving 
requested-time bounding; `TestConcurrentSchemaEvolutionTableSchemaGetter` gains 
latest-schema ordering regressions with the same two-commit layout on both 
versions (the earlier-requested commit completes last), so table version 8 and 
above must return the completion-time winner and table version 6 must return 
the requested-time winner even when the synthesized completion order disagrees; 
`TestInstantComparators` covers the new `InstantComparator` ordering APIs 
directly.
   
   ### Impact
   
   Fixes commit failures on multi-writer tables for ingestion rounds that write 
no data, on table version 6 and table version 8 and above alike. No public API 
or user-facing behavior change otherwise.
   
   ### Risk Level
   
   low
   
   The new regression tests fail with the production NPE signature before the 
fix and pass after; the table-version-6 ordering tests fail without the 
version-aware ordering and pass with it; both full test classes pass.
   
   ### Documentation Update
   
   none
   
   ### Contributor's checklist
   
   - [x] Read through [contributor's 
guide](https://hudi.apache.org/contribute/how-to-contribute)
   - [x] Enough context is provided in the sections above
   - [x] Adequate tests were added if applicable
   


-- 
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]

Reply via email to