private static async Task CreateLeaseCollectionIfNotExistsAsync(ICosmosDBService leaseCosmosDBService, string databaseName, string collectionName, int throughput) { try { await CosmosDBUtility.CreateDatabaseAndCollectionIfNotExistAsync(leaseCosmosDBService, databaseName, collectionName, null, throughput); } catch (DocumentClientException ex) when(ex.Message.Contains(SharedThroughputRequirementException)) { await CosmosDBUtility.CreateDatabaseAndCollectionIfNotExistAsync(leaseCosmosDBService, databaseName, collectionName, LeaseCollectionRequiredPartitionKey, throughput); } }
public async Task AddAsync(T item, CancellationToken cancellationToken = default(CancellationToken)) { bool create = false; try { await UpsertDocument(_docDBContext, item); } catch (Exception ex) { if (CosmosDBUtility.TryGetDocumentClientException(ex, out DocumentClientException de) && de.StatusCode == HttpStatusCode.NotFound) { if (_docDBContext.ResolvedAttribute.CreateIfNotExists) { create = true; } else { // Throw a custom error so that it's easier to decipher. string message = $"The collection '{_docDBContext.ResolvedAttribute.CollectionName}' (in database '{_docDBContext.ResolvedAttribute.DatabaseName}') does not exist. To automatically create the collection, set '{nameof(CosmosDBAttribute.CreateIfNotExists)}' to 'true'."; throw new InvalidOperationException(message, ex); } } else { throw; } } if (create) { await CosmosDBUtility.CreateDatabaseAndCollectionIfNotExistAsync(_docDBContext); await UpsertDocument(_docDBContext, item); } }
public async Task <ITriggerBinding> TryCreateAsync(TriggerBindingProviderContext context) { // Tries to parse the context parameters and see if it belongs to this [CosmosDBTrigger] binder if (context == null) { throw new ArgumentNullException("context"); } ParameterInfo parameter = context.Parameter; CosmosDBTriggerAttribute attribute = parameter.GetCustomAttribute <CosmosDBTriggerAttribute>(inherit: false); if (attribute == null) { return(null); } _monitorConnectionString = _nameResolver.Resolve(CosmosDBConfiguration.AzureWebJobsCosmosDBConnectionStringName); _leasesConnectionString = _nameResolver.Resolve(CosmosDBConfiguration.AzureWebJobsCosmosDBConnectionStringName); DocumentCollectionInfo documentCollectionLocation; DocumentCollectionInfo leaseCollectionLocation; ChangeFeedHostOptions leaseHostOptions = ResolveLeaseOptions(attribute); int?maxItemCount = null; if (attribute.MaxItemsPerInvocation > 0) { maxItemCount = attribute.MaxItemsPerInvocation; } try { string triggerConnectionString = ResolveAttributeConnectionString(attribute); CosmosDBConnectionString triggerConnection = new CosmosDBConnectionString(triggerConnectionString); if (triggerConnection.ServiceEndpoint == null) { throw new InvalidOperationException("The connection string for the monitored collection is in an invalid format, please use AccountEndpoint=XXXXXX;AccountKey=XXXXXX;."); } string leasesConnectionString = ResolveAttributeLeasesConnectionString(attribute, triggerConnectionString); CosmosDBConnectionString leasesConnection = new CosmosDBConnectionString(leasesConnectionString); if (leasesConnection.ServiceEndpoint == null) { throw new InvalidOperationException("The connection string for the leases collection is in an invalid format, please use AccountEndpoint=XXXXXX;AccountKey=XXXXXX;."); } documentCollectionLocation = new DocumentCollectionInfo { Uri = triggerConnection.ServiceEndpoint, MasterKey = triggerConnection.AuthKey, DatabaseName = ResolveAttributeValue(attribute.DatabaseName), CollectionName = ResolveAttributeValue(attribute.CollectionName) }; documentCollectionLocation.ConnectionPolicy.UserAgentSuffix = CosmosDBTriggerUserAgentSuffix; leaseCollectionLocation = new DocumentCollectionInfo { Uri = leasesConnection.ServiceEndpoint, MasterKey = leasesConnection.AuthKey, DatabaseName = ResolveAttributeValue(attribute.LeaseDatabaseName), CollectionName = ResolveAttributeValue(attribute.LeaseCollectionName) }; leaseCollectionLocation.ConnectionPolicy.UserAgentSuffix = CosmosDBTriggerUserAgentSuffix; if (string.IsNullOrEmpty(documentCollectionLocation.DatabaseName) || string.IsNullOrEmpty(documentCollectionLocation.CollectionName) || string.IsNullOrEmpty(leaseCollectionLocation.DatabaseName) || string.IsNullOrEmpty(leaseCollectionLocation.CollectionName)) { throw new InvalidOperationException("Cannot establish database and collection values. If you are using environment and configuration values, please ensure these are correctly set."); } if (documentCollectionLocation.Uri.Equals(leaseCollectionLocation.Uri) && documentCollectionLocation.DatabaseName.Equals(leaseCollectionLocation.DatabaseName) && documentCollectionLocation.CollectionName.Equals(leaseCollectionLocation.CollectionName)) { throw new InvalidOperationException("The monitored collection cannot be the same as the collection storing the leases."); } if (attribute.CreateLeaseCollectionIfNotExists) { // Not disposing this because it might be reused on other Trigger since Triggers could share lease collection ICosmosDBService service = _config.GetService(leasesConnectionString); await CosmosDBUtility.CreateDatabaseAndCollectionIfNotExistAsync(service, leaseCollectionLocation.DatabaseName, leaseCollectionLocation.CollectionName, null, attribute.LeasesCollectionThroughput); } } catch (Exception ex) { throw new InvalidOperationException(string.Format("Cannot create Collection Information for {0} in database {1} with lease {2} in database {3} : {4}", attribute.CollectionName, attribute.DatabaseName, attribute.LeaseCollectionName, attribute.LeaseDatabaseName, ex.Message), ex); } return(new CosmosDBTriggerBinding(parameter, documentCollectionLocation, leaseCollectionLocation, leaseHostOptions, maxItemCount)); }