1

We recently migrated from legacy publishing to publishing service. In Publishing service, "getItemReferences" pipeline decommissioned. So we have to seek the ways to publish related items. Hence, we have written a customized processor under "publishEndResultBatch" pipeline. Thanks for great article written by Vincent Lui. https://vincent-lui.medium.com/sitecore-publishing-service-the-good-the-bad-and-the-ugly-74a9c17c9e16

We are take the article as reference and built our logic under "publishEndResultBatch" pipeline. Related items are published.

But the problem is that every related item is publising in separate job that led to performance dip. For ex: If i have 50 related items for an item, 50 dedicated jobs scheduled in publishing service.

Can anybody came across these use cases. Please suggest the better way to publish all related items at one go along with context item.

Here is my code:

public class ProcessRelatedItems
 {
    private readonly IDatabaseFactory _databaseFactory;        
    private readonly IPublishingLog _publishingLog;
    private readonly IServiceItem _publishedItem;

    public ProcessRelatedItems() : this(new PublishingLogWrapper(), new DatabaseFactoryWrapper(new PublishingLogWrapper()), new PublishedItem()) { }

    public ProcessRelatedItems(IPublishingLog publishingLog,IDatabaseFactory databaseFactory,IServiceItem publishedItem)
    {
        Condition.Requires(publishingLog, nameof(publishingLog)).IsNotNull();
        Condition.Requires(databaseFactory, nameof(databaseFactory)).IsNotNull();
        Condition.Requires(publishedItem, nameof(publishedItem)).IsNotNull();
        _databaseFactory = databaseFactory;           
        _publishingLog = publishingLog;
        _publishedItem = publishedItem;
    }


    public void Process(PublishEndResultBatchArgs args)
    {
        if (args.JobData.Metadata.Where(x => x.Key == "Publish.Options.IncludeRelatedItems").Select(i => i.Value).FirstOrDefault() == "True")
        {
            Assert.ArgumentNotNull((object)args, nameof(args));
            _publishingLog.Debug("Processing Published Items and Transforming into a list of Published item");
            ProcessPublishedItems(args);
        }
    }


  public void ProcessPublishedItems(PublishEndResultBatchArgs args)
    {            
        IEnumerable<SC.Data.Items.Item> itemReferences = null;
        Database master = SC.Configuration.Factory.GetDatabase("master");
        Database web = SC.Configuration.Factory.GetDatabase("web");
        List<SC.Data.Items.Item> modifiedRelatedItems = new List<SC.Data.Items.Item>();
        List<SC.Publishing.PublishOptions> publishingOptionsList = new List<SC.Publishing.PublishOptions>();            
        SC.Publishing.PublishOptions publishOptions = new SC.Publishing.PublishOptions(master, web, SC.Publishing.PublishMode.SingleItem, Context.Language, System.DateTime.Now);            
        bool parseItemId = ID.TryParse(args.JobData.ItemId, out ID itemId);
        PublishItemContext publishitemcontext = new PublishItemContext(itemId, publishOptions);            
        SC.Data.Items.Item sourceItem = publishitemcontext.PublishHelper.GetSourceItem(itemId);
        if (sourceItem == null)
            return;
        itemReferences = this.GetReferences(sourceItem, true);
        var datasourceItems = itemReferences.Where(item => item.TemplateName == "Folder").ToList();
        foreach (SC.Data.Items.Item relatedItem in datasourceItems)
        {
            SC.Publishing.PublishOptions publishRelatedItemsOptions = new SC.Publishing.PublishOptions(master, web, SC.Publishing.PublishMode.Smart, Context.Language, System.DateTime.Now)
            {
                Deep = true,
                RootItem = relatedItem,
                PublishRelatedItems = true
            };

            publishingOptionsList.Add(publishRelatedItemsOptions);
        }            
        SC.Publishing.PublishOptions[] publishingOptionsArray = publishingOptionsList.ToArray();
        if (publishingOptionsArray.Length > 0)
        {
            var publisher = SC.Publishing.PublishManager.Publish(publishingOptionsArray);
            _publishedItem.PublishedStatus = true;
        }
        else
        {
            _publishedItem.PublishedStatus = false;
        }            
    }


 private IEnumerable<SC.Data.Items.Item> GetReferences(SC.Data.Items.Item item, bool sharedOnly)
    {
        Assert.ArgumentNotNull((object)item, nameof(item));
        List<SC.Data.Items.Item> source = new List<SC.Data.Items.Item>();
        ItemLink[] array = ((IEnumerable<ItemLink>)item.Links.GetValidLinks()).Where<ItemLink>((Func<ItemLink, bool>)(link => item.Database.Name.Equals(link.TargetDatabaseName, StringComparison.OrdinalIgnoreCase))).ToArray<ItemLink>();
        if (sharedOnly)
        {
            array = ((IEnumerable<ItemLink>)array).Where<ItemLink>((Func<ItemLink, bool>)(link =>
            {
                SC.Data.Items.Item sourceItem = link.GetSourceItem();
                if (sourceItem == null)
                {
                    return false;
                }
                if (!ID.IsNullOrEmpty(link.SourceFieldID))
                {
                    return sourceItem.Fields[link.SourceFieldID].Shared;
                }

                return true;
            })).ToArray<ItemLink>();
        }
        foreach (SC.Data.Items.Item obj in ((IEnumerable<ItemLink>)array).Select<ItemLink, SC.Data.Items.Item>((Func<ItemLink, SC.Data.Items.Item>)(link => link.GetTargetItem())).Where<SC.Data.Items.Item>((Func<SC.Data.Items.Item, bool>)(relatedItem => relatedItem != null)).ToList<SC.Data.Items.Item>())
        {
            source.AddRange(PublishQueue.GetParents(obj));
            source.Add(obj);
            if (obj.HasChildren)
            {
                source.AddRange(obj.GetChildren());
            }
        }
        return source.Distinct<SC.Data.Items.Item>((IEqualityComparer<SC.Data.Items.Item>)new ItemIdComparer());
    }
4
  • For what problem are you trying to solve by tapping into the pipeline? Is it possible you no longer need to even do this? Commented Apr 19, 2021 at 13:35
  • There are 2 problems: One is "getItemReferences" pipeline is decommissioned where we have did customization. Second, we have item reference for an item (i.e) datasource which contains multi level child items. If we change a child item at any level of datasource, that is not getting published along with context item. This is the main problem we are trying to solve. With publishing service, the datasource item only get published. if datasource item contains child items. If we change any one of the child item, that change is not published.
    – Thamizh
    Commented Apr 19, 2021 at 13:58
  • I just quickly dug through the Publishing Service config files. If you reflect Sitecore.Framework.Publishing.PublishJobQueue.Handlers.TreePublishHandler, Sitecore.Framework.Publishing you might get some idea. Find the keyword "related". You can then possibly override the config file from sc.publishing.services.xml. Please proceed with caution. Commented Apr 19, 2021 at 23:32
  • Another idea, it may be worth tapping into various item:save events and actually updating the Link databases, so that you do not have to make any changes at all in Publishing Related items, and fingers cross that the related items config will just publish those items. Commented Apr 19, 2021 at 23:41

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.