OctopusDeploy / Halibut

| Public | A secure communication stack for .NET using JSON-RPC over SSL.
Other
12 stars 44 forks source link

Co-operatively cancel all RPC Calls #576

Closed nathanwoctopusdeploy closed 9 months ago

nathanwoctopusdeploy commented 9 months ago

This is a combination of the reverted PRs https://github.com/OctopusDeploy/Halibut/pull/525 and https://github.com/OctopusDeploy/Halibut/pull/558 combined and rebased

Background

[sc-58429]

Before Async Halibut was introduced, Halibut only supported cancellation of an RPC call when the request was in the connecting state, queued for a Polling Request and the TCP Connection being established for a Listening Request. Once the RPC was in flight, dequeued for a Polling Request, and the connection established for a Listening Request, cancellation was not supported.

As the cancellation of an in-flight request was not supported, a caller would only have the option to walk away from an RPC call and leave threads and IO running.

When Async Halibut was introduced, cooperative cancellation was introduced down to the socket for RPC calls to Listening Service and to the queue for Polling Services. Cancellation could be performed if the RPC call was connecting and in-flight. So as not to force clients to change there existing behaviour, two cancellation tokens were introduced, one to cancel when connecting and one to cancel when in-flight.

Results

This PR extends the previous cancellation support so that an in-flight Polling Request can be cancelled to the Socket. Terminating any in-flight Reads or Writes on the TCP Connection.

The two cancellation tokens have been combined into one to simplify the cancellation logic. The ability to cancel just when connecting is no longer required in TentacleClient. Instead, the desire is to co-operatively cancel an RPC call regardless of it's current state.

Tentacle Client does need to know if the cancelled RPC call was connecting or in flight to make the most efficient decisions about what it has to do next, so cancellation will throw specific errors based on the state of the RPC call when it was cancelled.

net48 does not support full cancellation due to the usage of a deflate stream, which uses APM Begin and End methods and loses the cancellation token. As TentacleClient only supports net6.0, this is not an issue.

How to review this PR

Quality :heavy_check_mark:

Pre-requisites

shortcut-integration[bot] commented 9 months ago

This pull request has been linked to Shortcut Story #58429: After 2023.4 - Revisit RPC Retries once Sync Halibut is deleted and optimistically/co-operatically cancel RPC calls and Script Execution.