Skip to content

IGNITE-25502 fail node on index greater than current majority#7694

Open
dant3 wants to merge 5 commits intoapache:mainfrom
unisonteam:IGNITE-25502
Open

IGNITE-25502 fail node on index greater than current majority#7694
dant3 wants to merge 5 commits intoapache:mainfrom
unisonteam:IGNITE-25502

Conversation

@dant3
Copy link
Copy Markdown
Contributor

@dant3 dant3 commented Mar 3, 2026

LOG.error("FATAL ERROR: Can't truncate logs before appliedId={}, lastIndexKept={}", this.appliedId,
lastIndexKept);
return;
LOG.error("Raft log suffix conflict: cannot truncate entries that have been applied to the state machine. "
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's keep log format as everywhere else. nodeId={}, appliedId={}, lastIndexKept={} should be at the end surrounded by [].
Ex.: The partition will be moved to error state [nodeId={}, appliedId={}, lastIndexKept={}].",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that there should be no dot after ], but I saw people adding it in other places, which confuses me tbh

@alievmirza
Copy link
Copy Markdown
Contributor

I'll take a look

* @return persisted applied index, or 0 if unknown.
*/
default long getPersistedAppliedIndex() {
return 0;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we implement it for all listeners, especially for MS/CMG?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should, the same situation is possible there, maybe worth a separate ticket though

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that the real answer is "no, we should not". MG and CMG only use one data storage per FSM, which always guarantees that min(lastAppliedIndex) matches max(lastAppliedIndex), and the corresponding troubled behavior is impossible. This is a distribution-zone-exclusive problem.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, thanks for clarification @ibessonov

return false;
}

// Restore appliedId so that unsafeTruncateSuffix() can reject truncation of applied entries.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need this entire block of code? please explain

Copy link
Copy Markdown
Contributor Author

@dant3 dant3 Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This block restores appliedId from the state machine's persisted applied index so the guard is effective immediately after restart, before any entries are re-applied.
After a node restart, logManager.appliedId is transient and resets to 0. The unsafeTruncateSuffix() guard checks lastIndexKept < appliedId.getIndex(), but with appliedId=0, it can never reject anything. This effectively leads to possible data corruption.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this explanation is worth copying into the comment in the code.

}

@Override
public long getPersistedAppliedIndex() {
Copy link
Copy Markdown
Contributor

@alievmirza alievmirza Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By the way, I had a great discussion with @rpuch and it seems that we have already fixed the possibility of having gap between persisted and applied index (see https://issues.apache.org/jira/browse/IGNITE-28216), so there is a chance that all this PR could be unnecessary

Copy link
Copy Markdown
Contributor Author

@dant3 dant3 Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IGNITE-28216 fixes one of the known root causes: specific missed lastApplied() bumps in partition processing. This PR adds a detection mechanism: if truncation below applied index ever happens (from this bug or any future bug), we fail the node instead of silently corrupting data.

As a result these are complementary. IGNITE-28216 prevents the gap; our PR catches it if it ever occurs anyway, due to some other unknown bug or nuance -- a similar future bug would again cause silent corruption with no indication of something went wrong.

LOG.error("FATAL ERROR: Can't truncate logs before appliedId={}, lastIndexKept={}", this.appliedId,
lastIndexKept);
return;
LOG.error("Raft log suffix conflict: cannot truncate entries that have been applied to the state machine. "
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that there should be no dot after ], but I saw people adding it in other places, which confuses me tbh

Copy link
Copy Markdown
Contributor

@ibessonov ibessonov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My last comment is optional. Please consult with other review participant on the topic of resolving current conversations with them, I can merge the PR once it's done. Thank you!

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.

4 participants