Loading

Race condition between Apex code and API Call

Fecha de publicación: Apr 18, 2023
Descripción

In the following apex code, there's a possibility that the assert statement will fail if an API transaction executing in parallel was able to update the LastName. Select statement (with For update) will try to lock the record. But if record is already locked then it'll still select the record but wait for lock to be released (for 10 seconds). If record is released then second transaction will continue. 
 
List<Contact> myContactList = [SELECT Id, LastName FROM Contact where LastName = 'mylast' FOR UPDATE];
for (Contact c : myContactList){
    System.assertEquals('mylast', c.LastName.toLowerCase());
}
Solución
There's a possibility that the assert statement will fail if an API transaction executing in parallel was able to update the LastName. Select statement (with For update) will try to lock the record. But if record is already locked then it will still select the record but wait for lock to be released (for 10 seconds). If record is released then second transaction will continue. 

The locking process returns a fresh copy of the record from the database through the SELECT statement. But it doesn't really run SELECT statement again. It just does it "internally" to refresh the data of record which was already selected in the actual SOQL. So we have to check if the WHERE clause filter is still valid.

 
List<Contact> myContactList = [SELECT Id, LastName FROM Contact where LastName = 'mylast' FOR UPDATE];
for (Contact c : myContactList){
if (c.LastName == 'mylast')
    {System.assertEquals('mylast', c.LastName.toLowerCase());}
}


The behavior is also explained in this document .
Número del artículo de conocimiento

000387467

 
Cargando
Salesforce Help | Article