Router ASP.NET request cancellation

Contract

AspNetRouterRequestDispatcher.DispatchAsync receives the cancellation token owned by the active Router transport request. The dispatcher assigns that token directly to HttpContext.RequestAborted before endpoint matching and keeps it valid for the complete dispatch lifetime.

This preserves the cancellation chain:

  1. The gateway sends a correlated CANCEL frame when the caller abandons a request or its bound expires.
  2. The microservice transport cancels the request-specific token source for that correlation.
  3. AspNetRouterRequestDispatcher exposes that same token as HttpContext.RequestAborted.
  4. ASP.NET endpoint handlers, model binders, filters, and downstream operations observing RequestAborted stop promptly.

Control-lane compatibility

The gateway fans a signed CANCEL to each live healthy replica advertising messaging-cancel-control.v1. A legacy copy is also placed on the shared service request queue only when it is still required for compatibility:

When every live healthy replica is capable, the legacy copy is omitted so cancellation traffic cannot queue ahead of later user requests. Mixed-version and legacy-only fleets retain exactly one shared-queue copy while capable replicas also receive their dedicated delivery.

The dedicated cancellation consumer leases up to CancelControlBatchSize controls per wake (default 128). This setting is intentionally independent from the normal BatchSize and MaxConcurrentRequests bounds. A cancellation burst can therefore drain in one control-loop lease without increasing ordinary request concurrency or response batch size. Non-positive values fail options validation at startup.

Ownership and lifetime

Regression guard

AspNetRouterRequestDispatcherTests.DispatchAsync_CancellationAfterEndpointStarts_CancelsRequestAbortedPromptly starts a dispatched endpoint, cancels only after endpoint execution has begun, and requires RequestAborted plus the dispatch task to settle inside a hard bound. This ordering prevents a pre-cancelled token from masking a lifetime regression.

AspNetRouterRequestDispatcherTests.CompositeDispatch_TransportTokenRemainsRequestAbortedUntilEndpointCompletes exercises the production composition boundary and requires the transport token observed by CompositeRequestDispatcher to remain the exact HttpContext.RequestAborted token until endpoint completion. This prevents a future wrapper or linked-token lifetime from silently detaching the transport cancellation chain.

MessagingTransportCancelFallbackTests proves the complementary queue contract: an all-capable fleet receives only dedicated control delivery, while mixed and legacy-only fleets retain the compatibility copy.

MessagingTransportCancelControlBatchTests records the actual control queue lease request, proves the default operational burst size is 128, and verifies configured-value and non-positive validation behavior independently from the normal request batch.

The live acceptance forcing gate complements the unit test with 48 authenticated Findings UI reads canceled after 35 ms. The gate then requires five sequential Findings summary reads to return without HTTP 504 or client timeout while Router and Findings remain healthy with no restarts or error logs.

Operational diagnosis

If cancellation appears to arrive at the transport but ASP.NET work remains in flight:

Related documents: