Skip to content

Artery: fix control-queue sizing, overflow observability, and shutdown races - #8346

Merged
Aaronontheweb merged 1 commit into
akkadotnet:devfrom
Aaronontheweb:fix/artery-queue-and-shutdown-robustness
Jul 9, 2026
Merged

Aaronontheweb merged 1 commit into
akkadotnet:devfrom
Aaronontheweb:fix/artery-queue-and-shutdown-robustness

Conversation

@Aaronontheweb

Copy link
Copy Markdown
Member

Three related Artery robustness fixes.

Control queue sizing. The control queue's default capacity (256) was 78x smaller than Pekko's outbound-control-queue-size default, so a mass-Unwatch burst during teardown of a system with a few thousand remote watches could overflow it and spuriously quarantine a perfectly healthy peer. The default is now 20000.

Overflow observability. Ordinary-outbound-queue overflow was dead-lettered via a raw DeadLetters.Tell, which double-wraps and hid the reason. It now publishes a Dropped event directly to the event stream (mirroring Pekko's Association.dropped()), so the standard DeadLetterListener logging and any Dropped subscribers see the message and the reason.

Shutdown races. Materializing a new outbound stream while the actor system is terminating threw an uncaught InvalidOperationException from the terminating StreamSupervisor (the existing guard only caught IllegalStateException behind shutdown flags that lag /user-guardian teardown); that exception is now treated as the shutdown signal it is and swallowed at Debug. A companion fix stops a throwing materialize callback from permanently stranding the materialize-once gate.

New HOCON knobs: akka.remote.artery.advanced.outbound-control-queue-size (20000) and akka.remote.artery.advanced.outbound-message-queue-size (3072, unchanged default).

Tests: new mass-Unwatch no-quarantine regression test, new shutdown-race spec (verified to fail with the fix reverted), Dropped-event assertions on the existing overflow test, and config round-trip coverage for the new knobs.

@Aaronontheweb Aaronontheweb added artery Akka.Remote Artery Protocol akka-remote bug akka.net v1.6 Akka.NET v1.6-related issues labels Jul 9, 2026
@Aaronontheweb

Copy link
Copy Markdown
Member Author

One review suggestion: in the new InvalidOperationException catch in MaterializeOutboundStream, include the exception in the Debug log (e.g. _log.Debug("...terminating. Cause: {2}", streamId, remoteAddress, e.Message)") — if a non-shutdown InvalidOperationExceptionever escapes materialization, the current line reduces it to a generic message and (with theMaterializeOnceGate` now resetting on throw) it would retry silently with nothing to diagnose by. Cheap insurance for a catch that intentionally has no flag guard.

@Aaronontheweb
Aaronontheweb marked this pull request as ready for review July 9, 2026 18:32

@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

/// <c>akka.remote.artery.advanced.outbound-control-queue-size</c> (<see cref="ArterySettings.OutboundControlQueueSize"/>).
/// </summary>
public const int DefaultControlQueueCapacity = 256;
public const int DefaultControlQueueCapacity = 20_000;

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

// caused spurious quarantines under a mass-termination Unwatch burst) rather than the
// registry's own hardcoded defaults -- see ArterySettings.OutboundMessageQueueSize /
// OutboundControlQueueSize.
_registry = new AssociationRegistry(_settings.OutboundMessageQueueSize, _settings.OutboundControlQueueSize);

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 enabled auto-merge (squash) July 9, 2026 18:42
…n races

The control queue default was 78x too small (256), so a mass-Unwatch
termination burst against a healthy peer could spuriously quarantine it;
the default is now 20000 (Pekko's outbound-control-queue-size), with new
HOCON knobs outbound-control-queue-size and outbound-message-queue-size.
Ordinary-queue overflow now publishes a Dropped event directly to the
event stream instead of a raw DeadLetters Tell. Stream materialization
that races actor-system termination no longer surfaces an uncaught
InvalidOperationException, and a throwing materialize callback no longer
strands the materialize-once gate.
@Aaronontheweb
Aaronontheweb force-pushed the fix/artery-queue-and-shutdown-robustness branch from 3f4c2cd to fa62d82 Compare July 9, 2026 19:08
@Aaronontheweb
Aaronontheweb disabled auto-merge July 9, 2026 19:52
@Aaronontheweb
Aaronontheweb merged commit 2c0107d into akkadotnet:dev Jul 9, 2026
9 of 11 checks passed
@Aaronontheweb
Aaronontheweb deleted the fix/artery-queue-and-shutdown-robustness branch July 9, 2026 20:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

akka.net v1.6 Akka.NET v1.6-related issues akka-remote artery Akka.Remote Artery Protocol bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant