Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I always add CancellationToken to my controller actions?

Is this a good practice to always add CancellationToken in my actions no matter if operation is long or not?

I'm currently adding it to every action and I don't know if it's right or wrong.

[ApiController] [Route("api/[controller]")] public class DummiesController : ControllerBase {     private readonly AppDbContext _dbContext;      public DummyController(AppDbContext dbContext)     {         _dbContext = dbContext;     }      [HttpGet("{id}")]     public async Task<ActionResult<Dummy>> GetAsync(int id, CancellationToken ct) // <<----- should I always do this?     {         var dummy = await _dbContext.Dummies.AsNoTracking().SingleOrDefaultAsync(e=>e.Id == id, ct);         if (dummy == null) return NotFound();         return dummy;     } } 

Also is adding CancellationToken ct = default(CancellationToken) necessary?

like image 518
Konrad Avatar asked May 14 '18 11:05

Konrad


People also ask

When should I use CancellationToken?

So CancellationToken can be used to terminate a request execution at the server immediately once the request is aborted or orphan. Here we are going to see some sample code snippets about implementing a CancellationToken for Entity FrameworkCore, Dapper ORM, and HttpClient calls in Asp.

What is the purpose of CancellationToken?

A CancellationToken enables cooperative cancellation between threads, thread pool work items, or Task objects. You create a cancellation token by instantiating a CancellationTokenSource object, which manages cancellation tokens retrieved from its CancellationTokenSource. Token property.

Can you reuse CancellationTokenSource?

CancellationTokenSource is quite a heavyweight object and its not normally cancelled; however it can't be pooled or reused because its registrations cannot be cleared.

How do I cancel my CancellationToken?

CancellationToken is immutable and must be canceled by calling CancellationTokenSource. cancel() on the CancellationTokenSource that creates it. It can only be canceled once.


2 Answers

Should I always add CancellationToken to my controller actions?

No. You should not always.

Using CancellationTokens in ASP.NET Core MVC controllers
https://andrewlock.net/using-cancellationtokens-in-asp-net-core-mvc-controllers/

Whether this is correct behaviour will depend on your app. If the request modifies state, then you may not want to halt execution mid-way through a method. On the other hand, if the request has no side-effects, then you probably want to stop the (presumably expensive) action as soon as you can.

So if you have a method/action like below (simplified);

await ProcessOrder(); await UpdateInventory(); 

You do not want to cancel the order while it is being processed, if so, order can be completed, but you will not update the inventory if user passing through the tunnel, and loses the internet connection.

This is especially important when operations cannot be included in a Unit of Work like pattern (e.g. distributed system) and one should try to minimize cancellations.

like image 174
Teoman shipahi Avatar answered Sep 28 '22 08:09

Teoman shipahi


It's worthwhile adding if you have any dependency on an external resource.

Let's say your database is busy, or you have transient error handling / retry policies in place for your database connection. If an end user presses stop in their browser the cancellation token will aid any waiting operations (in your code) to cancel gracefully.

Think of it less about the long running nature under normal circumstances, but long running nature in less than ideal circumstances e.g. if running in Azure and your SQL database is undergoing routine maintenance and entity framework is configured to retry itself (asuming Entity framework responds to cancellation tokens sensibly).

As a side note: Polly resilience framework has excellent support for external cancellation tokens to coordinate retry cancellations from an external cancellation. Their wiki is worthwhile a read as it's a great eye opener to coordinating cancellation: https://github.com/App-vNext/Polly/wiki

Regarding CancellationToken ct = default(CancellationToken), it's probably more worthwhile on library code than on a Controller action. But handy if you are unit testing your controller directly but don't want to pass in a cancellation token. Having said that .net core's WebHostBuilder testframework is easier to test against than testing controller actions directly these days.

like image 27
Alex KeySmith Avatar answered Sep 28 '22 08:09

Alex KeySmith