コード例 #1
0
        private ChangeFeedProcessorOptions BuildProcessorOptions(CosmosDBTriggerAttribute attribute)
        {
            ChangeFeedHostOptions leasesOptions = _options.LeaseOptions;

            ChangeFeedProcessorOptions processorOptions = new ChangeFeedProcessorOptions
            {
                LeasePrefix             = ResolveAttributeValue(attribute.LeaseCollectionPrefix) ?? leasesOptions.LeasePrefix,
                FeedPollDelay           = ResolveTimeSpanFromMilliseconds(nameof(CosmosDBTriggerAttribute.FeedPollDelay), leasesOptions.FeedPollDelay, attribute.FeedPollDelay),
                LeaseAcquireInterval    = ResolveTimeSpanFromMilliseconds(nameof(CosmosDBTriggerAttribute.LeaseAcquireInterval), leasesOptions.LeaseAcquireInterval, attribute.LeaseAcquireInterval),
                LeaseExpirationInterval = ResolveTimeSpanFromMilliseconds(nameof(CosmosDBTriggerAttribute.LeaseExpirationInterval), leasesOptions.LeaseExpirationInterval, attribute.LeaseExpirationInterval),
                LeaseRenewInterval      = ResolveTimeSpanFromMilliseconds(nameof(CosmosDBTriggerAttribute.LeaseRenewInterval), leasesOptions.LeaseRenewInterval, attribute.LeaseRenewInterval),
                CheckpointFrequency     = leasesOptions.CheckpointFrequency ?? new CheckpointFrequency()
            };

            if (attribute.CheckpointInterval > 0)
            {
                processorOptions.CheckpointFrequency.TimeInterval = TimeSpan.FromMilliseconds(attribute.CheckpointInterval);
            }

            if (attribute.CheckpointDocumentCount > 0)
            {
                processorOptions.CheckpointFrequency.ProcessedDocumentCount = attribute.CheckpointDocumentCount;
            }

            return(processorOptions);
        }
コード例 #2
0
        public static async Task StartChangeFeedHost()
        {
            var config = ServiceLocator.GetService <IConfiguration>();

            string hostName = config.MonitoredCollectionName + "_monitor_" + Guid.NewGuid().ToString();
            DocumentCollectionInfo documentCollectionLocation = new DocumentCollectionInfo
            {
                Uri            = config.DatabaseAccountUri,
                MasterKey      = config.DatabaseAccountKey,
                DatabaseName   = config.MonitoredDatabaseName,
                CollectionName = config.MonitoredCollectionName
            };
            DocumentCollectionInfo leaseCollectionLocation = new DocumentCollectionInfo
            {
                Uri            = config.DatabaseAccountUri,
                MasterKey      = config.DatabaseAccountKey,
                DatabaseName   = config.ChangeTrackingDatabaseName,
                CollectionName = config.ChangeTrackingLeaseCollectionName
            };

            Console.WriteLine("Main program: Creating ChangeFeedEventHost...");

            ChangeFeedOptions     feedOptions     = new ChangeFeedOptions();
            ChangeFeedHostOptions feedHostOptions = new ChangeFeedHostOptions();



            ChangeFeedEventHost host = new ChangeFeedEventHost(hostName, documentCollectionLocation, leaseCollectionLocation, feedOptions, feedHostOptions);
            await host.RegisterObserverAsync <DocumentFeedObserver>();

            Console.WriteLine("Main program: press Enter to stop...");
            Console.ReadLine();
            await host.UnregisterObserversAsync();
        }
コード例 #3
0
        public async Task StartAsync_Retries()
        {
            var mockExecutor = new Mock <ITriggeredFunctionExecutor>();
            var collInfo     = new DocumentCollectionInfo {
                Uri = new Uri("http://fakeaccount"), MasterKey = "c29tZV9rZXk=", DatabaseName = "FakeDb", CollectionName = "FakeColl"
            };
            var leaseInfo = new DocumentCollectionInfo {
                Uri = new Uri("http://fakeaccount"), MasterKey = "c29tZV9rZXk=", DatabaseName = "FakeDb", CollectionName = "leases"
            };
            var hostOptions = new ChangeFeedHostOptions();
            var feedOptions = new ChangeFeedOptions();

            var listener = new MockListener(mockExecutor.Object, collInfo, leaseInfo, hostOptions, feedOptions, NullLogger.Instance);

            // Ensure that we can call StartAsync() multiple times to retry if there is an error.
            for (int i = 0; i < 3; i++)
            {
                var ex = await Assert.ThrowsAnyAsync <InvalidOperationException>(() => listener.StartAsync(CancellationToken.None));

                Assert.Equal("Failed to register!", ex.Message);
            }

            // This should succeed
            await listener.StartAsync(CancellationToken.None);
        }
 public CosmosDBTriggerBinding(ParameterInfo parameter, DocumentCollectionInfo documentCollectionLocation, DocumentCollectionInfo leaseCollectionLocation, ChangeFeedHostOptions leaseHostOptions)
 {
     _documentCollectionLocation = documentCollectionLocation;
     _leaseCollectionLocation    = leaseCollectionLocation;
     _leaseHostOptions           = leaseHostOptions;
     _parameter = parameter;
 }
コード例 #5
0
        /// <summary>
        /// Registers change feed observer to update changes read on change feed to destination
        /// collection. Deregisters change feed observer and closes process when enter key is pressed
        /// </summary>
        /// <returns>A Task to allow asynchronous execution</returns>
        public async Task RunChangeFeedHostAsync()
        {
            string hostName = Guid.NewGuid().ToString();

            // monitored collection info
            DocumentCollectionInfo documentCollectionLocation = new DocumentCollectionInfo
            {
                Uri            = new Uri(this.monitoredUri),
                MasterKey      = this.monitoredSecretKey,
                DatabaseName   = this.monitoredDbName,
                CollectionName = this.monitoredCollectionName
            };

            // lease collection info
            DocumentCollectionInfo leaseCollectionLocation = new DocumentCollectionInfo
            {
                Uri            = new Uri(this.leaseUri),
                MasterKey      = this.leaseSecretKey,
                DatabaseName   = this.leaseDbName,
                CollectionName = this.leaseCollectionName
            };

            // destination collection info
            DocumentCollectionInfo destCollInfo = new DocumentCollectionInfo
            {
                Uri            = new Uri(this.destUri),
                MasterKey      = this.destSecretKey,
                DatabaseName   = this.destDbName,
                CollectionName = this.destCollectionName
            };

            // Customizable change feed option and host options
            ChangeFeedOptions feedOptions = new ChangeFeedOptions();

            // ie customize StartFromBeginning so change feed reads from beginning
            // can customize MaxItemCount, PartitonKeyRangeId, RequestContinuation, SessionToken and StartFromBeginning
            feedOptions.StartFromBeginning = true;


            ChangeFeedHostOptions feedHostOptions = new ChangeFeedHostOptions();

            // ie. customizing lease renewal interval to 15 seconds
            // can customize LeaseRenewInterval, LeaseAcquireInterval, LeaseExpirationInterval, FeedPollDelay
            feedHostOptions.LeaseRenewInterval = TimeSpan.FromSeconds(15);

            using (DocumentClient destClient = new DocumentClient(destCollInfo.Uri, destCollInfo.MasterKey))
            {
                DocumentFeedObserverFactory docObserverFactory = new DocumentFeedObserverFactory(destClient, destCollInfo);

                ChangeFeedEventHost host = new ChangeFeedEventHost(hostName, documentCollectionLocation, leaseCollectionLocation, feedOptions, feedHostOptions);

                await host.RegisterObserverFactoryAsync(docObserverFactory);

                Console.WriteLine("Running... Press enter to stop.");
                Console.ReadLine();

                await host.UnregisterObserversAsync();
            }
        }
コード例 #6
0
 public CosmosDBTriggerBinding(ParameterInfo parameter, DocumentCollectionInfo documentCollectionLocation, DocumentCollectionInfo leaseCollectionLocation, ChangeFeedHostOptions leaseHostOptions)
 {
     _bindingDataProvider        = BindingDataProvider.FromType(parameter.ParameterType);
     _documentCollectionLocation = documentCollectionLocation;
     _leaseCollectionLocation    = leaseCollectionLocation;
     _leaseHostOptions           = leaseHostOptions;
     _parameter = parameter;
 }
コード例 #7
0
 public CosmosDBTriggerBinding(ParameterInfo parameter, DocumentCollectionInfo documentCollectionLocation, DocumentCollectionInfo leaseCollectionLocation, ChangeFeedHostOptions leaseHostOptions, int?maxItemsPerCall)
 {
     _documentCollectionLocation = documentCollectionLocation;
     _leaseCollectionLocation    = leaseCollectionLocation;
     _leaseHostOptions           = leaseHostOptions;
     _parameter       = parameter;
     _maxItemsPerCall = maxItemsPerCall;
 }
        public CosmosDBTriggerListener(ITriggeredFunctionExecutor executor, DocumentCollectionInfo documentCollectionLocation, DocumentCollectionInfo leaseCollectionLocation, ChangeFeedHostOptions leaseHostOptions, ChangeFeedOptions changeFeedOptions, ILogger logger)
        {
            this._logger   = logger;
            this._executor = executor;
            this._hostName = Guid.NewGuid().ToString();

            this._monitorCollection = documentCollectionLocation;
            this._leaseCollection   = leaseCollectionLocation;
            this._leaseHostOptions  = leaseHostOptions;
            this._changeFeedOptions = changeFeedOptions;
        }
コード例 #9
0
        /// <summary>
        /// Registers change feed observer to update changes read on change feed to destination
        /// collection. Deregisters change feed observer and closes process when enter key is pressed
        /// </summary>
        /// <returns>A Task to allow asynchronous execution</returns>
        public async Task RunChangeFeed()
        {
            string hostName = Guid.NewGuid().ToString();

            // monitored collection info
            DocumentCollectionInfo starshipCollectionInfo = new DocumentCollectionInfo
            {
                Uri            = new Uri(ConfigurationManager.AppSettings["SqlApi.EndpointUrl"]),
                MasterKey      = ConfigurationManager.AppSettings["SqlApi.AuthorizationKey"],
                DatabaseName   = ConfigurationManager.AppSettings["SqlApi.DatabaseName"],
                CollectionName = ConfigurationManager.AppSettings["SqlApi.StarshipCollectionName"]
            };

            // lease collection info
            DocumentCollectionInfo leaseCollectionInfo = new DocumentCollectionInfo
            {
                Uri            = new Uri(ConfigurationManager.AppSettings["SqlApi.EndpointUrl"]),
                MasterKey      = ConfigurationManager.AppSettings["SqlApi.AuthorizationKey"],
                DatabaseName   = ConfigurationManager.AppSettings["SqlApi.DatabaseName"],
                CollectionName = ConfigurationManager.AppSettings["SqlApi.LeaseCollectionName"]
            };

            await CreateCollectionIfNotExistsAsync(starshipCollectionInfo);
            await CreateCollectionIfNotExistsAsync(leaseCollectionInfo);

            // Customizable change feed option and host options
            ChangeFeedOptions feedOptions = new ChangeFeedOptions();

            // ie customize StartFromBeginning so change feed reads from beginning
            // can customize MaxItemCount, PartitonKeyRangeId, RequestContinuation, SessionToken and StartFromBeginning
            feedOptions.StartFromBeginning = true;

            ChangeFeedHostOptions feedHostOptions = new ChangeFeedHostOptions();

            // ie. customizing lease renewal interval to 15 seconds
            // can customize LeaseRenewInterval, LeaseAcquireInterval, LeaseExpirationInterval, FeedPollDelay
            feedHostOptions.LeaseRenewInterval = TimeSpan.FromSeconds(15);

            using (DocumentClient client = new DocumentClient(starshipCollectionInfo.Uri, starshipCollectionInfo.MasterKey))
            {
                DocumentFeedObserverFactory docObserverFactory = new DocumentFeedObserverFactory(client, starshipCollectionInfo);

                ChangeFeedEventHost host = new ChangeFeedEventHost(hostName, starshipCollectionInfo, leaseCollectionInfo, feedOptions, feedHostOptions);

                await host.RegisterObserverFactoryAsync(docObserverFactory).ConfigureAwait(false);

                Console.WriteLine("Running... Press enter to stop.");
                Console.ReadLine();

                await host.UnregisterObserversAsync();
            }
        }
