public DefaultCosmosContainerProvider(
            ICosmosClientProvider cosmosClientProvider,
            ICosmosPartitionKeyPathProvider cosmosPartitionKeyPathProvider,
            IOptions <RepositoryOptions> options,
            ILogger <DefaultCosmosContainerProvider <TItem> > logger)
        {
            _cosmosClientProvider = cosmosClientProvider ?? throw new ArgumentNullException(
                                              nameof(cosmosClientProvider), Resources.CosmosClientProviderIsRequired);

            _cosmosPartitionKeyPathProvider = cosmosPartitionKeyPathProvider ?? throw new ArgumentNullException(
                                                        nameof(cosmosPartitionKeyPathProvider), Resources.CosmosPartitionKeyNameProviderIsRequired);

            _options = options?.Value ?? throw new ArgumentNullException(
                                 nameof(options), Resources.RepositoryOptionsAreRequired);

            _ = _options.CosmosConnectionString ?? throw new ArgumentNullException(
                          nameof(options), Resources.TheBlankIsRequired.Format(nameof(_options.CosmosConnectionString)));

            if (_options.ContainerPerItemType is false)
            {
                _ = _options.DatabaseId ?? throw new ArgumentNullException(
                              nameof(options),
                              Resources.TheBlankIsRequiredWhenContainerPerItemTypeIsFalse.Format(nameof(_options.DatabaseId)));

                _ = _options.ContainerId ?? throw new ArgumentNullException(
                              nameof(options),
                              Resources.TheBlankIsRequiredWhenContainerPerItemTypeIsFalse.Format(nameof(_options.ContainerId)));
            }

            _logger = logger ?? throw new ArgumentNullException(
                                nameof(logger), Resources.TheBlankIsRequired.Format(nameof(logger)));

            _lazyContainer = new Lazy <Task <Container> >(
                async() =>
            {
                try
                {
                    Database database =
                        await _cosmosClientProvider.UseClientAsync(
                            client => client.CreateDatabaseIfNotExistsAsync(_options.DatabaseId)).ConfigureAwait(false);

                    ContainerProperties containerProperties = new ContainerProperties
                    {
                        Id = _options.ContainerPerItemType ? typeof(TItem).Name : _options.ContainerId,
                        PartitionKeyPath = _cosmosPartitionKeyPathProvider.GetPartitionKeyPath <TItem>()
                    };

                    Container container =
                        await database.CreateContainerIfNotExistsAsync(containerProperties).ConfigureAwait(false);

                    return(container);
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex.Message, ex);

                    throw;
                }
            });
        }
 public DefaultLeaseContainerProvider(
     ICosmosClientProvider cosmosClientProvider,
     IOptionsMonitor <RepositoryOptions> optionsMonitor)
 {
     _repositoryOptions    = optionsMonitor.CurrentValue;
     _cosmosClientProvider = cosmosClientProvider;
     _lazyContainer        = new Lazy <Task <Container> >(BuildLeaseContainer);
 }
Example #3
0
    public async Task Startup_ContainerWithUniqueKeyPolicy_CreatesContainerCorrectly()
    {
        try
        {
            //Arrange
            await GetClient().UseClientAsync(PruneDatabases);

            ICosmosClientProvider             clientProvider          = _provider.GetRequiredService <ICosmosClientProvider>();
            IRepository <UniqueKeyPolicyItem> uniqueKeyItemRepository = _provider.GetRequiredService <IRepository <UniqueKeyPolicyItem> >();

            //Act
            Database database = await clientProvider.UseClientAsync(x => x.CreateDatabaseIfNotExistsAsync(BuildDatabaseName(UniquePolicyDb)));

            UniqueKeyPolicyItem bobInYorkshire  = new("bob", 22, "Yorkshire", "Red");
            UniqueKeyPolicyItem bobInDerbyshire = new("bob", 22, "Derbyshire", "Yellow");
            UniqueKeyPolicyItem cannotHaveAnotherBobInYorkshire      = new("bob", 22, "Derbyshire", "Green");
            UniqueKeyPolicyItem jeffFromYorkshireCannotLikeRedAsWell = new("jeff", 40, "Yorkshire", "Red");

            await uniqueKeyItemRepository.CreateAsync(bobInYorkshire);

            await uniqueKeyItemRepository.CreateAsync(bobInDerbyshire);

            //Assert
            ContainerProperties?properties = await GetContainerProperties(database, UniqueKeyPolicyContainerName);

            properties.Should().NotBeNull();
            properties !.UniqueKeyPolicy.UniqueKeys.Count.Should().Be(2);
            properties.UniqueKeyPolicy.UniqueKeys
            .Count(x =>
                   x.Paths.Contains("/firstName") &&
                   x.Paths.Contains("/age") &&
                   x.Paths.Count is 2)
            .Should()
            .Be(1);

            properties.UniqueKeyPolicy.UniqueKeys
            .Count(x =>
                   x.Paths.Contains("/favouriteColor") &&
                   x.Paths.Count is 1)
            .Should()
            .Be(1);

            CosmosException ex = await Assert.ThrowsAsync <CosmosException>(() =>
                                                                            uniqueKeyItemRepository.CreateAsync(cannotHaveAnotherBobInYorkshire).AsTask());

            ex.StatusCode.Should().Be(HttpStatusCode.Conflict);

            ex = await Assert.ThrowsAsync <CosmosException>(() =>
                                                            uniqueKeyItemRepository.CreateAsync(jeffFromYorkshireCannotLikeRedAsWell).AsTask());

            ex.StatusCode.Should().Be(HttpStatusCode.Conflict);
        }
        finally
        {
            await GetClient().UseClientAsync(PruneDatabases);
        }
    }
Example #4
0
    public async Task CosmosEventSourcingTest()
    {
        ICosmosClientProvider clientProvider =
            _provider.GetRequiredService <ICosmosClientProvider>();

        await clientProvider
        .UseClientAsync(x =>
                        x.DeleteDatabaseIfExistsAsync(DatabaseName, _logger));

        await _changeFeedService.StartAsync(default);
Example #5
0
 public CosmosContext(
     ICosmosClientProvider clientProvider,
     ICosmosDatabaseConfiguration databaseConfiguration,
     ICosmosContainerConfiguration containerConfiguration)
 {
     _clientProvider         = clientProvider;
     _databaseConfiguration  = databaseConfiguration;
     _containerConfiguration = containerConfiguration;
     _container = GetContainer();
     ReadContainer();
 }
Example #6
0
        public DefaultCosmosContainerProvider(
            ICosmosClientProvider cosmosClientProvider,
            ICosmosPartitionKeyPathProvider cosmosPartitionKeyPathProvider,
            ICosmosContainerNameProvider cosmosContainerNameProvider,
            IOptions <RepositoryOptions> options,
            ILogger <DefaultCosmosContainerProvider <TItem> > logger)
        {
            _cosmosClientProvider = cosmosClientProvider
                                    ?? throw new ArgumentNullException(
                                              nameof(cosmosClientProvider), "Cosmos client provider is required.");

            _cosmosPartitionKeyPathProvider = cosmosPartitionKeyPathProvider
                                              ?? throw new ArgumentNullException(
                                                        nameof(cosmosPartitionKeyPathProvider), "Cosmos partition key name provider is required.");

            _cosmosContainerNameProvider = cosmosContainerNameProvider
                                           ?? throw new ArgumentNullException(
                                                     nameof(cosmosContainerNameProvider), "Cosmos container name provider is required.");

            _options = options?.Value
                       ?? throw new ArgumentNullException(
                                 nameof(options), "Repository options are required.");

            _logger = logger
                      ?? throw new ArgumentNullException($"The {nameof(logger)} is required.");

            if (_options.CosmosConnectionString is null)
            {
                throw new ArgumentNullException($"The {nameof(_options.CosmosConnectionString)} is required.");
            }
            if (_options.ContainerPerItemType is false)
            {
                if (_options.DatabaseId is null)
                {
                    throw new ArgumentNullException(
                              $"The {nameof(_options.DatabaseId)} is required when container per item type is false.");
                }
                if (_options.ContainerId is null)
                {
                    throw new ArgumentNullException(
                              $"The {nameof(_options.ContainerId)} is required when container per item type is false.");
                }
            }

            _lazyContainer = new Lazy <Task <Container> >(async() => await GetContainerValueFactoryAsync());
            _cosmosContainerNameProvider = cosmosContainerNameProvider;
        }
        public DefaultCosmosContainerProvider(
            ICosmosClientProvider cosmosClientProvider,
            ICosmosPartitionKeyPathProvider cosmosPartitionKeyPathProvider,
            IOptions <RepositoryOptions> options,
            ILogger <DefaultCosmosContainerProvider <TItem> > logger)
        {
            _cosmosClientProvider = cosmosClientProvider
                                    ?? throw new ArgumentNullException(
                                              nameof(cosmosClientProvider), "Cosmos client provider is required.");

            _cosmosPartitionKeyPathProvider = cosmosPartitionKeyPathProvider
                                              ?? throw new ArgumentNullException(
                                                        nameof(cosmosPartitionKeyPathProvider), "Cosmos partition key name provider is required.");

            _options = options?.Value
                       ?? throw new ArgumentNullException(
                                 nameof(options), "Repository options are required.");

            if (_options.CosmosConnectionString is null)
            {
                throw new ArgumentNullException($"The {nameof(_options.CosmosConnectionString)} is required.");
            }
            if (_options.ContainerPerItemType is false)
            {
                if (_options.DatabaseId is null)
                {
                    throw new ArgumentNullException(
                              $"The {nameof(_options.DatabaseId)} is required when container per item type is false.");
                }
                if (_options.ContainerId is null)
                {
                    throw new ArgumentNullException(
                              $"The {nameof(_options.ContainerId)} is required when container per item type is false.");
                }
            }
            if (logger is null)
            {
                throw new ArgumentNullException($"The {nameof(logger)} is required.");
            }

            _logger        = logger;
            _lazyContainer = new Lazy <Task <Container> >(async() =>
            {
                try
                {
                    Database database =
                        await _cosmosClientProvider.UseClientAsync(
                            client => client.CreateDatabaseIfNotExistsAsync(_options.DatabaseId)).ConfigureAwait(false);

                    ContainerProperties containerProperties = new ContainerProperties
                    {
                        Id = _options.ContainerPerItemType ? typeof(TItem).Name : _options.ContainerId,
                        PartitionKeyPath = _cosmosPartitionKeyPathProvider.GetPartitionKeyPath <TItem>()
                    };

                    Container container =
                        await database.CreateContainerIfNotExistsAsync(
                            containerProperties).ConfigureAwait(false);

                    return(container);
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex.Message, ex);

                    throw;
                }
            });
        }