private void RefreshContentOfContentTypes(int[] contentTypeIds) { const int pageSize = 500; var page = 0; var total = long.MaxValue; while (page * pageSize < total) { IEnumerable <IContent> contentToRefresh = _contentService.GetPagedOfTypes( //Re-index all content of these types contentTypeIds, page++, pageSize, out total, null, //order by shallowest to deepest, this allows us to check it's published state without checking every item Ordering.By("Path", Direction.Ascending)); //track which Ids have their paths are published var publishChecked = new Dictionary <int, bool>(); foreach (IContent c in contentToRefresh) { var isPublished = false; if (c.Published) { if (!publishChecked.TryGetValue(c.ParentId, out isPublished)) { //nothing by parent id, so query the service and cache the result for the next child to check against isPublished = _contentService.IsPathPublished(c); publishChecked[c.Id] = isPublished; } } _umbracoIndexingHandler.ReIndexForContent(c, isPublished); } } }
/// <summary> /// Updates indexes based on content changes /// </summary> /// <param name="sender"></param> /// <param name="args"></param> public void Handle(ContentCacheRefresherNotification args) { if (!_umbracoIndexingHandler.Enabled) { return; } if (Suspendable.ExamineEvents.CanIndex == false) { return; } if (args.MessageType != MessageType.RefreshByPayload) { throw new NotSupportedException(); } // Used to track permanent deletions so we can bulk delete from the index // when needed. For example, when emptying the recycle bin, else it will // individually update the index which will be much slower. HashSet <int> deleteBatch = null; foreach (var payload in (ContentCacheRefresher.JsonPayload[])args.MessageObject) { if (payload.ChangeTypes.HasType(TreeChangeTypes.Remove)) { if (deleteBatch == null) { deleteBatch = new HashSet <int>(); } deleteBatch.Add(payload.Id); } else if (payload.ChangeTypes.HasType(TreeChangeTypes.RefreshAll)) { // ExamineEvents does not support RefreshAll // just ignore that payload // so what?! // TODO: Rebuild the index at this point? } else // RefreshNode or RefreshBranch (maybe trashed) { if (deleteBatch != null && deleteBatch.Contains(payload.Id)) { // the same node has already been deleted, to ensure ordering is // handled, we'll need to execute all queued deleted items now // and reset the deleted items list. _umbracoIndexingHandler.DeleteIndexForEntities(deleteBatch, false); deleteBatch = null; } // don't try to be too clever - refresh entirely // there has to be race conditions in there ;-( var content = _contentService.GetById(payload.Id); if (content == null) { // gone fishing, remove entirely from all indexes (with descendants) _umbracoIndexingHandler.DeleteIndexForEntity(payload.Id, false); continue; } IContent published = null; if (content.Published && _contentService.IsPathPublished(content)) { published = content; } if (published == null) { _umbracoIndexingHandler.DeleteIndexForEntity(payload.Id, true); } // just that content _umbracoIndexingHandler.ReIndexForContent(content, published != null); // branch if (payload.ChangeTypes.HasType(TreeChangeTypes.RefreshBranch)) { var masked = published == null ? null : new List <int>(); const int pageSize = 500; var page = 0; var total = long.MaxValue; while (page * pageSize < total) { var descendants = _contentService.GetPagedDescendants(content.Id, page++, pageSize, out total, //order by shallowest to deepest, this allows us to check it's published state without checking every item ordering: Ordering.By("Path", Direction.Ascending)); foreach (var descendant in descendants) { published = null; if (masked != null) // else everything is masked { if (masked.Contains(descendant.ParentId) || !descendant.Published) { masked.Add(descendant.Id); } else { published = descendant; } } _umbracoIndexingHandler.ReIndexForContent(descendant, published != null); } } } } // NOTE // // DeleteIndexForEntity is handled by UmbracoContentIndexer.DeleteFromIndex() which takes // care of also deleting the descendants // // ReIndexForContent is NOT taking care of descendants so we have to reload everything // again in order to process the branch - we COULD improve that by just reloading the // XML from database instead of reloading content & re-serializing! // // BUT ... pretty sure it is! see test "Index_Delete_Index_Item_Ensure_Heirarchy_Removed" } if (deleteBatch != null) { // process the delete batch _umbracoIndexingHandler.DeleteIndexForEntities(deleteBatch, false); } }