コード例 #10
0
        public void ValidateLegacyOptionsAreUsed()
        {
            DateTime startTime   = DateTime.Now;
            var      feedOptions = new ChangeFeedOptions
            {
                MaxItemCount        = 1,
                StartFromBeginning  = true,
                StartTime           = startTime,
                RequestContinuation = "RequestContinuation",
                SessionToken        = "SessionToken",
            };

            var checkpointFrequency = new CheckpointFrequency {
                ExplicitCheckpoint = true
            };
            var hostOptions = new ChangeFeedHostOptions
            {
                LeaseRenewInterval          = TimeSpan.FromSeconds(2),
                LeaseAcquireInterval        = TimeSpan.FromSeconds(3),
                LeaseExpirationInterval     = TimeSpan.FromSeconds(4),
                FeedPollDelay               = TimeSpan.FromSeconds(5),
                CheckpointFrequency         = checkpointFrequency,
                LeasePrefix                 = "LeasePrefix",
                MinPartitionCount           = 6,
                MaxPartitionCount           = 7,
                QueryPartitionsMaxBatchSize = 8,
            };

            var processorOptions = ChangeFeedEventHost.CreateProcessorOptions(feedOptions, hostOptions);

            Assert.Equal(1, processorOptions.MaxItemCount);
            Assert.True(processorOptions.StartFromBeginning);
            Assert.Equal(startTime, processorOptions.StartTime);
            Assert.Equal("RequestContinuation", processorOptions.RequestContinuation);
            Assert.Equal("SessionToken", processorOptions.SessionToken);
            Assert.Equal(TimeSpan.FromSeconds(2), processorOptions.LeaseRenewInterval);
            Assert.Equal(TimeSpan.FromSeconds(3), processorOptions.LeaseAcquireInterval);
            Assert.Equal(TimeSpan.FromSeconds(4), processorOptions.LeaseExpirationInterval);
            Assert.Equal(TimeSpan.FromSeconds(5), processorOptions.FeedPollDelay);
            Assert.Equal(checkpointFrequency, processorOptions.CheckpointFrequency);
            Assert.Equal("LeasePrefix", processorOptions.LeasePrefix);
            Assert.Equal(6, processorOptions.MinPartitionCount);
            Assert.Equal(7, processorOptions.MaxPartitionCount);
            Assert.Equal(8, processorOptions.QueryPartitionsMaxBatchSize);
        }
コード例 #11
0
        private async Task StartChangeFeedHost()
        {
            ConnectionPolicy ConnectionPolicy = new ConnectionPolicy
            {
                ConnectionMode     = ConnectionMode.Direct,
                ConnectionProtocol = Protocol.Tcp,
                RequestTimeout     = new TimeSpan(1, 0, 0),
                MaxConnectionLimit = 1000,
                RetryOptions       = new RetryOptions
                {
                    MaxRetryAttemptsOnThrottledRequests = 10,
                    MaxRetryWaitTimeInSeconds           = 60
                }
            };


            //Customizable change feed option and host options
            ChangeFeedOptions feedOptions = new ChangeFeedOptions();

            // ie customize StartFromBeginning so change feed reads from beginning
            // can customize MaxItemCount, PartitonKeyRangeId, RequestContinuation, SessionToken and StartFromBeginning
            feedOptions.StartTime = this.Config.ChangeFeedStartTime;
            var feedHostOptions = new ChangeFeedHostOptions
            {
                // ie. customizing lease renewal interval to 15 seconds
                // can customize LeaseRenewInterval, LeaseAcquireInterval, LeaseExpirationInterval, FeedPollDelay
                LeaseRenewInterval = TimeSpan.FromSeconds(15)
            };

            string hostName = Guid.NewGuid().ToString();
            DocumentFeedObserverFactory docObserverFactory = new DocumentFeedObserverFactory(this.Config);

            this.ChangeFeedEventHost = new ChangeFeedEventHost(hostName, Config.SourceDocumentCollectionInfo, this.Config.LeaseDocumentCollectionInfo, feedOptions, feedHostOptions);

            await this.ChangeFeedEventHost.RegisterObserverFactoryAsync(docObserverFactory);

            Console.WriteLine("Running... Press enter to stop.");
        }
