Search code examples
c#httpclientazure-functionsazure-cosmosdb

HttpClient DocumentClient What Happens With Different Threads. Azure Functons


I read in an article about HttpClient/DocumentClient that it can be best practice to create a singleton for apps and inject it into object so that underlying resources are not exhausted by continued re-creating.How does this work? If an HttpClient is being accessed by various threads and making simultaneous calls to possibly different endpoints I can't see how this can work.

I read this

   https://medium.com/@nuno.caneco/c-httpclient-should-not-be-disposed-or-should-it-45d2a8f568bc

with interest. If I have an Azure Function making use of a DocumentClient calling cosmosDb how should I use the DocumentClient? Should it be a static instance?

I have my Azure function set up like this. I presume a new instance of DocmentClient is being created with every request which under high load could cause resource problems.

[FunctionName("MyGetFunc")]
    public static async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
    [CosmosDB("ct","ops", ConnectionStringSetting ="cosmosConn")] 
    DocumentClient docClient,
    ILogger log)

    //use docClient here...
    {

Solution

  • For the DocumentClient part of your question see here: https://learn.microsoft.com/en-us/sandbox/functions-recipes/cosmos-db?tabs=csharp#customize-a-documentclient-and-reuse-it-between-executions

    They talk about the different scenarios. So yes, if you have many Function invocations, I would use one static instance - which is also thread-safe.

    private static DocumentClient client = GetCustomClient();
    private static DocumentClient GetCustomClient()
    {
        DocumentClient customClient = new DocumentClient(
            new Uri(ConfigurationManager.AppSettings["CosmosDBAccountEndpoint"]), 
            ConfigurationManager.AppSettings["CosmosDBAccountKey"],
            new ConnectionPolicy
            {
                ConnectionMode = ConnectionMode.Direct,
                ConnectionProtocol = Protocol.Tcp,
                // Customize retry options for Throttled requests
                RetryOptions = new RetryOptions()
                {
                    MaxRetryAttemptsOnThrottledRequests = 10,
                    MaxRetryWaitTimeInSeconds = 30
                }
            });
    
        // Customize PreferredLocations
        customClient.ConnectionPolicy.PreferredLocations.Add(LocationNames.CentralUS);
        customClient.ConnectionPolicy.PreferredLocations.Add(LocationNames.NorthEurope);
    
        return customClient;
    }
    
    [FunctionName("CosmosDbSample")]
    public static async Task<HttpResponseMessage> Run(