예제 #1
0
        public async Task <UpsertOutcome> UpsertAsync(
            ResourceWrapper resource,
            WeakETag weakETag,
            bool allowCreate,
            bool keepHistory,
            CancellationToken cancellationToken)
        {
            EnsureArg.IsNotNull(resource, nameof(resource));

            var cosmosWrapper = new FhirCosmosResourceWrapper(resource);

            try
            {
                _logger.LogDebug($"Upserting {resource.ResourceTypeName}/{resource.ResourceId}, ETag: \"{weakETag?.VersionId}\", AllowCreate: {allowCreate}, KeepHistory: {keepHistory}");

                UpsertWithHistoryModel response = await _retryExceptionPolicyFactory.GetRetryPolicy().ExecuteAsync(
                    async ct => await _upsertWithHistoryProc.Execute(
                        _containerScope.Value.Scripts,
                        cosmosWrapper,
                        weakETag?.VersionId,
                        allowCreate,
                        keepHistory,
                        ct),
                    cancellationToken);

                return(new UpsertOutcome(response.Wrapper, response.OutcomeType));
            }
            catch (CosmosException exception)
            {
                switch (exception.GetSubStatusCode())
                {
                case HttpStatusCode.PreconditionFailed:
                    throw new PreconditionFailedException(string.Format(Core.Resources.ResourceVersionConflict, weakETag?.VersionId));

                case HttpStatusCode.NotFound:
                    if (cosmosWrapper.IsDeleted)
                    {
                        return(null);
                    }

                    if (weakETag != null)
                    {
                        throw new ResourceNotFoundException(string.Format(Core.Resources.ResourceNotFoundByIdAndVersion, resource.ResourceTypeName, resource.ResourceId, weakETag.VersionId));
                    }
                    else if (!allowCreate)
                    {
                        throw new MethodNotAllowedException(Core.Resources.ResourceCreationNotAllowed);
                    }

                    break;

                case HttpStatusCode.ServiceUnavailable:
                    throw new ServiceUnavailableException();
                }

                _logger.LogError(exception, "Unhandled Document Client Exception");

                throw;
            }
        }
예제 #2
0
        public async Task <Container> InitializeCollection(CosmosClient client)
        {
            Database  database        = client.GetDatabase(_cosmosDataStoreConfiguration.DatabaseId);
            Container containerClient = database.GetContainer(_cosmosCollectionConfiguration.CollectionId);

            _logger.LogInformation("Finding Container: {collectionId}", _cosmosCollectionConfiguration.CollectionId);

            AsyncPolicy retryPolicy = _retryExceptionPolicyFactory.GetRetryPolicy();

            var existingContainer = await retryPolicy.ExecuteAsync(async() => await database.TryGetContainerAsync(_cosmosCollectionConfiguration.CollectionId));

            _logger.LogInformation("Creating Cosmos Container if not exits: {collectionId}", _cosmosCollectionConfiguration.CollectionId);

            ContainerResponse containerResponse = await retryPolicy.ExecuteAsync(async() =>
                                                                                 await database.CreateContainerIfNotExistsAsync(
                                                                                     _cosmosCollectionConfiguration.CollectionId,
                                                                                     $"/{KnownDocumentProperties.PartitionKey}",
                                                                                     _cosmosCollectionConfiguration.InitialCollectionThroughput));

            if (containerResponse.StatusCode == HttpStatusCode.Created || containerResponse.Resource.DefaultTimeToLive != -1)
            {
                if (_cosmosCollectionConfiguration.InitialCollectionThroughput.HasValue)
                {
                    var throughputProperties = ThroughputProperties.CreateManualThroughput(_cosmosCollectionConfiguration.InitialCollectionThroughput.Value);
                    await retryPolicy.ExecuteAsync(async() => await containerClient.ReplaceThroughputAsync(throughputProperties));
                }

                containerResponse.Resource.DefaultTimeToLive = -1;
                existingContainer = await retryPolicy.ExecuteAsync(async() => await containerClient.ReplaceContainerAsync(containerResponse));
            }

            await retryPolicy.ExecuteAsync(async() =>
            {
                try
                {
                    await _clientTestProvider.PerformTest(existingContainer, _cosmosDataStoreConfiguration, _cosmosCollectionConfiguration);
                }
                catch (CosmosException e) when(e.StatusCode == HttpStatusCode.TooManyRequests)
                {
                    // This is the very first interaction with the collection, and we might get this exception
                    // when it calls GetCachedContainerPropertiesAsync, which does not use our request handler.
                    throw new RequestRateExceededException(e.RetryAfter);
                }
            });

            await _upgradeManager.SetupContainerAsync(containerClient);

            return(existingContainer);
        }