I recently encountered a business logic bug in our org that was accidentally deducting a customer 2x for completing an event that only actually occurred once. Using dev console I was able to determine that the method was running twice as a result of a Workflow Field Update that caused the transaction to loop through the order of execution a second time. Unchecking the "re-evaluate" box on the workflow rule didn't stop the bug.
So, I went the route of creating a 'RunOnce' style Boolean in a Helper Class, checking if it is false at the start of the method, and then setting it to true as the last line in the entire method (even after DML updates). This of course doesn't stop the record(s) from going through order of execution again, but it does stop the method from running since it already ran.
Example with main business logic removed for size purposes:
public static void updateUsedTrainingTimeUsingEventMaps(Map<Id,Event> oldEventMap, Map<Id,Event> newEventMap){
if(ValidatorClass.UpdateTrainingTimeTriggerFired == false){ // check if this method has run already
for(Event event : newEventMap.values())
{
A BUNCH OF BUSINESS LOGIC, FIELD UPDATES, ADDING TO UPDATE LISTS, ETC
} // end of for loop
update accountMap.values();
ValidatorClass.UpdateTrainingTimeTriggerFired = true; // stop method from running again in same transaction
} // end of updateUsedTrainingTimeUsingEventMaps()
Question: Being that this is my first time doing this, I am unsure of how exactly this effects (if at all), mass updates that trigger this method. I learned recently (in SFDev450 class) that Salesforce handles records in sets of 200 in loops - but I am unsure if that means they also only pass 200 records to the method at once.
Does this mean:
- Each 200 records get their own transaction per 200, and by extension, a fresh reset of the Boolean?
OR
- Will my 201st record not run the method since it's a second set of 200 being run through the method in the same transaction where the Boolean is now true?
OR
- Will all of my records (let's say 405) be sent to the method at the same time but just run through the loops in sets of 200 before doing my final DML update outside of the loop, resulting in all 405 running the method once regardless of how many times subsequent order of executions may start in that transaction?
OR
- None of the above? (Please specify)
Many thanks for your insight!