コード例 #12
0
        private static async Task Run()
        {
            ChangeFeedOptions feedOptions = new ChangeFeedOptions {
                StartFromBeginning = true
            };
            // Can customize LeaseRenewInterval, LeaseAcquireInterval, LeaseExpirationInterval, FeedPollDelay
            ChangeFeedHostOptions feedHostOptions = new ChangeFeedHostOptions {
                LeaseRenewInterval = TimeSpan.FromSeconds(15)
            };
            DocumentCollectionInfo documentCollectionLocation = new DocumentCollectionInfo
            {
                Uri            = new Uri(Connection.EndpointUrl),
                CollectionName = "FamilyCollection",
                // ConnectionPolicy = new ConnectionPolicy{},
                DatabaseName = "FamilyDB",
                MasterKey    = Connection.PrimaryKey
            };
            ChangeFeedEventHost       changeFeedEventHost       = new ChangeFeedEventHost("hostName", documentCollectionLocation, documentCollectionLocation, feedOptions, feedHostOptions);
            ChangeFeedObserverFactory changeFeedObserverFactory = new ChangeFeedObserverFactory();
            await changeFeedEventHost.RegisterObserverFactoryAsync(changeFeedObserverFactory);

            await changeFeedEventHost.UnregisterObserversAsync();
        }
        public 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(Task.FromResult <ITriggerBinding>(null));
            }

            DocumentCollectionInfo documentCollectionLocation;
            DocumentCollectionInfo leaseCollectionLocation;
            ChangeFeedHostOptions  leaseHostOptions = ResolveLeaseOptions(attribute);

            try
            {
                string triggerConnectionString = ResolveAttributeConnectionString(attribute);
                DocumentDBConnectionString triggerConnection = new DocumentDBConnectionString(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;.");
                }

                DocumentDBConnectionString leasesConnection = new DocumentDBConnectionString(ResolveAttributeLeasesConnectionString(attribute, triggerConnectionString));
                if (triggerConnection.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   = attribute.DatabaseName,
                    CollectionName = attribute.CollectionName
                };

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

                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.");
                }
            }
            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(Task.FromResult <ITriggerBinding>(new CosmosDBTriggerBinding(parameter, documentCollectionLocation, leaseCollectionLocation, leaseHostOptions)));
        }
 public CosmosDBTriggerAttributeBindingProvider(string monitorConnectionString, string leasesConnectionString, ChangeFeedHostOptions leasesOptions = null)
 {
     _monitorConnectionString = monitorConnectionString;
     _leasesConnectionString  = leasesConnectionString;
     _leasesOptions           = leasesOptions ?? new ChangeFeedHostOptions();
 }
        public CosmosDBTriggerListener(ITriggeredFunctionExecutor executor, DocumentCollectionInfo documentCollectionLocation, DocumentCollectionInfo leaseCollectionLocation, ChangeFeedHostOptions leaseHostOptions, int?maxItemCount)
        {
            this.executor = executor;
            string hostName = Guid.NewGuid().ToString();

            monitorCollection = documentCollectionLocation;
            leaseCollection   = leaseCollectionLocation;

            ChangeFeedOptions changeFeedOptions = new ChangeFeedOptions();

            if (maxItemCount.HasValue)
            {
                changeFeedOptions.MaxItemCount = maxItemCount;
            }

            this.host = new ChangeFeedEventHost(hostName, documentCollectionLocation, leaseCollectionLocation, changeFeedOptions, leaseHostOptions);
        }
コード例 #16
0
        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));
        }
コード例 #17
0
        /// <summary>
        /// Registers change feed observer to update changes read on change feed to destination
        /// collection. Deregisters change feed observer and closes process when enter key is pressed
        /// </summary>
        /// <returns>A Task to allow asynchronous execution</returns>
        public async Task Start(CosmosDBQueueConsumerSettings settings, CancellationTokenSource cts = default)
        {
            if (this.started)
            {
                throw new InvalidOperationException("Already started");
            }

            this.settings = settings;
            await Utils.CreateCollectionIfNotExists(this.settings.QueueCollectionDefinition);

            await Utils.CreateCollectionIfNotExists(this.settings.LeaseCollectionDefinition);

            if (this.OnMessage == null)
            {
                throw new InvalidOperationException($"Set a {nameof(OnMessage)} before start consuming queue items");
            }

            this.workerId = this.settings.WorkerId ?? Guid.NewGuid().ToString();

            // queue collection info
            var documentCollectionLocation = new DocumentCollectionInfo
            {
                Uri            = new Uri(this.settings.QueueCollectionDefinition.Endpoint),
                MasterKey      = this.settings.QueueCollectionDefinition.SecretKey,
                DatabaseName   = this.settings.QueueCollectionDefinition.DbName,
                CollectionName = this.settings.QueueCollectionDefinition.CollectionName
            };

            // lease collection info
            DocumentCollectionInfo leaseCollectionLocation = new DocumentCollectionInfo
            {
                Uri            = new Uri(this.settings.LeaseCollectionDefinition.Endpoint),
                MasterKey      = this.settings.LeaseCollectionDefinition.SecretKey,
                DatabaseName   = this.settings.LeaseCollectionDefinition.DbName,
                CollectionName = this.settings.LeaseCollectionDefinition.CollectionName,
            };

            this.queueCollectionClient = new DocumentClient(new Uri(this.settings.QueueCollectionDefinition.Endpoint), this.settings.QueueCollectionDefinition.SecretKey);

            // Customizable change feed option and host options
            ChangeFeedOptions feedOptions = new ChangeFeedOptions
            {
                StartFromBeginning = true
            };

            ChangeFeedHostOptions feedHostOptions = new ChangeFeedHostOptions
            {
                LeaseRenewInterval = TimeSpan.FromSeconds(15),
                LeasePrefix        = string.Concat(this.workerId, "_"),
            };

            this.logger?.LogTrace($"Starting worker {this.workerId}");

            ChangeFeedEventHost host = new ChangeFeedEventHost(this.workerId, documentCollectionLocation, leaseCollectionLocation, feedOptions, feedHostOptions);
            await host.RegisterObserverFactoryAsync(this);

            if (cts != null)
            {
                cts.Token.Register(async() =>
                {
                    await host.UnregisterObserversAsync();
                });
            }

            this.started = true;
        }
コード例 #18
0
 public MockListener(ITriggeredFunctionExecutor executor, DocumentCollectionInfo documentCollectionLocation, DocumentCollectionInfo leaseCollectionLocation, ChangeFeedHostOptions leaseHostOptions, ChangeFeedOptions changeFeedOptions, ILogger logger)
     : base(executor, documentCollectionLocation, leaseCollectionLocation, leaseHostOptions, changeFeedOptions, logger)
 {
 }
 public CosmosDBTriggerAttributeBindingProvider(INameResolver nameResolver, ChangeFeedHostOptions leasesOptions = null)
 {
     _nameResolver  = nameResolver;
     _leasesOptions = leasesOptions ?? new ChangeFeedHostOptions();
 }
        public CosmosDBTriggerListener(ITriggeredFunctionExecutor executor, DocumentCollectionInfo documentCollectionLocation, DocumentCollectionInfo leaseCollectionLocation, ChangeFeedHostOptions leaseHostOptions)
        {
            this.executor = executor;
            string hostName = Guid.NewGuid().ToString();

            monitorCollection = documentCollectionLocation;
            leaseCollection   = leaseCollectionLocation;

            this.host = new ChangeFeedEventHost(hostName, documentCollectionLocation, leaseCollectionLocation, new ChangeFeedOptions(), leaseHostOptions);
        }
コード例 #21
0
        private static async Task ProcessChangeFeedWithChangeFeedProcessor(DocumentClient client, Database db, DocumentCollection personCol)
        {
            // Use the ChangeFeed Processor which manages to read changes accross partitions.
            // This requires another CosmosDB collection so that ChangeFeedProcessor can store it's lease information!
            // https://docs.microsoft.com/en-us/azure/cosmos-db/change-feed#change-feed-processor
            #region Change Feed Processor
            // Create LeaseCollection
            DocumentCollection leasecol = await CosDB.CreateOrGetCollection(client, db, "leasecol", 400, null, null, false, true);

            // Customizable change feed option and host options
            ChangeFeedOptions feedOptions = new ChangeFeedOptions()
            {
                // ie customize StartFromBeginning so change feed reads from beginning
                // can customize MaxItemCount, PartitonKeyRangeId, RequestContinuation, SessionToken and StartFromBeginning
                StartFromBeginning = true
            };
            ChangeFeedHostOptions feedHostOptions = new ChangeFeedHostOptions()
            {
                // ie. customizing lease renewal interval to 15 seconds
                // can customize LeaseRenewInterval, LeaseAcquireInterval, LeaseExpirationInterval, FeedPollDelay
                LeaseRenewInterval = TimeSpan.FromSeconds(15)
            };
            string hostName = "UniqueHostName01";
            DocumentCollectionInfo documentCollectionLocation = new DocumentCollectionInfo()
            {
                CollectionName   = personCol.Id,
                ConnectionPolicy = ConnectionPolicy.Default,
                DatabaseName     = db.Id,
                MasterKey        = Config.Account_DemoBuild_Mongo_Key,
                Uri = new Uri(Config.Account_DemoBuild_Mongo)
            };
            DocumentCollectionInfo leaseCollectionLocation = new DocumentCollectionInfo()
            {
                CollectionName   = "leasecol",
                ConnectionPolicy = ConnectionPolicy.Default,
                DatabaseName     = db.Id,
                MasterKey        = Config.Account_DemoBuild_Mongo_Key,
                Uri = new Uri(Config.Account_DemoBuild_Mongo)
            };

            DocumentFeedObserverFactory docObserverFactory = new DocumentFeedObserverFactory();
            ChangeFeedEventHost         host = new ChangeFeedEventHost(hostName,
                                                                       documentCollectionLocation,
                                                                       leaseCollectionLocation,
                                                                       feedOptions, feedHostOptions);

            await host.RegisterObserverFactoryAsync(docObserverFactory);

            Console.WriteLine("Waiting 2-3 seconds before adding more documents...");
            Thread.Sleep(2500);

            Random        randGen = new Random((int)DateTime.Now.Ticks);
            List <string> cities  = new List <string>()
            {
                "Vienna", "Paris", "Frankfurt", "Prag", "Seattle"
            };
            for (int c = 0; c < 10000; c++) // with this long running sample, the Lease is probably lost
            {
                string city = cities[randGen.Next() % cities.Count];
                await client.CreateDocumentAsync(personCol.SelfLink, new Person()
                {
                    name = Guid.NewGuid().ToString("D"), city = city, label = "person"
                });

                await client.CreateDocumentAsync(personCol.SelfLink, new Person()
                {
                    name = Guid.NewGuid().ToString("D"), city = city, label = "person"
                });

                await client.CreateDocumentAsync(personCol.SelfLink, new Person()
                {
                    name = Guid.NewGuid().ToString("D"), city = city, label = "person"
                });
            }

            Console.WriteLine("Observer is still running... Modify or add documents with DocumentStudio. Press enter to stop.");
            Console.ReadLine();

            await host.UnregisterObserversAsync();

            #endregion
        }