-
Notifications
You must be signed in to change notification settings - Fork 44
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Co-operatively cancel all RPC Calls #576
Co-operatively cancel all RPC Calls #576
Conversation
cancellationTokenSource.Cancel(); | ||
await task; | ||
})).And.Message.Should().Contain($"An error occurred when sending a request to 'https://20.5.79.31:10933/', after the request began: The operation was canceled."); | ||
})).And.Message.Should().Contain($"An error occurred when sending a request to 'https://20.5.79.31:10933/', after the request began: The Request was cancelled while Connecting."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exception contract change - The error message changes
(await AssertException.Throws<HalibutClientException>(async () => await client.SayHelloAsync("Hello", new(cancellationTokenSource.Token, CancellationToken.None)))) | ||
.And.Message.Should().Contain("An error occurred when sending a request to 'https://20.5.79.31:10933/', after the request began: The operation was canceled."); | ||
(await AssertException.Throws<HalibutClientException>(async () => await client.SayHelloAsync("Hello", new(cancellationTokenSource.Token)))) | ||
.And.Message.Should().Contain("An error occurred when sending a request to 'https://20.5.79.31:10933/', after the request began: The Request was cancelled while Connecting."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exception contract change - The error message changes
exception.Message.Should().Be($"An error occurred when sending a request to '{clientAndService.ServiceUri}', after the request began: The ReadAsync operation was cancelled."); | ||
#endif | ||
var exception = (await AssertException.Throws<HalibutClientException>(async () => await client.SayHelloAsync("Hello", new(cancellationTokenSource.Token)))).And; | ||
exception.Message.Should().Be($"An error occurred when sending a request to '{clientAndService.ServiceUri}', after the request began: The Request was cancelled while Connecting."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exception contract change - The error message changes
(await AssertException.Throws<HalibutClientException>(async () => await doSomeActionClient.ActionAsync(new(cancellationTokenSource.Token, cancellationTokenSource.Token)))) | ||
.And.Message.Should().Contain($"An error occurred when sending a request to '{clientAndService.ServiceUri}', after the request began: The ReadAsync operation was cancelled."); | ||
(await AssertException.Throws<HalibutClientException>(async () => await doSomeActionClient.ActionAsync(new(cancellationTokenSource.Token)))) | ||
.And.Message.Should().Contain($"An error occurred when sending a request to '{clientAndService.ServiceUri}', after the request began: The Request was cancelled while Transferring."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exception contract change - The error message changes
@@ -240,15 +240,8 @@ public async Task WhenTheListeningRequestIsCancelledWhileConnecting_AndTheConnec | |||
|
|||
var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(5)); | |||
|
|||
#if NETFRAMEWORK |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice that we could get rid of this 😄
source/Halibut.Tests/ServiceModel/PendingRequestQueueFixture.cs
Outdated
Show resolved
Hide resolved
source/Halibut.Tests/WhenCancellingARequestForAPollingTentacle.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Nice to see this make its way back again 😁
namespace Halibut.Tests.Support.PendingRequestQueueFactories | ||
{ | ||
/// <summary> | ||
/// CancelWhenRequestDequeuedPendingRequestQueueFactory cancels the cancellation token source when a request is queued |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
when request is de
queued?
8c406ed
to
0274644
Compare
Combine connecting and in progress cancellation tokens
0274644
to
0dd6357
Compare
This is a combination of the reverted PRs #525 and #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 ✔️
Pre-requisites