Maksym Ponomarenko
Sitecore Consulting

How to fix a synchronization problem of the Sitecore Sharepoint Integration Framework (SPIF)


Using SPIF 2.1 for Sitecore 8.1, we found an interesting problem that some items are duplicated after the sync process if you use one-way synchronization. When we open the duplicated items, all fields are mapped correctly, the SharepointItemId as well. For some reason though, the sync process didn’t recognize that the integration items already exist for some documents.

How to reproduce:

  • Sync all Sharepoint items.
  • Delete all Sitecore Integration Items manually
  • Run sync process
  • Kill the Application process (restart Application Pool, website or IIS, update config or kill the process manually) before the sync process finished.
  • Rerun sync

Result:
  • All imported Items are duplicated.

Usually this happens on Dev or QA environments, because sometimes you need to delete all integration items and restart the sync process for testing. If you have thousands of Sharepoint docs and the blob integration is switched on, the sync process can run more than ten hours. During this time there are a lot of reasons why the application process can be restarted. But of course, it can happen on a production environment as well.

Why it happens:

The sync process runs in the synchronizeTree pipeline and the idea is pretty clear: we get a Sharepoint items list, a Sitecore integrations items list, compare them (in the MergeLists processor) and execute some merge actions (create/update/delete action for Sitecore or Sharepoint items).

synchronizationTree pipeline 

To know which items were manually deleted during the sync process, SPIF uses IDTable. When a user deletes an item manually from the CE, a HistoryProviderIDTable writes a row in the ID Table “SPIF_DELETE” with the Sharepoint Item ID and the Integration Item ID.

configuration uiDeleteItems processors in the Sharepoint.config 

SPIF_Delete in IDTable

Then the IDTable is used by the MergeLists processor to identify the Sharepoint items that should be deleted for bidirectional sync. In the last step, the module calls method “refresh” of the HistoryProviderIDTable processor to clean up the IDTable.

For guys who likes to read C# more than normal text, below I show a code of the MergeLists processor.

namespace Sitecore.Sharepoint.Pipelines.SynchronizeTree
{
  public class MergeLists
  {
    public void Process(SynchronizeTreeArgs args)
    {
      Assert.ArgumentNotNull(args, "args");
      Assert.IsNotNull(args.IntegrationItems, "Value can't be null: args.IntegrationItems");
      Assert.IsNotNull(args.SharepointItemList, "Value can't be null: args.SharepointItemList");
      Assert.IsNotNull(args.Context, "Value can't be null: args.Context");
      List<SyncActionBase> list = new List<SyncActionBase>();
      bool bidirectionalLink = args.Context.IntegrationConfigData.BidirectionalLink;
      Dictionary<string, BaseItem> dictionary = args.SharepointItemList.ToDictionary<BaseItem, string>(item => item.GUID);
      foreach (IntegrationItem item in args.IntegrationItems)
      {
      BaseItem item2;
      if (dictionary.TryGetValue(item.GUID, out item2))
      {
        if (!this.historyProvider.IsItemDeleted(args, item.GUID))
        {
          dictionary.Remove(item.GUID);
          if (item.IsActive)
          {
          if (bidirectionalLink && this.historyProvider.IsItemChanged(args, item.GUID))
          {
            list.Add(this.actionFactory.GetUpdateSharepointItemAction(args, item2, item));
            }
          else
          {
            list.Add(this.actionFactory.GetUpdateIntegrationItemAction(args, item, item2));
          }
          }
        }
      }
      else if (bidirectionalLink && item.IsNew)
      {
        list.Add(this.actionFactory.GetCreateSharepointItemAction(args, item));
      }
      else if (item.IsActive)
      {
        list.Add(this.actionFactory.GetDeleteIntegrationItemAction(args, item));
      }
      }
      foreach (BaseItem item3 in dictionary.Values)
      {
      if (bidirectionalLink && this.historyProvider.IsItemDeleted(args, item3.GUID))
      {
        list.Add(this.actionFactory.GetDeleteSharepointItemAction(args, item3));
      }
      else
      {
        list.Add(this.actionFactory.GetCreateIntegrationItemAction(args, item3));
      }
      }
      args.ActionList = list;
    }
  }
 

}


  • Where Item.Guid is a SharepointItemId;
  • dictionary – Sharepoint items list
  • IntegrationItems – a list of the integration Sitecore items
  • if bidirectionalLink is true sync process runs in both directions.

How to fix the problem:

As I mentioned, it is only for one-way syncing. That means, that you don’t need to write in the IDTable “SPIF_Delete” logs, which are the reason of the problem.

So the easiest way to fix it, is to comment the processor HistoryProviderIDTable in the Sharepoint config out.

Kommentare
Es wurden noch keine Kommentare zu diesem Eintrag geschrieben.
Kommentar hinzufügen
Vor und Zuname
E-Mail
E-Mail bei weiteren Kommentaren
Mein Kommentar