Fixes for fully-expired SSTable index notification in compaction - #5027
Fixes for fully-expired SSTable index notification in compaction#5027frankgh wants to merge 1 commit into
Conversation
The 2i notification path added to CompactionTask (CASSANDRA-20829) had three issues, all reachable on upgrade for existing clusters: - A read error or a throwing custom indexer aborted the whole compaction. Expired SSTables were never obsoleted and every retry hit the same failure. - The static row was never passed to removeRow, so static-column indexes missed expired-data notifications. - NoOpIndex, PaxosUncommittedIndex and RouteJournalIndex inherited the default (true) and did no useful work on this path, forcing needless full scans of expired SSTables on system.paxos / accord tables. Opt them out matching SAI/SASI. patch by Francisco Guerrero; reviewed by TBD for CASSANDRA-21577
There was a problem hiding this comment.
Pull request overview
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
This PR fixes issues in the compaction-time “fully expired SSTable” secondary-index notification path to ensure expired SSTables are reliably dropped, static rows are notified, and certain system/accord-related indexes opt out to avoid unnecessary work.
Changes:
- Make index notifications best-effort during fully-expired SSTable handling so compaction can still drop expired SSTables even if reads/indexers fail.
- Include static rows when notifying indexers about fully-expired SSTables.
- Opt out specific indexes (NoOpIndex, PaxosUncommittedIndex, RouteJournalIndex) from fully-expired SSTable row notifications; add regression tests.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| test/unit/org/apache/cassandra/index/CustomIndexTest.java | Adds regression tests for indexer-failure resilience and static-row notifications during fully-expired SSTable compaction. |
| src/java/org/apache/cassandra/service/paxos/uncommitted/PaxosUncommittedIndex.java | Disables fully-expired SSTable row notification for PaxosUncommittedIndex to avoid unnecessary scans. |
| src/java/org/apache/cassandra/index/accord/RouteJournalIndex.java | Disables fully-expired SSTable row notification for RouteJournalIndex to avoid unnecessary scans. |
| src/java/org/apache/cassandra/index/accord/NoOpIndex.java | Disables fully-expired SSTable row notification for NoOpIndex to avoid unnecessary scans. |
| src/java/org/apache/cassandra/db/compaction/CompactionTask.java | Makes notification best-effort, ensures static rows are notified, and guarantees finish() is called even on failures. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| for (Index.Indexer indexer : indexers) | ||
| indexer.begin(); | ||
|
|
||
| while (partition.hasNext()) | ||
| try | ||
| { | ||
| Unfiltered unfiltered = partition.next(); | ||
| if (unfiltered instanceof Row) | ||
| Row staticRow = partition.staticRow(); | ||
| if (!staticRow.isEmpty()) | ||
| { | ||
| for (Index.Indexer indexer : indexers) | ||
| indexer.removeRow((Row) unfiltered); | ||
| indexer.removeRow(staticRow); | ||
| } | ||
| } | ||
|
|
||
| for (Index.Indexer indexer : indexers) | ||
| indexer.finish(); | ||
| while (partition.hasNext()) | ||
| { | ||
| Unfiltered unfiltered = partition.next(); | ||
| if (unfiltered instanceof Row) | ||
| { | ||
| for (Index.Indexer indexer : indexers) | ||
| indexer.removeRow((Row) unfiltered); | ||
| } | ||
| } | ||
| } | ||
| finally | ||
| { | ||
| for (Index.Indexer indexer : indexers) | ||
| indexer.finish(); | ||
| } |
| // Let the rows (and SSTable) fully expire. | ||
| Uninterruptibles.sleepUninterruptibly(60, TimeUnit.SECONDS); |
| // Static-only writes: each partition gets a static row and no clustering rows, so removeRow would never be | ||
| // invoked for these partitions unless the static row is handled explicitly. | ||
| execute("INSERT INTO %s (pk, s) VALUES (?, ?) USING TTL 20", 0, 100); | ||
| execute("INSERT INTO %s (pk, s) VALUES (?, ?) USING TTL 20", 1, 200); | ||
|
|
||
| flush(); | ||
| Assert.assertFalse(cfs.getLiveSSTables().isEmpty()); | ||
|
|
||
| Uninterruptibles.sleepUninterruptibly(60, TimeUnit.SECONDS); |
The 2i notification path added to CompactionTask (CASSANDRA-20829) had three issues, all reachable on upgrade for existing clusters:
patch by Francisco Guerrero; reviewed by TBD for CASSANDRA-21577