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; } }
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); }