Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MongoDB C# driver CancellationToken

Does anyone know what the CancellationToken does if you add it with a parameter in the for example

public static UpdateResult UpdateMany<TDocument>(
    this IMongoCollection<TDocument> collection,
    Expression<Func<TDocument, bool>> filter,
    UpdateDefinition<TDocument> update,
    UpdateOptions options = null,
    CancellationToken cancellationToken = null
)

https://mongodb.github.io/mongo-csharp-driver/2.3/apidocs/html/M_MongoDB_Driver_IMongoCollectionExtensions_UpdateMany__1.htm

Is it a rollback? Or what does it do?

like image 772
StuiterSlurf Avatar asked May 02 '18 17:05

StuiterSlurf


1 Answers

A CancellationToken is generally used while writing asynchronous I/O code through the mongodb driver (InsertOneAsync for example). Lets take the following scenario into consideration. You are making breakfast. Example taken from here.

static async Task Main(string[] args)
{
    //Find eggs and bacon in database
    Task<List<Egg>> eggTask = FindEggsAsync(2);
    Task<List<Bacon>> baconTask = FindBaconAsync(3);

    Coffee cup = PourCoffee();
    Console.WriteLine("coffee is ready");
    
    Juice oj = PourOJ();
    Console.WriteLine("oj is ready");
    
    List<Egg> eggs = await eggTask;
    List<Bacon> bacon = await baconTask;
    
    FryEggs(eggs);
    Console.WriteLine("eggs are ready");

    FryBacon(bacon);
    Console.WriteLine("bacon is ready");
    
    Console.WriteLine("Breakfast is ready!");
}

This is good asynchronous code right ? We are awaiting our tasks only when we need the result from them.

We first need to find our eggs and bacon via I/O , lets imagine our eggs and bacon are stored in a mongodb as opposed to the pantry. So we send your 2 imaginary children with two tasks to find the eggs and bacon from the pantry(database).

While they find you pour yourself a cup of OJ and coffee that was already on hand(Basically Any CPU work).

With coffee and juice in hand you realize you are ready to prepare your ingredients , so you await the return of both tasks given to your kids and FryEggs and FryBacon.

Great breakfast is done - but lets assume you are a grumpy person and had a terrible morning , your coffee spills and this puts you completely off breakfast entirely(absurd I know), you need to tell your kids with tasks to stop searching. Lets amend the above code to integrate this.

static async Task Main(string[] args)
{
     var cancellationToken = new CancellationTokenSource(); 
    //Find eggs and bacon in database
    Task<List<Egg>> eggTask = FindEggsAsync(2,cancellationToken.Token);
    Task<List<Bacon>> baconTask = FindBaconAsync(3,cancellationToken.Token);

    Coffee cup = PourCoffee();
    if(cup.IsSpilled())
    {
        //Freak out and cancel tasks
        cancellationToken.Cancel();
        //Quit
        Environment.Exit(0)
    }  
    Console.WriteLine("coffee is ready");
    
    Juice oj = PourOJ();
    Console.WriteLine("oj is ready");
    
    List<Egg> eggs = await eggTask;
    List<Bacon> bacon = await baconTask;
    
    FryEggs(eggs);
    Console.WriteLine("eggs are ready");

    FryBacon(bacon);
    Console.WriteLine("bacon is ready");

    Console.WriteLine("Breakfast is ready!");
    //Dispose of token
    cancellationToken.Dispose();
}

The cancellation token itself will be passed to the async version of the mongodb driver method in Question. FindAsync will be called in the case of our two find methods and our cancellation token is passed in. If the task has not yet completed it will cancel the I/O operation accordingly.

like image 78
cl0ud Avatar answered Sep 28 '22 04:09

cl0ud