Sitecore contact cannot be loaded, code never responds

In Sitecore, it is possible to encounter a situation where the calls identifying or locking a contact never responds, but there is no errors returned.

A call to identify:

Tracker.Current.Session.Identify(contactName);

And a call to Load a contact:

Contact contact = 
    contactRepository.LoadContactReadOnly(username);

Can both take forever without any errors or any timeout.

This situation can occur if the Contact Successor points to the original Contact in a loop. When merging a contact, Sitecore will create a new contact, the Surviving contact. The existing contact (called the Dying contact) still contains all the interaction data from before the merge, so instead of Sitecore having to update all data fields with a new ID, it creates a “Successor” pointer to the Dying Contact.

Surviving Contact

Surviving Contact

But in certain situations, the Dying Contact will also have a Successor, which points back to the Surviving Contact, creating an infinite loop:

The Dying Contact's Successor points to the surviving contact.

The Dying Contact’s Successor points to the surviving contact.

The patterns for this situation are many, but usually involves merging and changing contact identifiers, and can be reproduced like this:

  • Create a contact “A”
  • Create a new contact “B”
  • Merge contact “B” with “A”
  • Merge contact “A” with “B”

To avoid this situation, it is customary to rename the dying contact’s (“A”) identifier to an obscure name (a guid). But the renaming might fail if the dying contact is locked, leaving a contact with a reusable identifier. The “Extended Contact Repository” which I have described previously will unfortunately gladly create a new contact with an existing name.

HOW TO RESOLVE IT:

The situation needs to be resolved manually. Find the contact, open RoboMongo and search for the contact:

identifier = db.Identifiers.findOne({_id: /NAME_OF_IDENTIFIER/i});
contact = db.Contacts.find({_id: identifier.contact});

Copy the “Successor” value from the contact, and find the Successor:

successor = db.Contacts.find({_id: NUUID("b1e760d7-7c60-4b1d-818f-e357f303ebef9")});

Right click the “Edit Document” button and delete the “Successor” field from the dying contact:

Delete Successor Field from the Dying Contact, breaking the infinite loop

Delete Successor Field from the Dying Contact, breaking the infinite loop

This can be done directly in production, and the code reacts instantly when the loop have been broken.

MORE TO READ:

 

Advertisement

About briancaos

Developer at Pentia A/S since 2003. Have developed Web Applications using Sitecore Since Sitecore 4.1.
This entry was posted in Sitecore 7, Sitecore 8 and tagged , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.