public void ShouldIncludeReferenceIndexingDetails() { using (var store = GetDocumentStore()) { var index = new Products_ByCategory(); index.Execute(store); using (var session = store.OpenSession()) { session.Store(new Category { Id = "categories/0", Name = "foo" }); session.Store(new Category { Id = "categories/1", Name = "bar" }); for (int i = 0; i < 200; i++) { session.Store(new Product { Category = $"categories/{i % 2}" }); } session.SaveChanges(); } Indexes.WaitForIndexing(store); using (var session = store.OpenSession()) { session.Store(new Category { Id = "categories/1", Name = "baz" }); session.SaveChanges(); } Indexes.WaitForIndexing(store); var indexInstance = GetDatabase(store.Database).Result.IndexStore.GetIndex(index.IndexName); var stats = indexInstance.GetIndexingPerformance(); var referenceRunDetails = stats.SelectMany(x => x.Details.Operations.Select(y => y.ReferenceDetails)).Where(x => x != null && x.ReferenceAttempts > 0).ToList(); Assert.Equal(1, referenceRunDetails.Count); Assert.Equal(100, referenceRunDetails[0].ReferenceAttempts); Assert.Equal(100, referenceRunDetails[0].ReferenceSuccesses); Assert.Equal(0, referenceRunDetails[0].ReferenceErrors); } }
public async Task Should_create_performance_hint_notification_when_exceeding_max_number_of_LoadDocument_calls_per_reference() { using (var store = GetDocumentStore()) { var db = await GetDatabase(store.Database); db.Configuration.PerformanceHints.MaxNumberOfLoadsPerReference = 10; db.NotificationCenter.Indexing.MinUpdateInterval = TimeSpan.MinValue; var index = new Products_ByCategory(); using (var session = store.OpenSession()) { session.Store(new Category { Id = "categories/0", Name = "foo" }); session.Store(new Category { Id = "categories/1", Name = "bar" }); for (int i = 0; i < 200; i++) { session.Store(new Product { Category = $"categories/{i % 2}" }); } session.SaveChanges(); } await index.ExecuteAsync(store); Indexes.WaitForIndexing(store); var notificationsQueue = new AsyncQueue <DynamicJsonValue>(); using (db.NotificationCenter.TrackActions(notificationsQueue, null)) { using (var session = store.OpenSession()) { session.Store(new Category { Id = "categories/0", Name = "abc" }); session.SaveChanges(); } Indexes.WaitForIndexing(store); Tuple <bool, DynamicJsonValue> performanceHint; do { performanceHint = await notificationsQueue.TryDequeueAsync(TimeSpan.FromSeconds(5)); } while (performanceHint.Item2["Type"].ToString() != NotificationType.PerformanceHint.ToString()); Assert.NotNull(performanceHint.Item2); Assert.Equal("We have detected high number of LoadDocument() / LoadCompareExchangeValue() calls per single reference item. The update of a reference will result in reindexing all documents that reference it. Please see Indexing Performance graph to check the performance of your indexes.", performanceHint.Item2[nameof(PerformanceHint.Message)]); Assert.Equal(PerformanceHintType.Indexing_References, performanceHint.Item2[nameof(PerformanceHint.HintType)]); var details = performanceHint.Item2[nameof(PerformanceHint.Details)] as DynamicJsonValue; Assert.NotNull(details); using (var ctx = JsonOperationContext.ShortTermSingleUse()) { var json = ctx.ReadObject(details, "foo"); var detailsObject = DocumentConventions.DefaultForServer.Serialization.DefaultConverter.FromBlittable <IndexingReferenceLoadWarning>(json, "bar"); Assert.Contains("Products/ByCategory", detailsObject.Warnings.Keys); Assert.Equal(1, detailsObject.Warnings.Count); var top10LoadedReferences = detailsObject.Warnings["Products/ByCategory"].Top10LoadedReferences; Assert.Equal(1, top10LoadedReferences.Count); Assert.Equal("categories/0", top10LoadedReferences["categories/0"].ReferenceId); Assert.Equal(100, top10LoadedReferences["categories/0"].NumberOfLoads); } // update of the hint using (var session = store.OpenSession()) { session.Store(new Category { Id = "categories/1", Name = "def" }); session.SaveChanges(); } Indexes.WaitForIndexing(store); db.NotificationCenter.Indexing.UpdateIndexing(null); do { performanceHint = await notificationsQueue.TryDequeueAsync(TimeSpan.FromSeconds(5)); } while (performanceHint.Item2["Type"].ToString() != NotificationType.PerformanceHint.ToString()); details = performanceHint.Item2[nameof(PerformanceHint.Details)] as DynamicJsonValue; Assert.NotNull(details); using (var ctx = JsonOperationContext.ShortTermSingleUse()) { var json = ctx.ReadObject(details, "foo"); var detailsObject = DocumentConventions.DefaultForServer.Serialization.DefaultConverter.FromBlittable <IndexingReferenceLoadWarning>(json, "bar"); Assert.Contains("Products/ByCategory", detailsObject.Warnings.Keys); Assert.Equal(1, detailsObject.Warnings.Count); var top10LoadedReferences = detailsObject.Warnings["Products/ByCategory"].Top10LoadedReferences; Assert.Equal(2, top10LoadedReferences.Count); Assert.Equal("categories/0", top10LoadedReferences["categories/0"].ReferenceId); Assert.Equal(100, top10LoadedReferences["categories/0"].NumberOfLoads); Assert.Equal("categories/1", top10LoadedReferences["categories/1"].ReferenceId); Assert.Equal(100, top10LoadedReferences["categories/1"].NumberOfLoads); } } } }