Skip to content

Remove explainUnassignedShardAllocation side effects - #157766

Merged
joshua-adams-1 merged 12 commits into
mainfrom
tf-gateway-allocator-cluster-it
Sep 16, 2026
Merged

joshua-adams-1 merged 12 commits into
mainfrom
tf-gateway-allocator-cluster-it

Conversation

@joshua-adams-1

Copy link
Copy Markdown
Contributor

Currently, explainUnassignedShardAllocation tries to query the current state of the fetches. These calls come from threads other than the master-service thread. However, when calling fetchData, it potentially triggers additional fetches. This causes the race condition in the failing test ClusterDisruptionIT.testAckedIndexing where explainUnassignedShardAllocation gets an open fetch from the map which has become closed by the time we call fetchData. This change removes the ability for the explainUnassignedShardAllocation flow to mutate allocator fetch state

Closes: #155449

Currently, explainUnassignedShardAllocation tries to query the current state of the fetches. These calls come from threads other than the master-service thread. However, when calling fetchData, it potentially triggers additional fetches. This causes the race condition in the failing test ClusterDisruptionIT.testAckedIndexing where explainUnassignedShardAllocation gets an open fetch from the map which has become closed by the time we call fetchData. This change removes the ability for the explainUnassignedShardAllocation flow to mutate allocator fetch state

Closes: #155449
@joshua-adams-1 joshua-adams-1 self-assigned this Aug 26, 2026
@joshua-adams-1 joshua-adams-1 added >bug :Distributed/Distributed A catch all label for anything in the Distributed Area. Please avoid if you can. labels Aug 26, 2026
@elasticsearchmachine

Copy link
Copy Markdown
Collaborator

Hi @joshua-adams-1, I've created a changelog YAML for you.

@github-actions

github-actions Bot commented Aug 26, 2026 •

Copy link
Copy Markdown
Contributor

🔍 Preview links for changed docs

⏳ Building and deploying preview... View progress

This comment will be updated with preview links when the build is complete.

@joshua-adams-1

joshua-adams-1 commented Aug 26, 2026 •

Copy link
Copy Markdown
Contributor Author

NB the test failure was on 9.3 (no longer supported), so I don't need to remove a muted-test entry, and I will backport this fix to 9.5 and 9.4 only. I don't need to backport to 8.19 since the debug logging was introduced in 9.2 in #133958

NB SearchableSnapshotAllocator.explainUnassignedShardAllocation → decideAllocation → fetchData has a similar flow to this PR, so if you agree, I can push a follow up PR to fix the same bug there

@github-actions

Copy link
Copy Markdown
Contributor

ℹ️ Important: Docs version tagging

👋 Thanks for updating the docs! Just a friendly reminder that our docs are now cumulative. This means all 9.x versions are documented on the same page and published off of the main branch, instead of creating separate pages for each minor version.

We use applies_to tags to mark version-specific features and changes.

Expand for a quick overview

When to use applies_to tags:

✅ At the page level to indicate which products/deployments the content applies to (mandatory)
✅ When features change state (e.g. preview, ga) in a specific version
✅ When availability differs across deployments and environments

What NOT to do:

❌ Don't remove or replace information that applies to an older version
❌ Don't add new information that applies to a specific version without an applies_to tag
❌ Don't forget that applies_to tags can be used at the page, section, and inline level

🤔 Need help?

@joshua-adams-1 joshua-adams-1 added auto-backport Automatically create backport pull requests when merged v9.5.3 v9.4.7 v8.19.22 labels Aug 26, 2026
ShardRouting unassignedShard,
RoutingAllocation allocation,
Logger logger,
boolean allocate

@joshua-adams-1 joshua-adams-1 Aug 26, 2026 •

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.

The hierarchy of classes in this part of the codebase is a little confusing. Since this is called by both the allocation and explain flows, I needed a way to distinguish between them, and a simple boolean flag seemed to be the best way (I couldn't find some other way to just "know" which path we're on without being explicit with a flag).

