Monday, May 23, 2022

How to Cancel a Query in Azure Cosmos DB



     Sometimes you go to a website and the page does not want to open for whatever reason. You might just click Stop and move on to another page. The stop button does not really stop the request, the server still tries to complete the request and send a response to the client even client does not exist anymore. Rather than clicking on Stop maybe you click Refresh which triggers another request when the first one is not completed yet.

      This scenario applies to all database calls. It might take longer to run a query for a reason and simply you need to wait until you get a response from the database server. If it takes too much time, you might want to cancel the request and try to look at your query to make it faster. You can do that programmatically by using CancellationTokens.

      CancellationTokens is a .NET mechanism. The program will not stop immediately when it receives a cancellation token. .NET will cancel the operation when it is safe to do so. .NET does not want to cause any conflicts, invalid states, or corruptions.

     Here is a simple example to use CancellationTokens in Azure Cosmos DB .NET SDK.

    var cosmosClient = new CosmosClient(connectionString);
    Container container = cosmosClient.GetContainer("Stackoverflow", "Posts");
    var cmd = "SELECT * FROM Posts o WHERE o.PostId < 500";
    var queryResultSetIterator = container.GetItemQueryIterator<StackOverflowPost>(query);
    var posts = new List<StackOverflowPost>();
    var canceltoken = new CancellationTokenSource();
    Console.WriteLine("Loading Items to Update...");
    try
    {
      while (queryResultSetIterator.HasMoreResults)
      {
         var currentResultSet = await queryResultSetIterator.ReadNextAsync(canceltoken.Token);
         foreach (StackOverflowPost current in currentResultSet)
         {
            posts.Add(current);
         }
         if (posts.Count > 250)
         {
           canceltoken.Cancel();
           Console.WriteLine("Cancelled.");
         }
      }
      Console.WriteLine("Number of Posts : " + posts.Count);
      return posts;
    }
    catch (Exception ex)
    {
       Console.WriteLine(ex.Message.ToString());
       return null;
    }
  

      First I declared a cancellationtokensource named cancel token then I passed it to the Cosmos DB ReadNextAsync function. After this, the application will watch for any cancellation requests. This request can come directly from the user or you can programmatically raise a cancellation request like the one I have on this code. I see the following screen when I run this code.


     The application throws a "The operation was canceled" error exception and stops running the code. Technically this is an error but you may want to handle it differently since the request might be coming from a user. The following code checks the exception type and changes the message.

   catch (Exception ex)
    {
       if (ex is CosmosOperationCanceledException)
       {
          Console.WriteLine("Cancel Request is received.");                    
       }
       else {      
          Console.WriteLine(ex.Message.ToString());
       }
       return null;
    }
   


No comments:

Post a Comment