Skip to content

fix(upsert): skip expired metadata during upsert instead of comparing against it#18733

Open
tarun11Mavani wants to merge 1 commit into
apache:masterfrom
tarun11Mavani:upsert-ttl-inline-check
Open

fix(upsert): skip expired metadata during upsert instead of comparing against it#18733
tarun11Mavani wants to merge 1 commit into
apache:masterfrom
tarun11Mavani:upsert-ttl-inline-check

Conversation

@tarun11Mavani

Copy link
Copy Markdown
Contributor

Problem

When upsertMetadataTTL is configured, expired metadata entries are only cleaned up at segment commit time (which can be hours apart for low-throughput tables). Records arriving after TTL expiry are still compared against stale metadata — a record with a lower comparison value gets rejected as out-of-order even though the existing entry is expired and should be irrelevant.

Fix

Add an inline TTL expiry check in doAddRecord(). When the existing record's comparison value is below the TTL threshold (largestSeenComparisonValue - metadataTTL), skip the comparison entirely:

  • The new record always wins regardless of its comparison value
  • The old doc is invalidated via replaceDocId (no duplicate queryable rows)
  • The map entry is replaced with a fresh RecordLocation

Also guard the partial upsert merge in doUpdateRecord() — skip reading the previous row when it's expired, preventing stale data from being merged into the new record.

Changes

  • ConcurrentMapPartitionUpsertMetadataManager.doAddRecord() — TTL check before comparison
  • ConcurrentMapPartitionUpsertMetadataManager.doUpdateRecord() — TTL guard on partial upsert merge
  • Test: expired metadata is skipped, lower comparison value accepted, old doc invalidated

Not changed

  • ConcurrentMapPartitionUpsertMetadataManagerForConsistentDeletesmetadataTTL and enableDeletedKeysCompactionConsistency are mutually exclusive, so the check can never fire there
  • removeExpiredPrimaryKeys() — lazy cleanup at segment commit continues as-is

… against it

When upsertMetadataTTL is configured, expired metadata entries were only
cleaned up lazily at segment commit time. Records arriving after TTL
expiry were still compared against stale metadata and could be rejected
as out-of-order. This makes behavior inconsistent — the output depends
on when cleanup last ran.

Add an inline TTL expiry check in doAddRecord() so that expired metadata
entries are treated as if they don't exist. The new record always wins
regardless of its comparison value, and the old doc is properly
invalidated via replaceDocId. Also guard the partial upsert merge path
in doUpdateRecord() to prevent merging stale data from expired records.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@tarun11Mavani tarun11Mavani marked this pull request as ready for review June 11, 2026 08:19
@codecov-commenter

codecov-commenter commented Jun 11, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.88889% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 64.55%. Comparing base (3693493) to head (5085afb).
⚠️ Report is 70 commits behind head on master.

Files with missing lines Patch % Lines
...t/ConcurrentMapPartitionUpsertMetadataManager.java 88.88% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##             master   #18733      +/-   ##
============================================
+ Coverage     56.80%   64.55%   +7.74%     
- Complexity        7     1305    +1298     
============================================
  Files          2580     3380     +800     
  Lines        149652   209651   +59999     
  Branches      24180    32779    +8599     
============================================
+ Hits          85010   135336   +50326     
- Misses        57444    63458    +6014     
- Partials       7198    10857    +3659     
Flag Coverage Δ
custom-integration1 100.00% <ø> (ø)
integration 100.00% <ø> (ø)
integration1 100.00% <ø> (ø)
integration2 0.00% <ø> (ø)
java-21 64.55% <88.88%> (+7.74%) ⬆️
temurin 64.55% <88.88%> (+7.74%) ⬆️
unittests 64.55% <88.88%> (+7.74%) ⬆️
unittests1 56.98% <0.00%> (+0.18%) ⬆️
unittests2 37.03% <88.88%> (?)

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.

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.

2 participants