@joshua-adams-1
joshua-adams-1 marked this pull request as ready for review August 27, 2026 09:25
@elasticsearchmachine elasticsearchmachine added the Team:Distributed Meta label for distributed team. label Aug 27, 2026
@elasticsearchmachine

Copy link
Copy Markdown
Collaborator

Pinging @elastic/es-distributed (Team:Distributed)

@joshua-adams-1

Copy link
Copy Markdown
Contributor Author

@DaveCTurner Hey, a gentle nudge if you have time this week for a review

@DaveCTurner

Copy link
Copy Markdown
Member

I don't particularly like adding a new boolean flag like that, although I do appreciate that it lets us use pretty much the same code on both the allocate and explain paths.

Yet, is this really doing anything different from RoutingAllocation#debugDecision()? AFAICT this is always false when we're genuinely allocating (and want to trigger new fetches), and always true on the explain (peek-only) path. Could we use that instead?

Could we also use org.elasticsearch.cluster.service.MasterService#assertMasterUpdateOrTestThread to ensure that we don't introduce any new trigger-new-fetches path outside of cluster state updates?

}

// Allocation should run only off the master thread
assert MasterService.assertMasterUpdateOrTestThread();

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.

There's always the possibility this causes a test failure down the line, but that would be proof of a bug, right? So it's okay to add this assertion?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yep exactly. Tho the comment says "off the master thread" and I think you mean "on the master thread".

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.

Ahaha the irony is that I wrote this comment and not an LLM 🤦

@DaveCTurner DaveCTurner left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM, with a couple of optional nits

final FetchResult<NodeGatewayStartedShards> shardState = fetchData(unassignedShard, allocation);
if (shardState.hasData() == false) {
allocation.setHasPendingAsyncFetch();
if (explain == false) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't think we need this extra if here, it doesn't matter if we set this flag while explain is true does it?

if (shardStores.hasData() == false) {
logger.trace("{}: ignoring allocation, still fetching shard stores", unassignedShard);
allocation.setHasPendingAsyncFetch();
if (explain == false) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Similarly here?

Comment on lines +61 to +63
* <p>
* This method may run on threads other than the master service thread. Implementations must not start new
* fetches or otherwise mutate allocator fetch state.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not sure this comment is all that helpful (unlike the assertions that check we're on the expected thread)

@joshua-adams-1
joshua-adams-1 merged commit af83102 into main Sep 16, 2026
39 checks passed
@joshua-adams-1
joshua-adams-1 deleted the tf-gateway-allocator-cluster-it branch September 16, 2026 15:26
@elasticsearchmachine

Copy link
Copy Markdown
Collaborator

💚 Backport successful

Status Branch Result
✅ 9.4
✅ 9.5

elasticsearchmachine pushed a commit that referenced this pull request Sep 16, 2026
Currently, `explainUnassignedShardAllocation` tries to query the current state of the fetches. These calls come from threads other than the master-service thread. However, when calling `fetchData`, it potentially triggers additional fetches. This causes the race condition in the failing test `ClusterDisruptionIT.testAckedIndexing` where `explainUnassignedShardAllocation` gets an open fetch from the map which has become closed by the time we call `fetchData`. This change removes the ability for the `explainUnassignedShardAllocation` flow to mutate allocator fetch state

Closes: #155449
elasticsearchmachine pushed a commit that referenced this pull request Sep 16, 2026
Currently, `explainUnassignedShardAllocation` tries to query the current state of the fetches. These calls come from threads other than the master-service thread. However, when calling `fetchData`, it potentially triggers additional fetches. This causes the race condition in the failing test `ClusterDisruptionIT.testAckedIndexing` where `explainUnassignedShardAllocation` gets an open fetch from the map which has become closed by the time we call `fetchData`. This change removes the ability for the `explainUnassignedShardAllocation` flow to mutate allocator fetch state

Closes: #155449
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

auto-backport Automatically create backport pull requests when merged >bug :Distributed/Distributed A catch all label for anything in the Distributed Area. Please avoid if you can. Team:Distributed Meta label for distributed team. v9.4.8 v9.5.5 v9.6.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[CI] ClusterDisruptionIT testAckedIndexing failing

3 participants