Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ For configuring how the library connects to Cosmos, the library uses the `Cosmos
| `DatabaseThroughput` | The throughput provisioned for the database in measurement of Request Units per second in the Azure Cosmos DB service. |
| `SerializerOptions` | The `JsonSerializerOptions` used for the `System.Text.Json.JsonSerializer`. |
| `Credential` | The `TokenCredential` used for accessing [cosmos with an Azure AD token](https://docs.microsoft.com/en-us/azure/cosmos-db/managed-identity-based-authentication). Please note that setting this property will ignore any value specified in `AccountKey`. |
| `TelemetryOptions` | Configure the telemetry exposed about the Cosmos usage. |

<br/>

Expand Down
6 changes: 6 additions & 0 deletions src/Atc.Cosmos/CosmosOptions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Text.Json;
using Azure.Core;
using Microsoft.Azure.Cosmos;

namespace Atc.Cosmos
{
Expand Down Expand Up @@ -67,5 +68,10 @@ public class CosmosOptions
/// When <see cref="TokenCredential"/> is provided the property <see cref="AccountKey"/> is not needed.
/// </remarks>
public TokenCredential? Credential { get; set; }

/// <summary>
/// Gets or sets the TelemetryOptions/>.
/// </summary>
public CosmosClientTelemetryOptions TelemetryOptions { get; set; } = new ();
}
}
44 changes: 20 additions & 24 deletions src/Atc.Cosmos/Internal/CosmosClientProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,19 @@

namespace Atc.Cosmos.Internal
{
public sealed class CosmosClientProvider : IDisposable, ICosmosClientProvider
public sealed class CosmosClientProvider(
IOptions<CosmosClientOptions> cosmosClientOptions,
IJsonCosmosSerializer serializer)
: IDisposable, ICosmosClientProvider
{
private readonly IOptions<CosmosClientOptions> cosmosClientOptions;
private readonly IJsonCosmosSerializer serializer;
private readonly ConcurrentDictionary<CosmosOptions, CosmosClient> cosmosClientCache;
private readonly ConcurrentDictionary<CosmosOptions, CosmosClient> cosmosBulkClientCache;

public CosmosClientProvider(
IOptions<CosmosClientOptions> cosmosClientOptions,
IJsonCosmosSerializer serializer)
{
this.cosmosClientOptions = cosmosClientOptions;
this.serializer = serializer;
cosmosClientCache = new ConcurrentDictionary<CosmosOptions, CosmosClient>();
cosmosBulkClientCache = new ConcurrentDictionary<CosmosOptions, CosmosClient>();
}
private readonly ConcurrentDictionary<CosmosOptions, CosmosClient> cosmosClientCache = new ();
private readonly ConcurrentDictionary<CosmosOptions, CosmosClient> cosmosBulkClientCache = new ();

public CosmosClient GetClient(CosmosOptions options)
=> cosmosClientCache.AddOrUpdate(options, o => CreateClient(o, allowBulk: false), (o, c) => c);
=> cosmosClientCache.AddOrUpdate(options, CreateClient, (_, c) => c);

public CosmosClient GetBulkClient(CosmosOptions options)
=> cosmosBulkClientCache.AddOrUpdate(options, o => CreateClient(o, allowBulk: true), (o, c) => c);
=> cosmosBulkClientCache.AddOrUpdate(options, CreateBulkClient, (_, c) => c);

public void Dispose()
{
Expand All @@ -43,6 +34,10 @@ public void Dispose()
}
}

private CosmosClient CreateBulkClient(CosmosOptions cosmosOptions) => CreateClient(cosmosOptions, true);

private CosmosClient CreateClient(CosmosOptions cosmosOptions) => CreateClient(cosmosOptions, false);

private CosmosClient CreateClient(CosmosOptions cosmosOptions, bool allowBulk)
{
var connectionString =
Expand All @@ -51,15 +46,15 @@ private CosmosClient CreateClient(CosmosOptions cosmosOptions, bool allowBulk)

var options = CreateCosmosClientOptions();
options.AllowBulkExecution = allowBulk;
options.Serializer = cosmosClientOptions.Value.Serializer
?? new CosmosSerializerAdapter(serializer);
options.Serializer = cosmosClientOptions.Value.Serializer ?? new CosmosSerializerAdapter(serializer);
options.CosmosClientTelemetryOptions = cosmosClientOptions.Value.CosmosClientTelemetryOptions;

return cosmosOptions.Credential is not null
? new CosmosClient(
cosmosOptions.AccountEndpoint,
cosmosOptions.Credential,
options)
: new CosmosClient(connectionString, options);
? new CosmosClient(
cosmosOptions.AccountEndpoint,
cosmosOptions.Credential,
options)
: new CosmosClient(connectionString, options);
}

private CosmosClientOptions CreateCosmosClientOptions()
Expand Down Expand Up @@ -97,6 +92,7 @@ private CosmosClientOptions CreateCosmosClientOptions()
result.EnableTcpConnectionEndpointRediscovery = o.EnableTcpConnectionEndpointRediscovery;
result.GatewayModeMaxConnectionLimit = o.GatewayModeMaxConnectionLimit;
result.MaxRetryAttemptsOnRateLimitedRequests = o.MaxRetryAttemptsOnRateLimitedRequests;
result.CosmosClientTelemetryOptions = o.CosmosClientTelemetryOptions;
}

return result;
Expand Down