Skip to content

Remove departed ingesters from routing table - #6680

Open
nadav-govari wants to merge 2 commits into
mainfrom
nadav/routing-fix
Open

Remove departed ingesters from routing table#6680
nadav-govari wants to merge 2 commits into
mainfrom
nadav/routing-fix

Conversation

@nadav-govari

Copy link
Copy Markdown
Collaborator

Description

Ingesters that leave the cluster aren't removed from the routing table. We were relying on the ingester pool to not select them. If these ingesters later rejoin the cluster, the old entry is still there- representing stale data. It's only cleared when the control plane inits shards on those ingesters, or they broadcast their first capacity update (both can take seconds). This clears the entry on departure to prevent that edge case.

How was this PR tested?

Unit tests.

@nadav-govari
nadav-govari requested a review from a team as a code owner August 11, 2026 19:11

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

https://github.com/quickwit-oss/quickwit/blob/40c141e2b7a95154a370228fcef1836a186ff051/quickwit-serve/src/lib.rs#L1260-L1262
P2 Badge Avoid treating readiness removals as departures

In clusters where an indexer only transitions out of ready state, this now publishes IngesterDeparture and the router deletes all routing entries for that node. ClusterChange::Remove is emitted for a ready→not-ready transition as well as for an actual leave (quickwit-cluster/src/change.rs:239-246), and when the node becomes ready again setup_ingester_pool just re-inserts it into the pool without restoring those routing entries. That creates a transient ingest regression for sources whose shards were still valid on that same ingester: requests have to go back through control-plane/capacity refresh instead of routing immediately. Consider distinguishing real departures/rejoins (for example with the chitchat generation or an explicit event kind) from readiness flaps before clearing the routing table.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread quickwit/quickwit-indexing/src/actors/indexing_service.rs Outdated
Comment thread quickwit/quickwit-ingest/src/ingest_v2/mod.rs Outdated
@nadav-govari
nadav-govari enabled auto-merge (squash) August 11, 2026 20:01

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 37268e24ef

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

let mut num_entries = 0;

for entry in self.table.values_mut() {
if entry.nodes.remove(node_id).is_some() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Guard departed ingesters against late routing updates

When a ClusterChange::Remove races with an in-flight control-plane response or a delayed capacity-score event from the same ingester, this removal is not durable: neither merge_from_shards nor apply_capacity_update records that the node has departed, so a stale update can reinsert the node immediately after this line. In the restart/rejoin case, the old shard counts/capacity become eligible again as soon as the same node_id is back in the pool, leaving the stale-routing window this change is meant to close; consider tracking a departure generation/tombstone or rejecting updates for nodes known to have left.

Useful? React with 👍 / 👎.

return;
};
let mut state_guard = state.lock().await;
let num_entries = state_guard.routing_table.remove_node(&departed_ingester.node_id);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve departed leaders for CP failover

When the departed ingester is the only known leader for a source, deleting it here also deletes the only evidence the next GetOrCreateOpenShardsRequest uses to populate unavailable_leaders. If this router observes the removal before the control plane's ingester pool does, the follow-up CP request is sent with an empty unavailable list, so the CP can return the same stale open shard for the removed node_id and the router re-seeds the route instead of forcing a replacement shard; keeping a tombstone/zero-capacity entry long enough to report the leader unavailable would avoid that propagation race.

Useful? React with 👍 / 👎.

@nadav-govari

Copy link
Copy Markdown
Collaborator Author

On hold as we discuss a more thorough, more complicated fix

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