0

I have below piece of code in web service apex class. If account is found with given emailId then I am updating the account, if account is not found with emailId then I am creating new account record.

global class MyWebServiceClass {
global MyWebServiceClass () {
}  
@TestVisible  
global class GetAccInformation{
    webservice String accNum{get;set;}
    webservice String accName{get;set;}
    webservice String SerialNo{get;set;}
    webservice String Email{get;set;}
}
@TestVisible
global class resultclass {
    webservice string Active{get;set;}
    webservice string ERROR_CODE{get;set;}       
}
webservice static resultclass accountDML(GetAccInformation RetInfo)  {
    resultclass re = new resultclass();
    list<Account> personAccounts = new list<Account>();
    personAccounts = [select id,Name,AccountNumber,SLASerialNumber__c,Email__c from Account where Email__c = :RetInfo.Email limit 1];
    Account acc = new Account();
    if(personAccounts.size() > 0){
        acc.Id = personAccounts[0].Id;
        acc.Name = RetInfo.accName;
        acc.AccountNumber = RetInfo.accNum;
        acc.SLASerialNumber__c = RetInfo.SerialNo;
        update acc;
    }
    else{
        acc.Name = RetInfo.accName;
        acc.AccountNumber = RetInfo.accNum;
        acc.SLASerialNumber__c = RetInfo.SerialNo;
        acc.Email__c = RetInfo.Email;
        insert acc;
    }
    re.Active = 'TRUE';
    return re;
}

}

The problem is - Within 20 seconds if 2 requests are received with same email id then its creating 2 accounts with same email id, as per logic written it should not create new account when second request received with same email id.

When its analysed in depth, its found that - due to some connectivity issue requester(External system) is not getting response hence external system will again attempt by sending same request within 20 seconds. Hence at salesforce end within a span of 20 sec we are getting 2 requests for same inputs and for both requests our webservice is creating 2 account records.

Can somebody help me to understand why my webservice is creating duplicate account for same email id?

1 Answer 1

0

You have a classic race condition.

Let's say you receive two inbound requests with the same email address.

Request A runs the query

select id,Name,AccountNumber,SLASerialNumber__c,Email__c from Account where Email__c = :RetInfo.Email limit 1

and finds nothing. It moves down the logic path to create its Account. Request A is executing in its own transaction (as is always the case in Apex) and will commit to the database when all downstream logic, such as triggers, flows, and workflow rules, complete successfully.

Request B comes in while Request A's transaction is still in progress. This means that the Account created by Request A has not yet committed to the database, and cannot be seen in a SOQL query.

Request B runs the query

select id,Name,AccountNumber,SLASerialNumber__c,Email__c from Account where Email__c = :RetInfo.Email limit 1

and also finds nothing. It proceeds to insert its Account.

This is a race condition because the query/insert structure is not atomic. You don't hold a lock on a record (because it does not yet exist), and hence cannot prevent parallel callers from performing the same action.

There's a variety of potential avenues to explore to try to address this.

  • Reduce the processing time for Account insert transactions by optimizing or making asynchronous some of your processing code. (This doesn't fix race conditions but limits their scope).
  • Change the retry behavior of your remote system.
  • Implement a native uniqueness constraint on the Email__c field, and catch any resulting exceptions when you attempt an insert.

You must log in to answer this question.

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