Click here to Skip to main content
13,899,227 members
Click here to Skip to main content
Add your own
alternative version

Tagged as

Stats

5.8K views
4 bookmarked
Posted 27 Dec 2018
Licenced CPOL

Azure Cosmos DB + Functions Cookbook— static client

, 27 Dec 2018
Azure Cosmos DB is Microsoft’s globally distributed multi-model database, when we team it up with Azure Functions, Azure’s serverless compute service, the result is the ideal database for the serverless era.

Editorial Note

This article is in the Product Showcase section for our sponsors at CodeProject. These articles are intended to provide you with information on products and services that we consider useful and of value to developers.

Preface

By definition, synergy happens when the interaction between two elements produces an effect greater than the individual elements’ contribution.

Azure Cosmos DB is Microsoft’s globally distributed multi-model database, when we team it up with Azure Functions, Azure’s serverless compute service, the result is the ideal database for the serverless era.

In this series of posts I’ll explore different recipes, gotchas and examples of this integration targeting specific scenarios and act as building blocks for your architecture.

Using and scaling

With Azure Functions, we can create small pieces of code that will run based on events (time, HTTP calls, message queues, database operations, to name a few) and can scale independently to adjust to your computational needs. While we technically do not see nor worry about the servers hosting our Functions (it’s serverless after all!), there is a Runtime (or ScriptHost) that maintains the memory space (besides other things) where our Functions run.

When working with Azure Cosmos DB, we might have seen code that uses the using statement with the DocumentClient (after all, it implements the IDisposable interface) so we might be tempted to do this in our Function’s code:

#r "Microsoft.Azure.Documents.Client"
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using System.Net;

private static string endpointUrl = ConfigurationManager.AppSettings["cosmosDBAccountEndpoint"]; 
private static string authorizationKey = ConfigurationManager.AppSettings["cosmosDBAccountKey"]; 

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
    // Avoid doing this!
    using (DocumentClient client = new DocumentClient(new Uri(endpointUrl), authorizationKey)){ 
        string id = req.GetQueryNameValuePairs()
            .FirstOrDefault(q => string.Compare(q.Key, "id", true) == 0)
            .Value;
        if (string.IsNullOrEmpty(id)){
          return req.CreateResponse(HttpStatusCode.BadRequest);
        }

        Uri documentUri = UriFactory.CreateDocumentUri("name of database","name of collection",id);
        Document doc = await client.ReadDocumentAsync(documentUri);

        if (doc == null){
          return req.CreateResponse(HttpStatusCode.NotFound);
        }

        return req.CreateResponse(HttpStatusCode.OK, doc);
    }
}

The problem with this approach is that it is creating an instance of the DocumentClient in each execution. We all know the woes of this approach for the HttpClient (and if you don’t, please read it right after this article!), and it has the exact same effect here: If the Function is getting a high volume of triggers, we not only will be penalizing the performance of our database calls with the initialization overhead but the memory consumption will raise and we might even incur in socket exhaustion scenarios.

The static client

One of the first and easiest-to-achieve performance improvement we can implement when working with Azure Cosmos DB is to use a single DocumentClient instance for all the service calls (see the full performance article for more). When we are building applications, we could achieve this by Depedency Injection frameworks to maintain a Singleton instance, but how can we achieve this in our Functions’ code? Turns out it’s pretty easy! Just declare the DocumentClient as static outside of your Function’s Run code:

#r "Microsoft.Azure.Documents.Client"
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using System.Net;
using System.Configuration;

private static string endpointUrl = ConfigurationManager.AppSettings["cosmosDBAccountEndpoint"]; 
private static string authorizationKey = ConfigurationManager.AppSettings["cosmosDBAccountKey"]; 
private static DocumentClient client = new DocumentClient(new Uri(endpointUrl), authorizationKey);

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
    string id = req.GetQueryNameValuePairs()
        .FirstOrDefault(q => string.Compare(q.Key, "id", true) == 0)
        .Value;
    if (string.IsNullOrEmpty(id)){
      return req.CreateResponse(HttpStatusCode.BadRequest);
    }
  
    Uri documentUri = UriFactory.CreateDocumentUri("name of database","name of collection",id);
    Document doc = await client.ReadDocumentAsync(documentUri);

    if (doc == null){
      return req.CreateResponse(HttpStatusCode.NotFound);
    }
  
    return req.CreateResponse(HttpStatusCode.OK, doc);
}

For security purposes, the code is reading the Azure Cosmos DB Endpoint and Key from the Application Settings. Alternatively you could also use Azure Key Vault to store and retrieve this information. For more information, see my other related article.

This will effectively maintain one instance of the DocumentClient for all your Function’s executions within the same ScriptHost (instance) and improve the overall performance by reusing the same client for all service calls.

In an scenario where your Function App has multiple instances, each instance will maintain its own static client (it will not be shared among instances).

Stay tuned for more recipes!

Other posts in this series:

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Matías Quaranta
United States United States
Software Engineer @ Microsoft Azure Cosmos DB. Your knowledge is as valuable as your ability to share it.

You may also be interested in...

Comments and Discussions

 
-- There are no messages in this forum --
Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web06 | 2.8.190306.1 | Last Updated 27 Dec 2018
Article Copyright 2018 by Matías Quaranta
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid