Beispiel #1
0
        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);
            }
        }