Skip to content

control-plane: rebuild the plan when the scheduler is stuck reapplying a non-converging plan#6602

Open
aanufriev-celonis wants to merge 5 commits into
quickwit-oss:mainfrom
celonis:escalate-reapply-to-rebuild
Open

control-plane: rebuild the plan when the scheduler is stuck reapplying a non-converging plan#6602
aanufriev-celonis wants to merge 5 commits into
quickwit-oss:mainfrom
celonis:escalate-reapply-to-rebuild

Conversation

@aanufriev-celonis

@aanufriev-celonis aanufriev-celonis commented Jul 13, 2026

Copy link
Copy Markdown

Summary

Make the indexing scheduler recover on its own from a persistently non-converging control_running_plan loop, instead of re-sending the same un-runnable plan forever.

Part of #6601.

Stacked PR. This PR is built on top of #6585, which is not yet merged, so it currently also contains that PR's commits. Once #6585 is merged, I will rebase the current PR.

Problem

See the original description of #6601.

Change

  • Add REAPPLY_LOOP_RESCHEDULE_THRESHOLD (10 cycles, ~5 min at the 30s production interval), above the existing REAPPLY_LOOP_WARN_THRESHOLD so the non-convergence warning still fires first.

  • Once num_consecutive_reapplies crosses it, the loop calls rebuild_plan(model) instead of re-sending the stale plan. If the model has since been corrected, the rebuilt plan is runnable, and the cluster converges (installing a new plan resets the counter via the existing reset-on-new-plan logic).

  • Rebuilds are throttled to once every REAPPLY_LOOP_RESCHEDULE_THRESHOLD cycles to avoid rebuild storms when the model still describes an unreachable state.

Testing

  • New unit test test_control_running_plan_rebuilds_after_persistent_reapplies: drives the reapply branch below the threshold (asserting the un-runnable task stays planned and the counter grows), then asserts the threshold cycle rebuilds from the model, drops the task, and resets the counter.

@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: b6bb7f04a3

ℹ️ 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".

plans_diff=?indexing_plans_diff,
"reapplying the last plan is not converging: rebuilding the plan from the model"
);
self.rebuild_plan(model);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Rebuild without seeding from the stuck plan

In the stuck shard-placement case this still calls the normal rebuild_plan, which passes self.state.last_applied_physical_plan.as_ref() into build_physical_indexing_plan and the scheduler reuses previous sharded tasks before assigning missing shards. When the model correction is only that a shard is no longer located on the old indexer, the rebuilt plan can be identical to the non-runnable one, so the new threshold path does not actually break the reapply loop it is meant to recover from; this path needs a way to build from the current model without preserving the stale physical assignment.

Useful? React with 👍 / 👎.

@aanufriev-celonis aanufriev-celonis force-pushed the escalate-reapply-to-rebuild branch from d188b5a to e89bbdc Compare July 13, 2026 18:52
@aanufriev-celonis

Copy link
Copy Markdown
Author

I had a couple more ideas in mind on how to tackle this problem, but decided to go with the least intrusive one. Below are some thoughts about alternative paths:

  • teach indexers to communicate back to CP the plan apply results, but that is quite some protocol work, would be more changes in the end;
  • try something around TTL, but I guess that idea didn't go far, I have found this commit from the past and I guess the idea was left: 4b6a240;
  • fix the model: currently, indexers after restart report reachable shared, but do not report lost ones, so CP does delete/trucate only those that are reported, and keeps ones that were not reported -> inconsistency; still, it can delete/close what was not reported, but this is a destructive change, so I decided to not go this way.

@aanufriev-celonis

Copy link
Copy Markdown
Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Chef's kiss.

Reviewed commit: f3c74cf095

ℹ️ 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".

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.

1 participant