solana-indexer: advance the finalized watermark from slot statuses - #4854
Conversation
|
Claude finished @squadgazzz's task in 4m 32s —— View job PR Review: advance the finalized watermark from slot statuses
Verdict: looks good — no blocking issues found. This is a clean, well-documented change and the reasoning in the comments matches the code. I traced the core correctness concerns and they hold up:
Optional (non-blocking): Note: I couldn't run |
| // Everything at or below the cutoff is complete even when nothing was | ||
| // buffered: advance the watermark on quiet slots too, so the resume | ||
| // point tracks the stream. | ||
| if cutoff > 0 && *flushed_through < Some(Slot(cutoff)) { |
There was a problem hiding this comment.
how does this check behave if flushed_through is None? Is None < Some(Slot(cutoff))?
Would be nice to make this less ambiguous.
There was a problem hiding this comment.
That comparison is gone, since flushing now keys off the confirmed slot status, and the watermark update is an explicit watermark.is_none_or(|w| w < confirmed), so no Option ordering is involved anymore.
| // Everything at or below the cutoff is complete even when nothing was | ||
| // buffered: advance the watermark on quiet slots too, so the resume | ||
| // point tracks the stream. | ||
| if cutoff > 0 && *flushed_through < Some(Slot(cutoff)) { |
There was a problem hiding this comment.
Why do we only write_last_indexed_slot() when we didn't flush to the cutoff yet?
It's very unclear to me what purpose cutoff and flushed_through have in relation to the last indexed block watermark.
There was a problem hiding this comment.
Simplified and gone now.
| @@ -164,6 +168,15 @@ impl Decoder { | |||
| self.flush_slot(slot, buffer, true).await?; | |||
There was a problem hiding this comment.
What happens if we encounter an error after we already replaced the data in the line above?
Seems like the data would be lost forever. Do we have to restart the indexer to not lose any data?
There was a problem hiding this comment.
Yes, that slot is gone from memory, but the error kills the indexer, and the watermark only advances after a successful flush. So the restart resumes below the failed slot and the stream re-delivers it. Updated the doc.
Description
The yellowstone subscription only delivered confirmed slot statuses, so the indexer never saw finality:
solana.indexer_state.finalized_slotandsolana.chain_tiphad no writer, and the last-indexed watermark only advanced when a settlement flushed. Since we eventually need to support resume/backfill and reorgs functionality for older slots, this needs to be changed.This is the first half of BE-203. The rollback cascade for rows above the finalized watermark follows in its own PR.
solana.chain_tipexisted to answer "is the indexer keeping up with the chain". The watermark could not answer that alone, since it only moved on settlements, so the planned monitoring needed a second row that tracked the chain to compare against. With this PR, the watermark moves on every confirmed slot, so "keeping up" is simply "the watermark keeps moving", and one row answers the question. That leaveschain_tipwith no reader and no purpose, so it goes away.Changes
finalized_slotadvances from finalized statuses, monotone and update-only.solana.chain_tipis dropped (V2 migration), see above: the quiet-slot watermark replaces it as the freshness signal.How to test
New unit tests and ignored postgres tests, including the pipeline test driving finalized and quiet-slot statuses end to end.
Related issues
BE-203