KKcorps commented on PR #19998:
URL: https://github.com/apache/pinot/pull/19998#issuecomment-6387216027
This comes from a model of upsert thread orders that StarTree runs on upsert
PRs, and it checked only the change to how the TTL watermark gets capped.
**The model's known bad orders replay the same, but a segment destroyed
inside the cap loop now turns off the out of TTL skip until the next round,
which opens one narrow duplicate.**
I replayed the model's 45 known bad orders with and without the change. A
search started inside the cap loop found this order on its own, and an hour of
wider search found nothing else.
**The order it adds.** With the skip off, an old segment N0 that comes back
ONLINE ignores its validDocIds snapshot and compares each row. Its A@0, which
lost to A@6 long ago, finds no key because metadataTTL already expired A, so
both rows are valid. It needs a destroy inside the cap loop and a re-add before
the next consumer starts, so it is rare, but it leaves a duplicate row.
```mermaid
sequenceDiagram
participant C as Consumer N3
participant R as Reload N1
participant M as Upsert manager
participant H as Helix N0
C->>M: takeSnapshot, N1 skipped while the reload holds its lock
R->>M: replaceSegment(N1), old N1 untracked
R->>R: old N1 destroyed
C->>M: getWatermarkToPersist, read lock on old N1 fails
M->>M: persist TTL_WATERMARK_NOT_SET
C->>M: removeExpiredPrimaryKeys drops A, its row A@6 in N2 stays valid
H->>M: N0 OFFLINE then ONLINE, addSegment(N0)
M->>M: no skip, so every N0 doc is compared
Note over M: A@0 finds no key, so A@0 and A@6 are both valid
```
<details><summary>Model history</summary>
```
('append', 'A', (0,), 0, {'v': 1}, False)
('append', 'C', (0,), 1, {'v': 1}, False)
('assign_consumer', "N0'")
('acquire', "N0'")
('consume', "N0'", 0)
('consume', "N0'", 1)
('commit_local', "N0'", 1)
('step', 'replace', "N0'", 'start_replace')
('step', 'replace', "N0'", 'add_committed_row:A@0')
('step', 'replace', "N0'", 'add_committed_row:C@1')
('step', 'replace', "N0'", 'begin_leftover')
('step', 'replace', "N0'", 'untrack_and_offload')
('append', 'A', (4,), 2, {'v': 1}, False)
('assign_consumer', "N1'")
('acquire', "N1'")
('consume', "N1'", 2)
('commit_local', "N1'", 2)
('step', 'replace', "N1'", 'start_replace')
('step', 'replace', "N1'", 'add_committed_row:A@2')
('step', 'replace', "N1'", 'begin_leftover')
('step', 'replace', "N1'", 'untrack_and_offload')
('append', 'B', (5,), 3, {'v': 1}, False)
('append', 'A', (6,), 4, {'v': 1}, False)
('append', 'D', (9,), 5, {'v': 1}, False)
('assign_consumer', "N2'")
('acquire', "N2'")
('consume', "N2'", 3)
('consume', "N2'", 4)
('consume', "N2'", 5)
('commit_local', "N2'", 5)
('step', 'replace', "N2'", 'start_replace')
('step', 'replace', "N2'", 'add_committed_row:B@3')
('step', 'replace', "N2'", 'add_committed_row:A@4')
('step', 'replace', "N2'", 'add_committed_row:D@5')
('step', 'replace', "N2'", 'begin_leftover')
('step', 'replace', "N2'", 'untrack_and_offload')
('reload', 'N1')
('assign_consumer', "N3'")
('acquire', "N3'")
('step', 'reload', 'N1', 'start_replace')
('step', 'reload', 'N1', 'add_row:A@2')
('step', 'reload', 'N1', 'begin_leftover')
('step', 'reload', 'N1', 'untrack')
('destroy_segment', 4)
('step_watermark_cap',)
('sweep_expired_keys', ['A', 'C', 'B'])
('offline_immutable', 'N0')
('step', 'offline', 'N0', 'begin_remove')
('step', 'offline', 'N0', 'skip_out_of_ttl')
('step', 'offline', 'N0', 'untrack')
('add_immutable', 'N0')
('step', 'add_immutable', 'N0', 'start_add')
('step', 'add_immutable', 'N0', 'add_row:A@0')
('step', 'add_immutable', 'N0', 'add_row:C@1')
('step', 'add_immutable', 'N0', 'register')
```
</details>
Today's code does the same when N0 itself missed the round, and this window
also stops a late segment with no snapshot file from having every doc marked
valid, so it is a trade rather than a new kind of bug. Caching each segment's
max comparison value when it is added would keep today's behavior.
The model covers one replica and one partition, and it did not check the
mapped metadata sidecar.
<!-- upsert-model-check head=60040605eeb2ef6180fd8bf677df0c12dbfd3ef1 -->
--
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]