Feature request: Extended ICancellationStrategy cancellation strategy #1326
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Reason for Change Proposal
We are using this library to remotely control our test machines. However, the current implementation of
ICancellationStrategyis quite restrictive.We would like to bind the
IHostApplicationLifetime.ApplicationStoppingcancellation token to requests in order to perform a graceful shutdown, rather than abruptly closing the WebSocket connection.After experimenting extensively with different configurations, I have been unable to find a viable workaround within the current implementation.
At present, the
JsonRpcconstructor explicitly creates aStandardCancellationStrategy, which then registers the$/cancelRequestmethod endpoint. This design prevents a custom implementation ofICancellationStrategyfrom being used while maintaining the same cancellation logic.Attempted Workaround
I built a wrapper around the existing
ICancellationStrategyto track request IDs independently, so that requests could be cancelled gracefully when the host application stops:Unexpectedly, this caused
StandardCancellationStrategy.inboundCancellationSourcesto be populated correctly duringIncomingRequestStarted, but to appear empty in theCancelInboundRequestmethod.Suggested Fix
Move the construction of
StandardCancellationStrategyinto theJsonRpc.CancellationStrategyproperty as a nullable assignment.This would allow developers to override the default behaviour before the method is reserved, without breaking existing functionality:
// JsonRpc.cs public class JsonRpc { public JsonRpc(IJsonRpcMessageHandler messageHandler) { // ... - this.CancellationStrategy = new StandardCancellationStrategy(this); } public ICancellationStrategy? CancellationStrategy { - get => this.cancellationStrategy; + get => this.cancellationStrategy ??= new StandardCancellationStrategy(this); set { this.ThrowIfConfigurationLocked(); this.cancellationStrategy = value; } } }Possible Alternative Solutions
CancelAllRequestsmethod toICancellationStrategy, allowing the user to cancel from outside of the strategy. (Doesn't solve the method name clash for own implementation)RegisterExternalCancellationTokentoStandardCancellationStrategy, registering the cancellation for the user with a convenience method. (Doesn't solve the method name clash for own implementation)builder.WithCancellationStrategy<TStrategy>(), this would allow for much more expressive configuration.Current Impact
This limitation is currently blocking a pending release.
As a temporary workaround, I’m passing the
CancellationTokeninto each concrete type’s constructor and creating linked sources for every method, which not ideal but will do for the time.I am happy to contribute more to this should you want to go down the alternative solutions route.