SFDO-Community / declarative-lookup-rollup-summaries

Declarative Lookup Rollup Summaries (DLRS) is a community built and maintained Salesforce application that allows you to create cross object roll-ups declaratively - no code! For install instructions and documentation, visit our website https://sfdo-community-sprints.github.io/DLRS-Documentation/
https://sfdo-community-sprints.github.io/DLRS-Documentation/
BSD 3-Clause "New" or "Revised" License
690 stars 235 forks source link

dlrs_TaskTrigger: execution of AfterInsert caused by: System.DmlException: Upsert failed. First exception on row 0; first error: UNABLE_TO_LOCK_ROW #788

Open kkorynta opened 5 years ago

kkorynta commented 5 years ago

Hi Team!

I've been trying to figure out the best way to handle this UNABLE_TO_LOCK_ROW error and have looked over your forums, but I think our use case is different than the other threads since we're not using bulk API nor do we want to remove this dlrs.

Our users, when trying to send an email from a chatter publisher action, are intermittently hitting this error:

Apex script unhandled trigger exception by user/organization: 00515000007h7fV/00D15000000FTXQ

dlrs_TaskTrigger: execution of AfterInsert

caused by: System.DmlException: Upsert failed. First exception on row 0; first error: UNABLE_TO_LOCK_ROW, unable to obtain exclusive access to this record or 1 records: a0D1500000R03quEAB: []

Class.dlrs.RollupService.updateMasterRollupsTrigger: line 1023, column 1
Class.dlrs.RollupService.handleRollups: line 919, column 1
Class.dlrs.RollupService.triggerHandler: line 311, column 1
Trigger.dlrs_TaskTrigger: line 12, column 1

They can get around it by reloading the page and trying again. However, I know they're hitting it frequently based on the number of errors coming to my email.

  1. We have two triggers on the task object: the dlrs one and our internal one. Our internal trigger only has one singular apex class that runs before delete to prevent a user from removing a task record. We do have a few things going on at the case level once the case is updated, but nothing that should immediately fire when this field in the dlrs is updated.

  2. We only have one dlrs config on the task. It's scheduled for real-time (and must remain real-time because it drives our service rep queue priority). We have a filter so that it is only supposed to run when tasks are of a TaskSubtype of Call. (Which is another reason why I'm confused emails being examined in this dlrs and attempting to update the case).

Any advice on what to look for or what to tweak? Again, we need to keep this at real-time. If I need to create some internal custom code, so be it. I just thought it wouldn't hurt to ask.

Here's the metadata record for this: 2019-02-05_14-46-58

And a screenshot of the record that's being referred to in the error: 2019-04-03_11-01-37

kkorynta commented 5 years ago

Perhaps what I need to do is switch this to developer mode and merge it with my current trigger framework? I looked around for some documentation on a few examples of Developer mode and the syntax needed to call it from our own custom triggers. Can I rip the current stuff right off the example from the manage child trigger page?

DMB28th commented 5 years ago

We're getting the same issue. @kkorynta Did you end up finding a fix for this?

horzel commented 5 years ago

Looking at the error detail from OP, the id of the record concerned is: a0D1500000R03quEAB

Which is not a Task, but a custom object record?

For OP, my question would be which object represents a0D?

For DMB28th, what kind of id is mentioned in your scenario?

kkorynta commented 5 years ago

@horzel The prefix a0D in our org is pointed to the dlrsLookupRollupSummaryc object, which is what makes this error tricky to manage.

Also, I've since merged the two triggers, which has cut down on the number of errors significantly, but has not eliminated the issue completely. Here's a more recnet error from this morning.


TaskTrigger: execution of AfterInsert

caused by: System.DmlException: Upsert failed. First exception on row 0; first error: UNABLE_TO_LOCK_ROW, unable to obtain exclusive access to this record or 1 records: a0D1C00000TYVEKUA5: []

Class.dlrs.RollupService.updateMasterRollupsTrigger: line 1023, column 1
Class.dlrs.RollupService.handleRollups: line 919, column 1
Class.dlrs.RollupService.triggerHandler: line 311, column 1
Class.TaskTriggerDispatcher.afterInsert: line 50, column 1
Class.TriggerHandler.run: line 44, column 1
Trigger.TaskTrigger: line 5, column 1

I've updated the original post to include a screenshot of the record.

DMB28th commented 5 years ago

@horzel Thanks for following up!

the id mentioned in my scenario is an account id but it's rolling up information from a Task. Here is my error

`Apex script unhandled trigger exception by user/organization: 0050y00000D7WoJ/00D80000000KtFf

dlrs_TaskTrigger: execution of AfterInsert

caused by: System.DmlException: Update failed. First exception on row 0 with id 0010y00001ZAYxuAAH; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, Please fill in the Acct Demo Booked and Acct Demo Type fields: []

Class.dlrs.RollupService.Updater.updateRecords: line 1315, column 1 Class.dlrs.RollupService.UpdateWithoutSharing.updateRecords: line 1358, column 1 Class.dlrs.RollupService.updateRecords: line 1286, column 1 Class.dlrs.RollupService.handleRollups: line 918, column 1 Class.dlrs.RollupService.triggerHandler: line 311, column 1 Trigger.dlrs_TaskTrigger: line 7, column 1`

horzel commented 5 years ago

caused by: System.DmlException: Update failed. First exception on row 0 with id 0010y00001ZAYxuAAH; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, Please fill in the Acct Demo Booked and Acct Demo Type fields: []

Not only is it mentioning an account, it is also mentioning a different error, it does not concern a row locking error.

For your scenario, I take it you are rolling up information from the Tasks to the Account? That means the Account is being updated, but a validation rule prevents this, as some fields are not populated.

You would need to either make sure all Accounts have these fields populated, before you start using the roll ups, or you would need to adjust the validation to not fire if only the fields with the roll up results are updated on the account.

horzel commented 5 years ago

@kkorynta Regarding your issue, I am not that deep into this package yet, but looking at your screenshot for the referenced record 'Tasks This Month', is that roll up defined correct? I do not see much info in there?

You might need to check on that roll up instead of the Total Case Calls roll up.

kkorynta commented 5 years ago

@horzel This record was auto created by the system after I converted the settings to the new metadata format. When I reached out to the SFDC community group (Declarative Lookup Rollup Summaries Tool), I was told this was expected behavior when using the metadata setup as opposed to the custom object setup because the scheduled items needed a place to be housed.

horzel commented 5 years ago

Okay, I would not know how to help further, sorry. The UNABLE_TO_LOCK_ROW, is caused by it being accessed at the same time by multiple actions.

kkorynta commented 5 years ago

Right, that's why I'm here. The only processes that would access that dlrsLookupRollupSummaryc record in our org are those in the dlrs package.

kkorynta commented 5 years ago

Will this issue be prioritized? is there any additional information I can provide?

JimBTek commented 5 years ago

Hey There, I help maintain DLRS. I do not think this is necessarily a DLRS specific bug/issue to be fixed. It is as people have said likely something with your configuration and multiple actions blocking each other. DLRS won't trip over itself blocking itself from editing a record. UNABLE TO LOCK ROW, is always something else is editing the same record at the same time.

You could quickly "bandaid" this by changing from realtime to process builder, and using a scheduled action that has a 0 hours delay, or using scheduled mode and running jobs to update it.

Other than that, you can certainly incorporate the DLRS trigger code into your own trigger, and disable the DLRS trigger, to help control your order of operations.

Trying to roll up Tasks onto Cases is certainly a tricky scenario since the volume of tasks is so large and the relationship WhatId is polymorphic.

You should turn on debugging and run this again, it will tell you want all is running at the same time that is trying to edit the same record.

JimBTek commented 5 years ago

@kkorynta why don't you delete that DLRS record that the row lock is happening on? it's odd to have a DLRS with a bunch of N/A typed into it like that.

kkorynta commented 5 years ago

I’ve tried to delete it before, the package just ends up recreating another record like it. No other process is accessing dlrs records except for this package.

The dlrs triggers were already merged into our existing framework for several objects and we’re still having the issue, albeit less frequently. We cannot switch the calculation to a process builder or to scheduled since our support processes rely on this calculation being real-time currently. If anything, i’d Have to convert the real-time ones to our own code and rip this package out. That’s a hefty project to convert everything and i’d like to avoid it.

Also, I’m reaching out again because it’s a similar issue on our email message object, which removes the polymorphic id issue.

I can pull some logs. It might take me a day or two because this is an intermittent problem and there’s a lot on my plate at work. If I can show that it’s the dlrs roll up service causing the issue, who should I reach out to?

Thanks, Kelly

On Mon, Jul 15, 2019 at 2:26 PM Jim Bartek notifications@github.com wrote:

@kkorynta https://github.com/kkorynta why don't you delete that DLRS record that the row lock is happening on? it's odd to have a DLRS with a bunch of N/A typed into it like that.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/afawcett/declarative-lookup-rollup-summaries/issues/788?email_source=notifications&email_token=AE57YJFO6FUKYFNVQAV5VR3P7S6NPA5CNFSM4GUP5KJ2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODZ6R4LQ#issuecomment-511516206, or mute the thread https://github.com/notifications/unsubscribe-auth/AE57YJHDR5PNKCT4KM2SPPDP7S6NPANCNFSM4GUP5KJQ .

JimBTek commented 5 years ago

Kelly, OK thanks for the details. Let me know if you can produce some logs showing what is going on. I can discuss with Andy and see if we can pinpoint a bug in the product, however there are thousands of orgs using DLRS.

Along with the debug logs:

Also, you said "when trying to send an email from a chatter publisher action":

Again even with a Process Builder you can get it to run near instantaneous, like a Future method. Or you might be able to move the DLRS trigger call into your trigger wrapped in a future.

kkorynta commented 5 years ago

Hey Jim,

We are currently using version 2.11.1.

In regards to the task trigger, yes, sort of. Originally when I started at this company, they had two triggers on the task object - the dlrs one and an internal one. I've removed the dlrs one and merged it into our trigger framework. If it's ok, I'd like to focus on the EmailMessage dlrs trigger. I'm getting the same error message, but this has a much bigger impact on our org as it affects inbound emails. I've provided the trigger code at the bottom and its dispatcher.

Here is the error message:

CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY : EmailMessageTrigger: execution of AfterInsert

caused by: System.DmlException: Upsert failed. First exception on row 0; first error: UNABLE_TO_LOCK_ROW, unable to obtain exclusive access to this record or 1 records: a0D1C00000TYVEeUAP: []

Class.dlrs.RollupService.updateMasterRollupsTrigger: line 1026, column 1
Class.dlrs.RollupService.handleRollups: line 922, column 1
Class.dlrs.RollupService.triggerHandler: line 311, column 1
Class.EmailMessageTriggerDispatcher.afterInsert: line 55, column 1
Class.TriggerHandler.run: line 44, column 1
Trigger.EmailMessageTrigger: line 5, column 1

Here's what that record Id looks like when I pull it up - note it's not active and we don't have a matching metadata config that matches either. Mr. Rodriguez is also not a system administrator and does not have access to the dlrs app or its objects. 2019-07-15_17-59-22

As far as what roll ups we have for the email message object as the child, we currently have three. They are all configured under the metadata side of things and are all System Calculation + realtime. One counts the total number of emails, one for inbound, and the other for outbound. They all aggregate up to the case object.

Metadata configs 2019-07-15_18-02-40

dlrs configs 2019-07-15_18-03-35

As mentioned, I'll work on getting those logs. It's going to take a little bit of coordination as I'm not the support process owner, so I don't receive the errors directly. I do have the logs set up and will get a sample for you within 2 days.

Thanks, Kelly

trigger EmailMessageTrigger on EmailMessage (before insert, before update, before delete, after insert, after update, after delete, after undelete) {
    Map<String, Trigger_Settings__c> triggerSettings = Trigger_Settings__c.getAll();

    if(triggerSettings.get('EmailMessageTrigger') <> null && triggerSettings.get('EmailMessageTrigger').Execute_Trigger__c)
        new EmailMessageTriggerDispatcher().run();
}
public without sharing class EmailMessageTriggerDispatcher extends TriggerHandler {
    //Trigger context variables are still available but need to be cast: trigger.new, trigger.newMap, trigger.oldMap
    List<EmailMessage> emailMessages = (List<EmailMessage>) trigger.new;
    Map<Id, EmailMessage> emailMessageOldMap = (Map<Id, EmailMessage>) trigger.oldMap;
    Map<Id, EmailMessage> emailMessageNewMap = (Map<Id, EmailMessage>) trigger.newMap;
    Map<String, Trigger_Settings__c> triggerSettings = Trigger_Settings__c.getAll();

    protected override void beforeInsert() {
        //declare variables
        //loop through to find qualifying records
        //execute methods
        if(!TriggerHandler.isBypassed('BI-dlrs_EmailMessageTrigger') && triggerSettings.get('dlrs_EmailMessageTrigger') <> null && triggerSettings.get('dlrs_EmailMessageTrigger').Execute_Trigger__c) {
            TriggerHandler.bypass('BI-dlrs_EmailMessageTrigger');
            dlrs.RollupService.triggerHandler(EmailMessage.SObjectType);
        }
    }

    protected override void beforeUpdate() {
        //declare variables
        //loop through to find qualifying records
        //execute methods
        if(!TriggerHandler.isBypassed('BU-dlrs_EmailMessageTrigger') && triggerSettings.get('dlrs_EmailMessageTrigger') <> null && triggerSettings.get('dlrs_EmailMessageTrigger').Execute_Trigger__c) {
            TriggerHandler.bypass('BU-dlrs_EmailMessageTrigger');
            dlrs.RollupService.triggerHandler(EmailMessage.SObjectType);
        }
    }

    protected override void beforeDelete() {
        //declare variables
        //loop through to find qualifying records
        //execute methods
        //if(!emailMessageOldMap.isEmpty() && !TriggerHandler.isBypassed('PreventDeleteHandler') && triggerSettings.get('PreventDeleteHandler') <> null && triggerSettings.get('PreventDeleteHandler').Execute_Trigger__c) {
        //    TriggerHandler.bypass('PreventDeleteHandler');
        if(!emailMessageOldMap.isEmpty() && triggerSettings.get('PreventDeleteHandler') <> null && triggerSettings.get('PreventDeleteHandler').Execute_Trigger__c) {
            PreventDeleteHandler.preventDelete(emailMessageOldMap.values());
        }

        if(!TriggerHandler.isBypassed('BD-dlrs_EmailMessageTrigger') && triggerSettings.get('dlrs_EmailMessageTrigger') <> null && triggerSettings.get('dlrs_EmailMessageTrigger').Execute_Trigger__c) {
            TriggerHandler.bypass('BD-dlrs_EmailMessageTrigger');
            dlrs.RollupService.triggerHandler(EmailMessage.SObjectType);
        }
    }

    protected override void afterInsert() {
        //declare variables
        //loop through to find qualifying records
        //execute methods
        if(!emailMessages.isEmpty() && !TriggerHandler.isBypassed('CaseCloneHandler') && triggerSettings.get('CaseCloneHandler') <> null && triggerSettings.get('CaseCloneHandler').Execute_Trigger__c) {
                TriggerHandler.bypass('CaseCloneHandler');
                CaseCloneHandler.processEmailMessages(emailMessages);
        }

        if(!TriggerHandler.isBypassed('AI-dlrs_EmailMessageTrigger') && triggerSettings.get('dlrs_EmailMessageTrigger') <> null && triggerSettings.get('dlrs_EmailMessageTrigger').Execute_Trigger__c) {
            TriggerHandler.bypass('AI-dlrs_EmailMessageTrigger');
            dlrs.RollupService.triggerHandler(EmailMessage.SObjectType);
        }
    }

    protected override void afterUpdate() {
        //declare variables
        //loop through to find qualifying records
        //execute methods
        if(!TriggerHandler.isBypassed('AU-dlrs_EmailMessageTrigger') && triggerSettings.get('dlrs_EmailMessageTrigger') <> null && triggerSettings.get('dlrs_EmailMessageTrigger').Execute_Trigger__c) {
            TriggerHandler.bypass('AU-dlrs_EmailMessageTrigger');
            dlrs.RollupService.triggerHandler(EmailMessage.SObjectType);
        }
    }

    protected override void afterDelete() {
        //declare variables
        //loop through to find qualifying records
        //execute methods
        if(!TriggerHandler.isBypassed('AD-dlrs_EmailMessageTrigger') && triggerSettings.get('dlrs_EmailMessageTrigger') <> null && triggerSettings.get('dlrs_EmailMessageTrigger').Execute_Trigger__c) {
            TriggerHandler.bypass('AD-dlrs_EmailMessageTrigger');
            dlrs.RollupService.triggerHandler(EmailMessage.SObjectType);
        }
    }

    protected override void afterUndelete() {
        //declare variables
        //loop through to find qualifying records
        //execute methods
        if(!TriggerHandler.isBypassed('AUD-dlrs_EmailMessageTrigger') && triggerSettings.get('dlrs_EmailMessageTrigger') <> null && triggerSettings.get('dlrs_EmailMessageTrigger').Execute_Trigger__c) {
            TriggerHandler.bypass('AUD-dlrs_EmailMessageTrigger');
            dlrs.RollupService.triggerHandler(EmailMessage.SObjectType);
        }
    }
}
JimBTek commented 5 years ago

I am not sure why you have Scheduled Items when it is realtime. Are those old records?

But i think the main culprit is you call DLRS in both BEFORE INSERT and AFTER INSERT, so you are calling it twice in the same transaction. You should put comments in there so you can see in the logs if it succeeded the first time, and then failed in the after insert.

kkorynta commented 5 years ago

It's likely an old record, but it doesn't make sense why current transactions are referencing it.

I'm calling dlrs in both the before insert and after insert as that's what the auto generated apex trigger references. Happy to adjust it if we're certain that's the culprit.

/**
 * Auto Generated and Deployed by the Declarative Lookup Rollup Summaries Tool package (dlrs)
 **/
trigger dlrs_EmailMessageTrigger on EmailMessage
    (before delete, before insert, before update, after delete, after insert, after undelete, after update)
{
    dlrs.RollupService.triggerHandler(EmailMessage.SObjectType);
}
JimBTek commented 5 years ago

Yeah you are right, no processing is done in the before phase anyways: https://github.com/afawcett/declarative-lookup-rollup-summaries/blob/master/force-app/main/classes/RollupService.cls

I think debug logs are the next step, specifically seeing what is trying to touch that record.

I would also try clearing out all that old scheduled items, as when it runs it may being trying to process those as well.

BTekVentures.com

On Tue, Jul 16, 2019 at 8:02 AM kkorynta notifications@github.com wrote:

It's likely an old record, but it doesn't make sense why current transactions are referencing it.

I'm calling dlrs in both the before insert and after insert as that's what the default apex class references. Happy to adjust it if we're certain that's the culprit.

/**

  • Auto Generated and Deployed by the Declarative Lookup Rollup Summaries Tool package (dlrs)
  • Deactivated as it's been merged into the core trigger framework **/ trigger dlrs_EmailMessageTrigger on EmailMessage (before delete, before insert, before update, after delete, after insert, after undelete, after update) { dlrs.RollupService.triggerHandler(EmailMessage.SObjectType); }

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/afawcett/declarative-lookup-rollup-summaries/issues/788?email_source=notifications&email_token=AAI7GG2MPFFPUQOSVW3GDATP7W2DRA5CNFSM4GUP5KJ2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD2AT4XI#issuecomment-511786589, or mute the thread https://github.com/notifications/unsubscribe-auth/AAI7GG77GK6FVQATUOAOFQTP7W2DRANCNFSM4GUP5KJQ .

kkorynta commented 5 years ago

Hey Jim - still working with Salesforce support on getting the logs and vetting the information that they're telling us. I'll be sure to update you as soon as I know more.

JimBTek commented 5 years ago

@kkorynta you can simply turn on Debug Logs in Salesforce, and then go cause the error to happen to capture a log

kkorynta commented 5 years ago

Yep, I know how to run a debug log. The problem is, I'm getting logs like this on full detail, which is why I've involved salesforce support to take a look at server side logs and see if they can make heads or tails of what's going on.

apex-07L1C00004zgKFzUAM.log

JimBTek commented 5 years ago

Cool, FYI that log has some Identifiable info in the email.

I notice the entire log is only running BeforeInsert. While the trigger passes Before context to the TriggerHandler for DLRS, it does nothing in the Before context:

https://github.com/afawcett/declarative-lookup-rollup-summaries/blob/master/force-app/main/classes/RollupService.cls

Your original log shows an AfterInsert error.

The parent Case is already getting updated by the fact of the Email getting Attached to it, and you are trying to also have DLRS update the same case at the same time. Also you are running CaseCloneHandler.processEmailMessages(emailMessages); at the same time.

Are you able to reproduce it when bypassing CaseCloneHandler?

afawcett commented 4 years ago

So .... for Schedule Mode triggers there is (in the current release) a master-detail relationship between LookupRollupSummaryScheduleItemsc and LookupRollupSummaryc. This means a lock scenario can occur under high concurrent load. If locking is due to this it can be confirmed by checking the ID in the error message and relating it back to the source object. I noticed at least one reference to this being the case in the thread above. Good news.... the code in master (yet to be release in package form) removes this master detail relationship..... and also those pesky shadow rollup records in the custom object for those using custom metadata objects only. There is a packaging complication getting this change I need to work through to get a feature enabled with Salesforce. I'll work to get these changes and others out in a new release asap!

kkorynta commented 4 years ago

Thanks Andrew - hoping to see that the fix will improve our issues.

@JimBTek - As far as your question, we're not able to bypass the CaseCloneHandler as that's a critical piece of code we use to support our clients. Basically, if an inbound email comes in and attaches to a closed case, we clone that email into a new case so our support team can properly handle it.

In general, with the dispatchers, I have set dlrs to run at the end of all of the executing methods. Hopefully, it shouldn't be running at the same time, but there could be something asynchronous occuring in the transaction because dlrs is being called for all DML events.

As far as the investiagation with salesforce has gone, we've engaged their CATT team due to numerous issues with performance in the lightning platform. Now that we're past most of the javascript based issues with lightning, they're poking into server slowness. They identified that a lot of the slowness we're receiving server side is coming from how heavy we use dlrs. Recently, we did start running into governor limits with concurrent processing as we were attempting to execute an archive process (deleting email messages). The logs from salesforce point back to high trigger CPU run-time, which lines up with the information the CATT team has provided us.

Internally, we're going to see if some of the jobs can be removed/deactivated so there's not as much running. However, salesforce has said that what ever the fix is that Andrew is planning, it should greatly improve our server side processing. Fingers crossed it resolves a lot of the row locking issues as we're still having issues with this in various parts of our application.

KalmanS commented 4 years ago

@JimBTek @afawcett - Thanks for the info here. We too are running into these errors at bulk loading. We have a lot hitting Campaign Member records and users are importing lists via Apsona and getting these errors often with bulk loads. I just got 1,600 errors from 31k records loaded.

"Rejected: Salesforce said: dlrs_CampaignMemberTrigger: execution of AfterInsert
caused by: System.DmlException: Upsert failed. First exception on row 200; first error: UNABLE_TO_LOCK_ROW, unable to obtain exclusive access to this record or 1 records: a1Gf4000006vhpZEAQ: []
Class.dlrs.RollupService.updateMasterRollupsTrigger: line 1023, column 1
Class.dlrs.RollupService.handleRollups: line 919, column 1
Class.dlrs.RollupService.triggerHandler: line 311, column 1
Trigger.dlrs_CampaignMemberTrigger: line 7, column 1"

I have all (5) jobs scheduled at 2am,230am,3am,330am, and 4am. They are also creating new Lookup Rollup Summary records with thousands of child records. I mass deleted all the child records but the app is creating them over and over again. The creator (of who created those add'l records) are not me and the users (of course) are not aware of triggering it.

In terms of operation - If my schedule is not currently happening - are the records getting queued at create? Trying to unpack this. Thanks!

shnavita commented 4 years ago

So .... for Schedule Mode triggers there is (in the current release) a master-detail relationship between LookupRollupSummaryScheduleItemsc and LookupRollupSummaryc. This means a lock scenario can occur under high concurrent load. If locking is due to this it can be confirmed by checking the ID in the error message and relating it back to the source object. I noticed at least one reference to this being the case in the thread above. Good news.... the code in master (yet to be release in package form) removes this master detail relationship..... and also those pesky shadow rollup records in the custom object for those using custom metadata objects only. There is a packaging complication getting this change I need to work through to get a feature enabled with Salesforce. I'll work to get these changes and others out in a new release asap!

Hello @afawcett , Hope you are doing good. I recently started using DLRS package and faced Lock Issue on DLRS Objects for scheduled mode. Is there any estimated timeline for release of this fix in the package?

  1. All RUS fields are defined in Scheduled Mode.
  2. These custom objects gets synchronized by offline Mobile app and hence there can be scenarios for concurrent update. Since CPU timeout limit was the concern , I opted the approach for Schedule (batch calculation only), but this gives Lock issues intermittently.

Do you suggest any alternative if fix is not coming in package version soon? Thanks in advance for your reply. Navita

Martinch713 commented 4 years ago

@afawcett Hey Andrew, I work with the OP. Is this resolved in the most recent update? I'm not seeing this in the release notes, though I see you were hoping to have this released per your comment last year.

afawcett commented 4 years ago

@Martinch713 yeah if you are talking about my comment here https://github.com/afawcett/declarative-lookup-rollup-summaries/issues/788#issuecomment-570104597. Then yes the latest release includes those changes. Can you retest?

Martinch713 commented 4 years ago

@Martinch713 yeah if you are talking about my comment here #788 (comment). Then yes the latest release includes those changes. Can you retest?

I've finally been able to update and test and we're still getting the Unable to Lock Row error.

afawcett commented 4 years ago

@Martinch713 can you confirm that you have completed all the post install steps for the latest release?

kkorynta commented 4 years ago

Hi @afawcett - We did recently complete the post install steps for the latest release. We are still getting some lock row issues, but not nearly as frequently. They do seem to 'retry' the record and clear out the next time the RollupJob runs.

Error: Delete failed. First exception on row 82 with id a0C1C00001gtAsrUAE; first error: UNABLE_TO_LOCK_ROW, unable to obtain exclusive access to this record or 1 records: a0C1C00001gtAsrUAE: []. Review Rollup Summary Schedule Items a0C1C00001gtAtZUAU,a0C1C00001gtAtYUAU,a0C1C00001gtAtXUAU,a0C1C00001gtAtWUAU,a0C1C00001gtAtVUAU,a0C1C00001gtAtUUAU,a0C1C00001gtAtTUAU,..... [omitted for brevity]

The only other odd issues that come up are: Upsert failed. First exception on row 0; first error: DUPLICATE_VALUE, duplicate value found: dlrs__QualifiedParentID__c duplicates value on record with id: a0C1C00001hXzRt: []

and

Failed to process batch for class 'dlrs.RollupJob' for job id '7071C0000B6AuvQ' caused by: System.LimitException: dlrs:Too many query rows: 50001

The query rows I have an idea for a record blacklist that might fix the issue of the scheduled item from being created in the first place. The duplicate value, I'm not sure what's going on with this since the a0C record is the Scheduled Item object and would be managed by the code.

kemacdougall96 commented 1 year ago

Hi @afawcett and @JimBTek,

I have just updated my org's dlrs package to the newest release. In doing so, we deployed the case child trigger because we are transitioning to a scheduled system instead of a scheduled full calculate. Currently, I have the RollUpJob scheduled to run at 9AM, 12 PM, 3 PM, and 6PM. There were no issues with this until a scheduled triggered flow attempted to run and failed, producing the following errors:

"The flow tried to update these records: 5004x00000Dw0A5AAJ. This error occurred: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY: dlrs_CaseTrigger: execution of AfterUpdate caused by: System.DmlException: Upsert failed. First exception on row 0; first error: UNABLE_TO_LOCK_ROW, unable to obtain exclusive access to this record: [] (dlrs) Trigger.dlrs_CaseTrigger: line 7, column"

and

"Error element Update_Status_Code (FlowRecordUpdate). The flow tried to update these records: 5004x00000HeQGsAAN. This error occurred: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY: dlrs_CaseTrigger: execution of AfterUpdate caused by: System.DmlException: Upsert failed. First exception on row 1; first error: DUPLICATE_VALUE, duplicate value found: dlrsQualifiedParentIDc duplicates value on record with id: a1bQP0000000MW1YAM: [] (dlrs) Trigger.dlrs_CaseTrigger: line 7, column 1. "

The scheduled triggered flow runs daily at 1:15 AM to check if a formula field is evaluated to true. The formula field is set to only evaluate to true on the 15th of every month. When it does, it updates a Case record's status and associated status code to "Successful".

Our dlrs field is on the Case level rolling up to the Account. It evaluates the MIN of a formula field that ranks a Case based on its status. When its ranking moves up, this Case is populated in the dlrs field at the Account level. The status "Successful" is the highest ranking case at 1. So each of these case updates impact what the dlrs field will change to on the Account level.

I'm posting here because these errors are very similar to the ones listed above. What would be next steps in trying to resolve this? Thanks!

aheber commented 1 year ago

@kemacdougall96 I think it would be best to treat this as an independent issue. I'll provide some level of guidance but I think you'd be best to start in the Trailblazer Community Group for DLRS looking for help resolving these errors.

These errors don't necessarily indicate a problem with DLRS but more a conflict between running processing. Figuring out where and how that conflict is occurring can be difficult, deciding what to do about it is another layer of difficulty.

"UNABLE_TO_LOCK_ROW" is something using SOQL to request a record FOR UPDATE, or essentially calling "dibs" on that record until it is done. There are a few other ways "locks" in the database can be requested but it is a mechanism to say "I'm going to change the record, nobody else change the record until I'm done"

In your first example I would have expected a set of record IDs. "While updating the User with ID 5004x00000Dw0A5AAJ we were unable to lock record..." but the values are blank. So something on the Case trigger was seemingly trying to rollup a value to the User record and that process failed.

I can tell you that DLRS attempts to lock parent User records when it is updating values. (https://github.com/SFDO-Community/declarative-lookup-rollup-summaries/blob/02752a724ac2063fab16ef399270e2c241bb6e44/dlrs/main/classes/RollupService.cls#L686) but I don't know why it is limited to User records. I'd have to dig through more history to figure that out. Is it possible that multiple concurrent case updates are trying to write to the same User record at the same time and this is causing the record contention?

As for your second error, this is similar and we actually have another open issue more closely related to this. You have a rollup configured in Scheduled mode so when DLRS notice a change it tries to write Scheduled Item records to the database using Upsert. Something about that process seemed to having a timing or visibility issue and the Upsert command tried to create a new record but failed because there is already an existing record holding the same dlrs__QualifiedParentID__c value. I haven't been able to replicate this issue on demand for testing but I have some guesses as to how we can handle it better. I believe it is caused by concurrent edits, very similar to the above just a different action in the code.

It seems both of your problems are likely concurrent edits, likely caused by batch updates in your Flow. You will need to try and figure out how to order records better or how to handle the batch updates so they can manage this situation better.

I'm hoping to be able to replicate and work on a fix eventually for your second issue but the first issue is likely not something DLRS can eventually be smart enough to make go away. It will be more of an issue in your environment and your concurrent edits conflicting because they want to update the same record at the same time.

A lot of this is conjecture on my part and I'm sorry if I'm missing the point or overlooked some aspect of your specific issues. Right now the best thing to do is see that the root cause is concurrency and try and figure out how to manage that aspect of it better.

handisbas commented 6 months ago

Hi , I'm getting the same error. First I received the below error when I bulk-inserted the users as contacts in salesforce. After re-try inserting the contacts, the issue was gone. Now we have Okta salesforce integration, Okta integration creates contacts in salesforce. Last week okta integration tried to create 40 contacts but we received below error. I've researched and this error is related to declarative lookup rollup summary manage tool manage packages, our org using this package since 2019. We can't uninstall this package because we are using it. How we can resolve this error issue? Do you have any idea? Thank you

'' dlrs_ContactTrigger: execution of AfterInsert\n\ncaused by: System.DmlException: Update failed. First exception on row 0 with id 001Qo000009kMurIAE; first error: UNABLE_TO_LOCK_ROW, unable to obtain exclusive access to this record or 1 records: 001Qo000009kMurIAE: []\n\n(dlrs)\nTrigger.dlrs_ContactTrigger: line 7, column 1", "errorCode": "CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY",