Skip to content

De-flake ShardRegionQueriesSpecs: async cluster formation, realistic Ask timeouts, proxy-side logging - #8618

Merged
Aaronontheweb merged 1 commit into
akkadotnet:devfrom
Aaronontheweb:fix/shardregionqueries-remote-ask-timeout
Sep 23, 2026
Merged

Aaronontheweb merged 1 commit into
akkadotnet:devfrom
Aaronontheweb:fix/shardregionqueries-remote-ask-timeout

Conversation

@Aaronontheweb

Copy link
Copy Markdown
Member

ShardRegionQueriesSpecs.ShardRegion_should_support_GetEntityLocation_query_remotely failed on a 2-vCPU Windows agent (in a #8606 build, which doesn't touch sharding or remoting) with AskTimeoutException: Timeout after 3.00 seconds on its first Ask through a new proxy region.

What happened

Time Event
17:00:10.96 Sys and the proxy system associate
17:00:17.75 Sys marks the proxy node UNREACHABLE
17:00:22.93 EndpointDisassociatedException: Disassociated; the address is gated for 5 s
~17:00:22.5–25.5 The 3 s Ask runs and dies inside the gate
  • Not SBR: it waits stable-after = 20s before acting, so it couldn't have acted this early.
  • Not the transport failure detector: it needs 4 s + 120 s.
  • Not a remoting idle timeout: there is no idle handler in the DotNetty pipeline.
  • Likely cause: the proxy side closed the socket or sent Disassociate(Unknown). The proxy system's log wasn't connected to the test output, so this run can't say why. The root cause of the disconnect is still open. This PR adds the logging needed to see it next time.

A healthy link would not have saved the test either. The first message through a new region waits on the region's registration retries (250 ms, 500 ms, 1 s, then every 2 s; GetShardHome is re-sent on that tick). One lost message plus a gate cycle costs about 7–8 s, so 3 s had no slack.

Change

  • Timeouts: entity Asks now use Dilated(10s), and GetEntityLocation queries use Dilated(3s), in all three tests.
  • Setup: StartAsync plus the 2-node cluster formation move from the constructor's synchronous AwaitAssert into InitializeAsync, using JoinAsync, which waits for the real MemberUp. It follows the pattern in ClusterShardingLeaseSpec. If setup throws, the class disposes itself, because xUnit v3 doesn't dispose a class whose InitializeAsync failed.
  • Logging: InitializeLogger(_proxySys, "[proxy]") sends the proxy system's log to the test output.
  • Not changed: the cluster failure detector. "Unreachable" never touches remoting, and a longer heartbeat pause wouldn't have avoided the gate.

Verification (local)

  • 5/5 runs of the class (3 tests each) pass.

… asking with 1-3 s timeouts

ShardRegion_should_support_GetEntityLocation_query_remotely timed out on
its first Ask through a freshly started proxy region on a 2-vCPU Windows
agent. The Sys-side association to the proxy system was dropped
(EndpointDisassociatedException, address gated for 5 s) while that Ask
was in flight, and the 3 s timeout died inside the gate. Even without a
dropped link the first message through a new region can need the region's
registration retries, which settle at 2 s apart, so 3 s had no slack.

- Entity Asks use Dilated(10s), GetEntityLocation queries Dilated(3s).
- The region start and the 2-node cluster formation move from the ctor's
  synchronous AwaitAssert into InitializeAsync (StartAsync + JoinAsync),
  disposing the class if that throws, since xUnit will not.
- The proxy system's log is wired to the test output: why the proxy side
  closed the association is not visible in this run's log, and the next
  failure should show it.

@Aaronontheweb Aaronontheweb left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

LGTM

@Aaronontheweb
Aaronontheweb merged commit 3d7cd46 into akkadotnet:dev Sep 23, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant