3

I am running a process in the Data Exchange Framework so I don't really have access to the tracker. Is there a way to tell if a contact is locked/in session other than using the following and checking the status (already locked)?

LockAttemptResult<Contact> lockResult = contactRepository.TryLoadContact(emailAddress, leaseOwner, TimeSpan.FromMinutes(1));

That returns a status, but also tries and locks it. I just need to know if it is already locked.

I was hoping var contact = contactRepository.LoadContactReadOnly(email); would also include a lock status, but does not seem to be a way to get it. I need a way basically to pass in an email and return a lock status. This post was helpful, but I am hoping there is another way to do it. Thanks.

Identify contact without using Tracker.Current.Session.Identify()

  • What is the purpose of checking to see if the contact is locked, if you don't want to lock the contact yourself? It sounds like you're trying to reuse an existing lock. That isn't possible, because the contact repository does not currently support concurrent edits. I think you want to release the contact. – Adam Conn Apr 14 '17 at 23:22
  • The reason is that we could get an update from the CRM sent to Sitecore at the same time a contact is in session (being updated on the site). So we save the update from the CRM in a separate collection and then run DEF to take that list and go through the contact list and update/merge the contacts. If the contact is locked though (still in session has a lease value) we don't want to update yet. Hope that makes sense. – RReilley Apr 14 '17 at 23:50
  • I don't understand what the problem is. If the contact is locked, you don't want to update. So if you cannot get the lock, you know to abort the attempt to update. If you're concerned about the 1 minute that you would have an active lock, after you lock the contact, release it. – Adam Conn Apr 14 '17 at 23:56
  • That is what I what I am doing actually. :) I just wanted to know if there is a way to check the lock status without attempting to lock it. If a contact is locked I get the already locked status so I don't do the update. If I don't get that status and the contact is locked I release it and do the update. – RReilley Apr 15 '17 at 0:02
  • In that case, see my answer... – Adam Conn Apr 15 '17 at 0:03
0

No. There is no way to do this with Sitecore 8.2 or earlier.

|improve this answer|||||
  • 1
    While correct, just a few lines of explanation as to why, would be helpful – Mark Cassidy Apr 15 '17 at 10:19
  • Sorry Mark. I was being a bit flippant with my response. FWIW, the comments​ on the original question give a thorough explanation of why you can't do it and of the alternative. – Adam Conn Apr 15 '17 at 18:59
2

Direct query approach

You can check whether a contact is locked using a direct MongoDB query. Keep in mind that the way contacts are locked may be changed in the future versions of Sitecore. The code below has been tested on Sitecore 8.1 and 8.2

bool IsContactLocked(Guid contactId)
{
    MongoDbDriver driver = MongoDbDriver.FromConnectionString("analytics");

    long count = driver.Contacts.Count(
        Query.And(
            Query.EQ("_id", contactId),
            Query.GT("Lease.ExpirationTime", DateTime.UtcNow)));

    return count > 0;
}

Here's how to use the method:

Guid contactId = new Guid("54A0D46A-A843-42BC-B62B-9F947167FD65");

if (IsContactLocked(contactId))
{
    // ... postpone your contact update
}

Proper approach

You should still use the ContactRepository.TryLoadContact() API. Based on your comments, I can see you want to check whether a contact is unlocked, and only then schedule an update operation. The thing is, your code is running in a multithreading/multiprocess environment. So even if you make sure the contact is free with the code above, once the scheduled job starts, the contact may become locked by that time.

The concurrency-aware approach here is for the scheduled job to try to lock the contact. If it succeeds, it will know for sure it can update the contact. If the lock attempt fails, the job should just reschedule itself.

This way you'll use the standard Sitecore API, and when you think about it, this approach won't be any slower compared to the direct query approach above.

|improve this answer|||||
  • Thanks Dmytro. I thought about using a query. I will take a look at this approach. We use email as the contactid, but I think it should work the same. – RReilley Apr 17 '17 at 2:13
  • 1
    @RReilley Actually, you're using emails as contact identifiers, not as contactId. If you want to check contact locks by identifier/email, that's not as straightforward. You can check for Identifiers.Identifier in the MongoDB query instead of _id, but keep in mind that contacts can even be loaded by previous identifiers. See the private method MongoDbDataAdapterProvider.TryLoadIdentifier() to see how that works. – Dmytro Shevchenko Apr 19 '17 at 19:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.