0

Im getting the following error:

caused by: System.QueryException: Record Currently Unavailable: The record you are attempting to edit, or one of its related records, is currently being modified by another user. Please try again.

This happens on the first line of the calculatePAKPIOnSoldprotocol method which is called by the calculatePAKPIOnSoldprotocolAsync future method.

I understand this is a locking issue.

  1. Calling an apex class from a future method I suppose the context still future right?
  2. Do I need to remove the FOR UPDATE since its interfering with another for FOR UPDATE or am I missing something else?
if(!protocolIds.isEmpty()) {
    if (System.isFuture() || System.isBatch()) {
        calculatePAKPIOnSoldprotocol(protocolIds);
    }
    else {
        calculatePAKPIOnSoldprotocolAsync(protocolIds);
    }
} 
@future
private static void calculatePAKPIOnSoldprotocolAsync(Set<Id> scopeIds) {
    calculatePAKPIOnSoldprotocol(scopeIds);
}

private static void calculatePAKPIOnSoldprotocol(Set<Id> scopeIds) {
    List<Sold_protocols__c> scope = [SELECT Id, TNT_Nr_proposed_Pas_Applications__c, TNT_Total_Pas_Application_on_protocol__c, (SELECT Id, cxsrec__Status__c FROM Pas_Applications__r) FROM Sold_protocols__c WHERE Id IN: scopeIds FOR UPDATE];
    Map<String,Integer> packPACountMap = new Map<String,Integer>();
    Map<String,Integer> packPAProposedMap = new Map<String,Integer>();
    UpdateCounterKPIprotocol.calculateProposedAndCount(packPACountMap, packPAProposedMap, scope);
    
    List<Sold_protocols__c> spToUpdate = new List<Sold_protocols__c>();
    for (Sold_protocols__c pack : scope){
        if(pack.TNT_Nr_proposed_Pas_Applications__c != packPAProposedMap.get(pack.Id) || pack.TNT_Total_Pas_Application_on_protocol__c != packPACountMap.get(pack.Id)) {
            pack.TNT_Nr_proposed_Pas_Applications__c = packPAProposedMap.get(pack.Id);
            pack.TNT_Total_Pas_Application_on_protocol__c = packPACountMap.get(pack.Id);
            spToUpdate.add(pack);
        }
    }
    if(!spToUpdate.isEmpty())
        update spToUpdate;
}
3
  • As for Q1 - Yes, still in async context. Note that if the UpdateCounterKPIprotocol does a callout, the For Update lock is released and needs to be re-acquired. Switch the future to queueable and if you get the error, chain a new queueable
    – cropredy
    Commented Mar 25 at 16:59
  • @cropredy Thank you. Please add this as an answer.
    – Thomas
    Commented Mar 26 at 10:38
  • Thomas -- so there is a callout involved between the SELECT FOR UPDATE and the update DML statement?
    – cropredy
    Commented Mar 26 at 15:59

1 Answer 1

0

This has been resolved by removing the OR UPDATE from the SOQL.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .