/// <summary> /// Initializes a new instance of the <see cref="DocumentCollectionInfo"/> class. /// </summary> /// <param name="other">The other <see cref="DocumentCollectionInfo"/> to copy settings from.</param> public DocumentCollectionInfo(DocumentCollectionInfo other) { this.Uri = other.Uri; this.MasterKey = other.MasterKey; this.DatabaseName = other.DatabaseName; this.CollectionName = other.CollectionName; this.ConnectionPolicy = other.ConnectionPolicy; }
/// <summary> /// Initializes a new instance of the <see cref="ChangeFeedEventHost"/> class. /// </summary> /// <param name="hostName">Unique name for this host.</param> /// <param name="feedCollectionLocation">Specifies location of the Cosmos DB collection to monitor changes for.</param> /// <param name="leaseCollectionLocation">Specifies location of auxiliary data for load-balancing instances of <see cref="ChangeFeedEventHost" />.</param> /// <param name="changeFeedHostOptions">Additional options to control load-balancing of <see cref="ChangeFeedEventHost" /> instances.</param> public ChangeFeedEventHost( string hostName, DocumentCollectionInfo feedCollectionLocation, DocumentCollectionInfo leaseCollectionLocation, ChangeFeedHostOptions changeFeedHostOptions) : this(hostName, feedCollectionLocation, leaseCollectionLocation, new ChangeFeedOptions(), changeFeedHostOptions) { }
/// <summary> /// Sets the <see cref="DocumentCollectionInfo"/> of the collection to use for leases. /// </summary> /// <param name="leaseCollectionLocation">The instance of a <see cref="DocumentCollectionInfo"/> to use.</param> /// <returns>The instance of <see cref="ChangeFeedProcessorBuilder"/> to use.</returns> public ChangeFeedProcessorBuilder WithLeaseCollection(DocumentCollectionInfo leaseCollectionLocation) { if (leaseCollectionLocation == null) { throw new ArgumentNullException(nameof(leaseCollectionLocation)); } this.leaseCollectionLocation = leaseCollectionLocation.Canonicalize(); return(this); }
private async Task <ILeaseStoreManager> GetLeaseStoreManagerAsync( DocumentCollectionInfo collectionInfo, bool isPartitionKeyByIdRequiredIfPartitioned) { if (this.LeaseStoreManager == null) { var leaseDocumentClient = this.leaseDocumentClient ?? this.leaseCollectionLocation.CreateDocumentClient(); var collection = await leaseDocumentClient.GetDocumentCollectionAsync(collectionInfo).ConfigureAwait(false); bool isPartitioned = collection.PartitionKey != null && collection.PartitionKey.Paths != null && collection.PartitionKey.Paths.Count > 0; if (isPartitioned && isPartitionKeyByIdRequiredIfPartitioned && (collection.PartitionKey.Paths.Count != 1 || collection.PartitionKey.Paths[0] != "/id")) { throw new ArgumentException("The lease collection, if partitioned, must have partition key equal to id."); } var requestOptionsFactory = isPartitioned ? (IRequestOptionsFactory) new PartitionedByIdCollectionRequestOptionsFactory() : (IRequestOptionsFactory) new SinglePartitionRequestOptionsFactory(); string leasePrefix = this.GetLeasePrefix(); var leaseStoreManagerBuilder = new DocumentServiceLeaseStoreManagerBuilder() .WithLeasePrefix(leasePrefix) .WithLeaseCollection(this.leaseCollectionLocation) .WithLeaseCollectionLink(collection.SelfLink) .WithRequestOptionsFactory(requestOptionsFactory) .WithHostName(this.HostName); leaseStoreManagerBuilder = leaseStoreManagerBuilder.WithLeaseDocumentClient(leaseDocumentClient); this.LeaseStoreManager = await leaseStoreManagerBuilder.BuildAsync().ConfigureAwait(false); } return(this.LeaseStoreManager); }
/// <summary> /// Initializes a new instance of the <see cref="ChangeFeedEventHost"/> class. /// </summary> /// <param name="hostName">Unique name for this host.</param> /// <param name="feedCollectionLocation">Specifies location of the Cosmos DB collection to monitor changes for.</param> /// <param name="leaseCollectionLocation">Specifies location of auxiliary data for load-balancing instances of <see cref="ChangeFeedEventHost" />.</param> /// <param name="changeFeedOptions">Options to pass to the DocumentClient.CreateDocumentChangeFeedQuery API.</param> /// <param name="changeFeedHostOptions">Additional options to control load-balancing of <see cref="ChangeFeedEventHost" /> instances.</param> public ChangeFeedEventHost( string hostName, DocumentCollectionInfo feedCollectionLocation, DocumentCollectionInfo leaseCollectionLocation, ChangeFeedOptions changeFeedOptions, ChangeFeedHostOptions changeFeedHostOptions) { if (string.IsNullOrEmpty(hostName)) { throw new ArgumentNullException(nameof(hostName)); } if (feedCollectionLocation == null) { throw new ArgumentNullException(nameof(feedCollectionLocation)); } if (leaseCollectionLocation == null) { throw new ArgumentNullException(nameof(leaseCollectionLocation)); } if (changeFeedOptions == null) { throw new ArgumentNullException(nameof(changeFeedOptions)); } if (changeFeedHostOptions == null) { throw new ArgumentNullException(nameof(changeFeedHostOptions)); } ChangeFeedEventHost.TraceLogProvider.OpenNestedContext(hostName); this.builder .WithHostName(hostName) .WithFeedCollection(feedCollectionLocation) .WithProcessorOptions(ChangeFeedEventHost.CreateProcessorOptions(changeFeedOptions, changeFeedHostOptions)) .WithLeaseCollection(leaseCollectionLocation); }
/// <summary> /// Example of a code migration template from Change Feed Processor V2 to SDK V3. /// </summary> /// <returns></returns> public static async Task RunMigrationSample( string databaseId, CosmosClient client, IConfigurationRoot configuration) { await Program.InitializeAsync(databaseId, client); Console.WriteLine("Generating 10 items that will be picked up by the old Change Feed Processor library..."); await Program.GenerateItems(10, client.GetContainer(databaseId, Program.monitoredContainer)); // This is how you would initialize the processor in V2 // <ChangeFeedProcessorLibrary> ChangeFeedProcessorLibrary.DocumentCollectionInfo monitoredCollectionInfo = new ChangeFeedProcessorLibrary.DocumentCollectionInfo() { DatabaseName = databaseId, CollectionName = Program.monitoredContainer, Uri = new Uri(configuration["EndPointUrl"]), MasterKey = configuration["AuthorizationKey"] }; ChangeFeedProcessorLibrary.DocumentCollectionInfo leaseCollectionInfo = new ChangeFeedProcessorLibrary.DocumentCollectionInfo() { DatabaseName = databaseId, CollectionName = Program.leasesContainer, Uri = new Uri(configuration["EndPointUrl"]), MasterKey = configuration["AuthorizationKey"] }; ChangeFeedProcessorLibrary.ChangeFeedProcessorBuilder builder = new ChangeFeedProcessorLibrary.ChangeFeedProcessorBuilder(); var oldChangeFeedProcessor = await builder .WithHostName("consoleHost") .WithProcessorOptions(new ChangeFeedProcessorLibrary.ChangeFeedProcessorOptions { StartFromBeginning = true, LeasePrefix = "MyLeasePrefix", MaxItemCount = 10, FeedPollDelay = TimeSpan.FromSeconds(1) }) .WithFeedCollection(monitoredCollectionInfo) .WithLeaseCollection(leaseCollectionInfo) .WithObserver <ChangeFeedObserver>() .BuildAsync(); // </ChangeFeedProcessorLibrary> await oldChangeFeedProcessor.StartAsync(); // Wait random time for the delegate to output all messages after initialization is done await Task.Delay(5000); Console.WriteLine("Now we will stop the V2 Processor and start a V3 with the same parameters to pick up from the same state, press any key to continue..."); Console.ReadKey(); await oldChangeFeedProcessor.StopAsync(); Console.WriteLine("Generating 5 items that will be picked up by the new Change Feed Processor..."); await Program.GenerateItems(5, client.GetContainer(databaseId, Program.monitoredContainer)); // This is how you would do the same initialization in V3 // <ChangeFeedProcessorMigrated> Container leaseContainer = client.GetContainer(databaseId, Program.leasesContainer); Container monitoredContainer = client.GetContainer(databaseId, Program.monitoredContainer); ChangeFeedProcessor changeFeedProcessor = monitoredContainer .GetChangeFeedProcessorBuilder <ToDoItem>("MyLeasePrefix", Program.HandleChangesAsync) .WithInstanceName("consoleHost") .WithLeaseContainer(leaseContainer) .WithMaxItems(10) .WithPollInterval(TimeSpan.FromSeconds(1)) .WithStartTime(DateTime.MinValue.ToUniversalTime()) .Build(); // </ChangeFeedProcessorMigrated> await changeFeedProcessor.StartAsync(); // Wait random time for the delegate to output all messages after initialization is done await Task.Delay(5000); Console.WriteLine("Press any key to continue with the next demo..."); Console.ReadKey(); await changeFeedProcessor.StopAsync(); }
/// <summary> /// Initializes a new instance of the <see cref="ChangeFeedEventHost"/> class. /// </summary> /// <param name="hostName">Unique name for this host.</param> /// <param name="documentCollectionLocation">Specifies location of the DocumentDB collection to monitor changes for.</param> /// <param name="leaseCollectionLocation ">Specifies location of auxiliary data for load-balancing instances of <see cref="ChangeFeedEventHost" />.</param> public ChangeFeedEventHost(string hostName, DocumentCollectionInfo documentCollectionLocation, DocumentCollectionInfo leaseCollectionLocation) : this(hostName, documentCollectionLocation, leaseCollectionLocation, new ChangeFeedOptions(), new ChangeFeedHostOptions()) { }
private static async Task <string> GetCollectionResourceIdAsync(IChangeFeedDocumentClient documentClient, DocumentCollectionInfo collectionLocation) { Logger.InfoFormat("Reading collection: '{0}'", collectionLocation.CollectionName); DocumentCollection documentCollection = await documentClient.GetDocumentCollectionAsync(collectionLocation).ConfigureAwait(false); return(documentCollection.ResourceId); }
private static async Task <string> GetDatabaseResourceIdAsync(IChangeFeedDocumentClient documentClient, DocumentCollectionInfo collectionLocation) { Logger.InfoFormat("Reading database: '{0}'", collectionLocation.DatabaseName); Uri databaseUri = UriFactory.CreateDatabaseUri(collectionLocation.DatabaseName); var response = await documentClient.ReadDatabaseAsync(databaseUri, null).ConfigureAwait(false); return(response.Resource.ResourceId); }