public void ParsePreferredLocations_WithEntries()
        {
            // Arrange
            string preferredLocationsWithEntries = "East US, North Europe,";

            // Act
            var parsedLocations = CosmosDBUtility.ParsePreferredLocations(preferredLocationsWithEntries);

            // Assert
            Assert.Equal(2, parsedLocations.Count());
        }
        public void ParsePreferredLocations_WhenEmpty()
        {
            // Arrange
            string preferredLocationsEmpty = string.Empty;
            string preferredLocationsNull  = null;

            // Act
            var parsedLocationsEmpty = CosmosDBUtility.ParsePreferredLocations(preferredLocationsEmpty);
            var parsedLocationsNull  = CosmosDBUtility.ParsePreferredLocations(preferredLocationsNull);

            // Assert
            Assert.Empty(parsedLocationsEmpty);
            Assert.Empty(parsedLocationsNull);
        }
        public async Task <ITriggerBinding> TryCreateAsync(TriggerBindingProviderContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var parameter = context.Parameter;
            var attribute = parameter.GetCustomAttribute <CosmosStoreTriggerAttribute>(inherit: false);

            if (attribute == null)
            {
                return(null);
            }

            var desiredConnectionMode     = _bindingOptions.ConnectionMode;
            var desiredConnectionProtocol = _bindingOptions.Protocol;

            DocumentCollectionInfo documentCollectionLocation;
            DocumentCollectionInfo leaseCollectionLocation;
            var processorOptions = BuildProcessorOptions(attribute);

            processorOptions.StartFromBeginning = attribute.StartFromBeginning;
            if (attribute.MaxItemsPerInvocation > 0)
            {
                processorOptions.MaxItemCount = attribute.MaxItemsPerInvocation;
            }

            IDocumentClient monitoredDocumentClient;
            IDocumentClient leaseDocumentClient;

            try
            {
                var monitoredConnectionString = ResolveConnectionString(attribute.ConnectionStringSetting, nameof(CosmosStoreTriggerAttribute.ConnectionStringSetting));
                if (string.IsNullOrEmpty(monitoredConnectionString))
                {
                    throw new InvalidOperationException("The connection string for the monitored collection is in an invalid format, please use AccountEndpoint=XXXXXX;AccountKey=XXXXXX;.");
                }

                var monitoredCosmosDbConnectionString = new CosmosDBConnectionString(monitoredConnectionString);

                var leasesConnectionString = ResolveAttributeLeasesConnectionString(attribute);
                var 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;.");
                }

                var monitoredCollectionName = GetMonitoredCollectionName(attribute);

                documentCollectionLocation = new DocumentCollectionInfo
                {
                    Uri              = monitoredCosmosDbConnectionString.ServiceEndpoint,
                    MasterKey        = monitoredCosmosDbConnectionString.AuthKey,
                    DatabaseName     = ResolveAttributeValue(attribute.DatabaseName),
                    CollectionName   = monitoredCollectionName,
                    ConnectionPolicy = { UserAgentSuffix = CosmosStoreTriggerUserAgentSuffix }
                };

                if (desiredConnectionMode.HasValue)
                {
                    documentCollectionLocation.ConnectionPolicy.ConnectionMode = desiredConnectionMode.Value;
                }

                if (desiredConnectionProtocol.HasValue)
                {
                    documentCollectionLocation.ConnectionPolicy.ConnectionProtocol = desiredConnectionProtocol.Value;
                }

                leaseCollectionLocation = new DocumentCollectionInfo
                {
                    Uri            = leasesConnection.ServiceEndpoint,
                    MasterKey      = leasesConnection.AuthKey,
                    DatabaseName   = ResolveAttributeValue(attribute.LeaseDatabaseName),
                    CollectionName = ResolveAttributeValue(attribute.LeaseCollectionName)
                };

                leaseCollectionLocation.ConnectionPolicy.UserAgentSuffix = CosmosStoreTriggerUserAgentSuffix;

                if (desiredConnectionMode.HasValue)
                {
                    leaseCollectionLocation.ConnectionPolicy.ConnectionMode = desiredConnectionMode.Value;
                }

                if (desiredConnectionProtocol.HasValue)
                {
                    leaseCollectionLocation.ConnectionPolicy.ConnectionProtocol = desiredConnectionProtocol.Value;
                }

                var resolvedPreferredLocations = ResolveAttributeValue(attribute.PreferredLocations);
                foreach (var location in CosmosDBUtility.ParsePreferredLocations(resolvedPreferredLocations))
                {
                    documentCollectionLocation.ConnectionPolicy.PreferredLocations.Add(location);
                    leaseCollectionLocation.ConnectionPolicy.PreferredLocations.Add(location);
                }

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

                var cosmosStore = new CosmosStore <T>(new CosmosStoreSettings(documentCollectionLocation.DatabaseName,
                                                                              documentCollectionLocation.Uri, documentCollectionLocation.MasterKey),
                                                      attribute.CollectionName);

                monitoredDocumentClient = cosmosStore.CosmonautClient.DocumentClient;

                leaseDocumentClient = new DocumentClient(leasesConnection.ServiceEndpoint, leasesConnection.AuthKey, leaseCollectionLocation.ConnectionPolicy);

                if (attribute.CreateLeaseCollectionIfNotExists)
                {
                    await CreateLeaseCollectionIfNotExistsAsync(leaseDocumentClient, leaseCollectionLocation.DatabaseName, leaseCollectionLocation.CollectionName, attribute.LeasesCollectionThroughput);
                }
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException(
                          $"Cannot create Collection Information for {attribute.CollectionName} in database {attribute.DatabaseName} with lease {attribute.LeaseCollectionName} in database {attribute.LeaseDatabaseName} : {ex.Message}", ex);
            }

            return(new CosmosStoreTriggerBinding <T>(parameter, documentCollectionLocation, leaseCollectionLocation, monitoredDocumentClient, leaseDocumentClient, processorOptions, _logger));
        }