-
Notifications
You must be signed in to change notification settings - Fork 91
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
Support sending requests with CancellationToken #262
Comments
@bgold09 I believe it will be useful. Will implement it and upload a new version of the library in a few hours. |
@bgold09 I implemented the methods and tried it out but all requests with CancellationToken set to true throw errors that tasks have been canceled. I could not find any proper solution after an hour research. Do you have any other suggestions? |
@ivaylokenov if you add a custom message handler to the HttpConfiguration used to initialize the server, does the CancellationToken at least flow through to its SendAsync() method? Does the exception come from the server or the client message invoker? |
@bgold09 I tried with both custom OWIN handler and message handler on the HttpConfiguration and it doest not reach it. The code throws errors on the https://github.com/ivaylokenov/MyTested.WebApi/blob/master/src/MyTested.WebApi/Builders/Servers/ServerTestBuilder.cs#L124 line so I expect the task to throw in the client. The request does not gets processed on the server. |
Is an OperationCanceledException being thrown? If so, I suspect that CancellationToken.ThrowIfCancellationRequested() is being called somewhere in the depths of System.Net.Http.dll. |
@bgold09 Actually it is TaskCanceledException. Looking through this code: There are numerous checks for the cancellation token and I guess it is normal that we receive the exception. I guess it will not be possible to implement this feature? I am out of ideas. |
Hmm, let me do a bit of digging and get back to you. I agree though, it looks like this is less straightforward than I originally thought. |
@ivaylokenov I think I understand what's happening now, as I was misunderstanding part of how CancellationTokens are supposed to be used. We should instead be asking the user to pass a CancellationTokenSource which can be used to get an associated CancellationToken. What we actually would want here is to create a method invoker.SendAsync(this.httpRequestMessage, this.cancellationTokenSource.Token).Result; For example, the user could then create a new CancellationTokenSource which cancels the operation after a certain amount of time: var tokenSource = new new CancellationTokenSource(TimeSpan.FromSeconds(30));
MyWebApi.Server().Working().WithCancellationTokenSource(tokenSource); |
@bgold09 Yes, we both misunderstood it obviously. Otherwise, with the One final thought before I implement this feature - if the only parameter the developer can use is a |
Fair point; in that case, the user could then initialize a default CancellationTokenSource, keep it in a local variable, pass it to WithCancellationTokenSource() and later call CancellationTokenSource.Cancel() to manually do it. That should provide more control. We should include one such example in the documentation, as well as an example where the CancellationTokenSource is initialized with a TimeSpan value. |
@bgold09 Unfortunately, when I tried that it did not work as again This is the Owin class I tried: public class CancellationStartup
{
public static CancellationTokenSource CancellationTokenSource = new CancellationTokenSource();
public void Configuration(IAppBuilder app)
{
app.Use((context, next) =>
{
CancellationTokenSource.Cancel();
if (context.Request.CallCancelled.IsCancellationRequested)
{
context.Response.StatusCode = 500;
context.Response.Write("Canceled");
}
return next();
});
}
} And this is the test: MyWebApi
.Server()
.Working<CancellationStartup>()
.WithCancellationTokenSource(CancellationStartup.CancellationTokenSource)
.WithHttpRequestMessage(req => req.WithMethod(HttpMethod.Get))
.ShouldReturnHttpResponseMessage()
.WithStatusCode(HttpStatusCode.InternalServerError); This feature became harder than it looked at first. |
Is there any way to swallow the exception being thrown in the HttpClient? If I understood correctly, the cancellation does happen in the startup code you have above. The interesting case for me is whether or not I can get this cancellation notification in some custom message handler, so that I can ensure that it is properly handling this case from the perspective of my service. |
@bgold09 Yes, I am canceling the token in the OWIN inline handler, and then the Otherwise - for a particular handler, which handles the cancellation - will a simple unit test work for validating the behavior without running the whole pipeline? Can I see the handler code? |
I agree, I think it's fine to simply unit test this. Originally I was trying to see if the cancellation could be piped through to various methods as well, but I think now that I better understand cancellation tokens this is not really needed. Feel free to close this and thanks for following up. |
You are welcome! 👍 |
When testing the full server stack, it can be useful to invoke an operation with a CancellationToken other than CancellationToken.None, i.e.
This support can be introduced by modifying ServerTestBuilder:
CancellationToken cancellationToken
to the class, which by default is initialized to CancellationToken.None to preserve the current behaviorIServerTestBuilder WithCancellationToken(CancellationToken cancellationToken)
which sets the private fieldWhat are your thoughts on this idea and its potential implementation? I'd be happy to implement it myself; your library has already been very helpful in testing my WebApi application.
The text was updated successfully, but these errors were encountered: