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:
- The gateway sends a correlated
CANCELframe when the caller abandons a request or its bound expires. - The microservice transport cancels the request-specific token source for that correlation.
AspNetRouterRequestDispatcherexposes that same token asHttpContext.RequestAborted.- ASP.NET endpoint handlers, model binders, filters, and downstream operations observing
RequestAbortedstop 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:
- no signed control-lane target is available; or
- at least one live healthy replica does not advertise the control-lane capability.
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
- The transport creates, owns, cancels, and disposes the request token source.
- The dispatcher does not create a second token source because there is no additional cancellation source to combine.
- The dispatcher must not dispose or detach the transport linkage before the endpoint delegate and response capture complete.
OperationCanceledExceptioncaused by the supplied token is rethrown so the transport can complete the correlated cancellation path without manufacturing an HTTP error response.
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:
- correlate the Router request and
CANCELframe identifiers; - confirm the service transport cancels the matching request token source;
- verify the endpoint observes
HttpContext.RequestAborted; - run the focused dispatcher test before repeating the live forcing gate.
Related documents:
docs/modules/router/architecture.md- Router request and CANCEL frame flow.docs/modules/router/messaging-valkey-transport.md- messaging request/control lanes.docs/modules/router/aspnet-endpoint-bridge.md- ASP.NET endpoint discovery and dispatch.
