Microsoft.Azure.Cosmos/src/Fluent/Settings/ContainerBuilder.cs (196 lines of code) (raw):
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace Microsoft.Azure.Cosmos.Fluent
{
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading;
using System.Threading.Tasks;
/// <summary>
/// <see cref="Container"/> fluent definition for creation flows.
/// </summary>
public class ContainerBuilder : ContainerDefinition<ContainerBuilder>
{
private readonly Database database;
private readonly CosmosClientContext clientContext;
private readonly Uri containerUri;
private UniqueKeyPolicy uniqueKeyPolicy;
private ConflictResolutionPolicy conflictResolutionPolicy;
private ChangeFeedPolicy changeFeedPolicy;
private ClientEncryptionPolicy clientEncryptionPolicy;
private VectorEmbeddingPolicy vectorEmbeddingPolicy;
private FullTextPolicy fullTextPolicy;
/// <summary>
/// Creates an instance for unit-testing
/// </summary>
protected ContainerBuilder()
{
}
/// <summary>
/// Creates an instance of ContainerBuilder .
/// </summary>
/// <param name="database"> The Microsoft.Azure.Cosmos.Database object.</param>
/// <param name="name"> Azure Cosmos container name to create. </param>
/// <param name="partitionKeyPath"> The path to the partition key. Example: /partitionKey </param>
public ContainerBuilder(
Database database,
string name,
string partitionKeyPath)
: base(
string.IsNullOrEmpty(name) ? throw new ArgumentNullException(nameof(name)) : name,
string.IsNullOrEmpty(partitionKeyPath) ? throw new ArgumentNullException(nameof(partitionKeyPath)) : partitionKeyPath)
{
this.database = database ?? throw new ArgumentNullException(nameof(database));
this.clientContext = database.Client.ClientContext;
this.containerUri = UriFactory.CreateDocumentCollectionUri(this.database.Id, name);
}
/// <summary>
/// Defines a Unique Key policy for this Azure Cosmos container.
/// </summary>
/// <returns>An instance of <see cref="UniqueKeyDefinition"/>.</returns>
public UniqueKeyDefinition WithUniqueKey()
{
return new UniqueKeyDefinition(
this,
(uniqueKey) => this.AddUniqueKey(uniqueKey));
}
/// <summary>
/// Defined the conflict resolution for Azure Cosmos container
/// </summary>
/// <returns>An instance of <see cref="ConflictResolutionDefinition"/>.</returns>
public ConflictResolutionDefinition WithConflictResolution()
{
return new ConflictResolutionDefinition(
this,
(conflictPolicy) => this.AddConflictResolution(conflictPolicy));
}
/// <summary>
/// Defined the change feed policy for this Azure Cosmos container
/// </summary>
/// <param name="retention"> Indicates for how long operation logs have to be retained. <see cref="ChangeFeedPolicy.FullFidelityRetention"/>.</param>
/// <returns>An instance of <see cref="ChangeFeedPolicyDefinition"/>.</returns>
#if PREVIEW
public
#else
internal
#endif
ChangeFeedPolicyDefinition WithChangeFeedPolicy(TimeSpan retention)
{
return new ChangeFeedPolicyDefinition(
this,
retention,
(changeFeedPolicy) => this.AddChangeFeedPolicy(changeFeedPolicy));
}
/// <summary>
/// Defines the <see cref="ClientEncryptionPolicy"/> for Azure Cosmos container.
/// The <see cref="ClientEncryptionPolicy.PolicyFormatVersion"/> will be set to 1.
/// Note: If you need to include partition key or id field paths as part of <see cref="ClientEncryptionPolicy"/>, please set <see cref="ClientEncryptionPolicy.PolicyFormatVersion"/> to 2.
/// </summary>
/// <returns>An instance of <see cref="ClientEncryptionPolicyDefinition"/>.</returns>
public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy()
{
return new ClientEncryptionPolicyDefinition(
this,
(clientEncryptionPolicy) => this.AddClientEncryptionPolicy(clientEncryptionPolicy), 1);
}
/// <summary>
/// Defines the ClientEncryptionPolicy for Azure Cosmos container
/// Note: If you need to include partition key or id field paths as part of <see cref="ClientEncryptionPolicy"/>, please set <see cref="ClientEncryptionPolicy.PolicyFormatVersion"/> to 2.
/// </summary>
/// <param name="policyFormatVersion">Version of the client encryption policy definition. Current supported versions are 1 and 2.</param>
/// <returns>An instance of <see cref="ClientEncryptionPolicyDefinition"/>.</returns>
public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion)
{
return new ClientEncryptionPolicyDefinition(
this,
(clientEncryptionPolicy) => this.AddClientEncryptionPolicy(clientEncryptionPolicy),
policyFormatVersion);
}
/// <summary>
/// Defines the vector embedding policy for this Azure Cosmos container
/// </summary>
/// <param name="embeddings">List of vector embeddings to include in the policy definition.</param>
/// <returns>An instance of <see cref="VectorEmbeddingPolicyDefinition"/>.</returns>
public VectorEmbeddingPolicyDefinition WithVectorEmbeddingPolicy(
Collection<Embedding> embeddings)
{
return new VectorEmbeddingPolicyDefinition(
this,
embeddings,
(embeddingPolicy) => this.AddVectorEmbeddingPolicy(embeddingPolicy));
}
/// <summary>
/// Defines the full text policy for this Azure Cosmos container
/// </summary>
/// <param name="defaultLanguage">A string indicating the default language.</param>
/// <param name="fullTextPaths">List of full text paths to include in the policy definition.</param>
/// <returns>An instance of <see cref="FullTextPolicyDefinition"/>.</returns>
public FullTextPolicyDefinition WithFullTextPolicy(
string defaultLanguage,
Collection<FullTextPath> fullTextPaths)
{
return new FullTextPolicyDefinition(
this,
defaultLanguage,
fullTextPaths,
(fullTextPolicy) => this.AddFullTextSearchPolicy(fullTextPolicy));
}
/// <summary>
/// Creates a container with the current fluent definition.
/// </summary>
/// <param name="throughputProperties">Desired throughput for the container expressed in Request Units per second.</param>
/// <param name="cancellationToken">(Optional) <see cref="CancellationToken"/> representing request cancellation.</param>
/// <returns>An asynchronous Task representing the creation of a <see cref="Container"/> based on the Fluent definition.</returns>
/// <seealso href="https://docs.microsoft.com/azure/cosmos-db/request-units">Request Units</seealso>
public async Task<ContainerResponse> CreateAsync(
ThroughputProperties throughputProperties,
CancellationToken cancellationToken = default)
{
ContainerProperties containerProperties = this.Build();
return await this.database.CreateContainerAsync(
containerProperties: containerProperties,
throughputProperties: throughputProperties,
cancellationToken: cancellationToken);
}
/// <summary>
/// Creates a container if it does not exist with the current fluent definition.
/// </summary>
/// <param name="throughputProperties">Desired throughput for the container expressed in Request Units per second.</param>
/// <param name="cancellationToken">(Optional) <see cref="CancellationToken"/> representing request cancellation.</param>
/// <returns>An asynchronous Task representing the creation of a <see cref="Container"/> based on the Fluent definition.</returns>
/// <seealso href="https://docs.microsoft.com/azure/cosmos-db/request-units">Request Units</seealso>
public async Task<ContainerResponse> CreateIfNotExistsAsync(
ThroughputProperties throughputProperties,
CancellationToken cancellationToken = default)
{
ContainerProperties containerProperties = this.Build();
return await this.database.CreateContainerIfNotExistsAsync(
containerProperties: containerProperties,
throughputProperties: throughputProperties,
cancellationToken: cancellationToken);
}
/// <summary>
/// Creates a container with the current fluent definition.
/// </summary>
/// <param name="throughput">Desired throughput for the container expressed in Request Units per second.</param>
/// <param name="cancellationToken">(Optional) <see cref="CancellationToken"/> representing request cancellation.</param>
/// <returns>An asynchronous Task representing the creation of a <see cref="Container"/> based on the Fluent definition.</returns>
/// <seealso href="https://docs.microsoft.com/azure/cosmos-db/request-units">Request Units</seealso>
public async Task<ContainerResponse> CreateAsync(
int? throughput = null,
CancellationToken cancellationToken = default)
{
ContainerProperties containerProperties = this.Build();
return await this.database.CreateContainerAsync(
containerProperties: containerProperties,
throughput: throughput,
requestOptions: null,
cancellationToken: cancellationToken);
}
/// <summary>
/// Creates a container if it does not exist with the current fluent definition.
/// </summary>
/// <param name="throughput">Desired throughput for the container expressed in Request Units per second.</param>
/// <param name="cancellationToken">(Optional) <see cref="CancellationToken"/> representing request cancellation.</param>
/// <returns>An asynchronous Task representing the creation of a <see cref="Container"/> based on the Fluent definition.</returns>
/// <seealso href="https://docs.microsoft.com/azure/cosmos-db/request-units">Request Units</seealso>
public async Task<ContainerResponse> CreateIfNotExistsAsync(
int? throughput = null,
CancellationToken cancellationToken = default)
{
ContainerProperties containerProperties = this.Build();
return await this.database.CreateContainerIfNotExistsAsync(
containerProperties: containerProperties,
throughput: throughput,
requestOptions: null,
cancellationToken: cancellationToken);
}
/// <summary>
/// Applies the current Fluent definition and creates a container configuration.
/// </summary>
/// <returns>Builds the current Fluent configuration into an instance of <see cref="ContainerProperties"/>.</returns>
public new ContainerProperties Build()
{
ContainerProperties containerProperties = base.Build();
if (this.uniqueKeyPolicy != null)
{
containerProperties.UniqueKeyPolicy = this.uniqueKeyPolicy;
}
if (this.conflictResolutionPolicy != null)
{
containerProperties.ConflictResolutionPolicy = this.conflictResolutionPolicy;
}
if (this.changeFeedPolicy != null)
{
containerProperties.ChangeFeedPolicy = this.changeFeedPolicy;
}
if (this.clientEncryptionPolicy != null)
{
containerProperties.ClientEncryptionPolicy = this.clientEncryptionPolicy;
}
if (this.vectorEmbeddingPolicy != null)
{
containerProperties.VectorEmbeddingPolicy = this.vectorEmbeddingPolicy;
}
if (this.fullTextPolicy != null)
{
containerProperties.FullTextPolicy = this.fullTextPolicy;
}
return containerProperties;
}
private void AddUniqueKey(UniqueKey uniqueKey)
{
if (this.uniqueKeyPolicy == null)
{
this.uniqueKeyPolicy = new UniqueKeyPolicy();
}
this.uniqueKeyPolicy.UniqueKeys.Add(uniqueKey);
}
private void AddConflictResolution(ConflictResolutionPolicy conflictResolutionPolicy)
{
if (conflictResolutionPolicy.Mode == ConflictResolutionMode.Custom
&& !string.IsNullOrEmpty(conflictResolutionPolicy.ResolutionProcedure))
{
this.clientContext.ValidateResource(conflictResolutionPolicy.ResolutionProcedure);
conflictResolutionPolicy.ResolutionProcedure = UriFactory.CreateStoredProcedureUri(this.containerUri.ToString(), conflictResolutionPolicy.ResolutionProcedure).ToString();
}
this.conflictResolutionPolicy = conflictResolutionPolicy;
}
private void AddChangeFeedPolicy(ChangeFeedPolicy changeFeedPolicy)
{
this.changeFeedPolicy = changeFeedPolicy;
}
private void AddClientEncryptionPolicy(ClientEncryptionPolicy clientEncryptionPolicy)
{
this.clientEncryptionPolicy = clientEncryptionPolicy;
}
private void AddVectorEmbeddingPolicy(VectorEmbeddingPolicy embeddingPolicy)
{
this.vectorEmbeddingPolicy = embeddingPolicy;
}
private void AddFullTextSearchPolicy(FullTextPolicy fullTextPolicy)
{
this.fullTextPolicy = fullTextPolicy;
}
}
}