1

Wonder how Salesforce handles batching records in relation to execution context.

For example, if I have a static variable that tracks the records being processed by a trigger:

trigger MyTrigger on MyObject__c (after insert) {
  Tracker.recordIds.addAll(Trigger.newMap.keySet());
}

public class Tracker{
   public static List<Id> recordIds = new List<Id>();
}

and my TBW updates 10,000 items, will my Tracker.recordIds list hold all 10k at the end of the updates?

  • Shouldn't be it Tracker.recordIds.addAll(Trigger.newMap.KeySet()) ? – Jarvis Feb 4 '16 at 4:11
  • Ya, the code is just more for the conceptual understanding, but I've updated it – NSjonas Feb 4 '16 at 4:57
  • I can pretty much guarantee it won't be ten thousand. Probably 200 at a time, but I'd have to set up a test. – sfdcfox Feb 4 '16 at 5:11
  • @sfdcfox not sure . may be i am wrong but we use static boolean variable to stop recursion . Don't we follow same approach in this case. trigger will run in one onstance and i think will store value. Please correct if am wrong. – Tushar Sharma Feb 4 '16 at 5:21
  • for my purposes I hope @sfdcfox is correct, but was fearing that it might store all the values. I'm trying to prevent trigger recursion across detail records by storing the Master Id. But if details are not processed in the same batch, I want the process on the master record to fire again. – NSjonas Feb 4 '16 at 6:34
1

Salesforce has some limitations around the number of records processed by TBW in an hour. Please find the note below from Salesforce documentation - " Salesforce limits the number of time triggers an organization can execute per hour. If an organization exceeds the limits for its Edition, Salesforce defers the execution of the additional time triggers to the next hour. For example, if an Unlimited Edition organization has 1,200 time triggers scheduled to execute between 4:00 PM and 5:00 PM, Salesforce processes 1,000 time triggers between 4:00 PM and 5:00 PM and the remaining 200 time triggers between 5:00 PM and 6:00 PM."

More details can be found here

We had a similar implementation to update a record via TBW and then trigger a call out to external system after the records were updated but as we figured there is a limitation we preferred to write our own custom logic.

So I think your static variable can have a maximum value of 1000 but not more than that.So if you want to keep track of the count, I would recommend, create a Custom setting record and keep updating it every time the batch update finishes executing.

| improve this answer | |
  • It's actually in regards to trigger recursion that prevents a process from running multiple times on a master record. You however have done a very good job of answering this question. thanks for the info! – NSjonas Feb 4 '16 at 6:52
0

Just think about it.

Salesforce executes triggers in batches (For bulk processing), and each batch represents an execution cycle. If we look at static variables, they only maintain state for an execution cycle.

A trigger batch can never exceed 200 records.

Even though salesforce executes those 10k updates in a single instance, trigger execution will break them down to 200 records in a batch. Therefore static variable will hold values upto 200 for each execution.

The above behaviour can be achieved by implementing Stateful interface with batch classes.

| improve this answer | |
  • please see the answer I submitted. Statics do seem to persist across execution batches – NSjonas Feb 4 '16 at 6:58
0

After seeing some discussion around static persistence across execution batches, I decided I should just test this out myself.

Turns out the Id's ARE tracked through each trigger batch.

Here's the test I ran:

Static Class

public with sharing class Tracker {
    public static Integer runTime = 0;
    public static List<Id> recordIds = new List<Id>();
}

Trigger

trigger StaticTestTrigger on Foo__c (after insert) {
    Tracker.runTime++;
    Tracker.recordIds.addAll(Trigger.newMap.keySet());

    System.debug(Tracker.runTime);
    System.debug(Tracker.recordIds.size());
}

Anonymous Apex:

List<Foo__c> foos = new List<Foo__c>();
for(Integer i = 0; i< 2000; i++){
    foos.add(new Foo__c(Name = 'test'+i));
    if(foos.size() == 200){
        insert foos;
        foos = new List<Foo__c>();
    }
}

Output: enter image description here

This obviously doesn't really answer the question I asked but I think should clear up confusion around statics across trigger batches.

Further testing:

Ran a batch of 460 records using the Salesforce Data Import wizard:

Again, it ran in a single execution context (statics were persisted):

enter image description here

| improve this answer | |
  • You still missed a lot of things in the debug log. When anonymous code is executed, this is equivalent to a single execution. You should check how many times triggers were initiated. Am I making any sense to you? Try to insert 400 records using data-loader and then you will understand how static variables behave. – Salesforcesmarty Feb 4 '16 at 12:33
  • @Salesforcesmarty I think you're confused about what I am asking... Yes, I do understand how static's behave. The trigger was run 10 times in my example above. Maybe the dataloader kicks off a new execution context for each batch but this is not true for all bulk operations. If a class updates 1000 records the static will exist across all 5 batches. My question was in regards to how SF handles splitting execution context's on TBW. – NSjonas Feb 5 '16 at 0:27
  • Not to mention... you're wrong about the data uploader. Just used the import wizard to upload 450 records and it ran in trigger 3 batches... My statics were persisted across the 3 batches. – NSjonas Feb 5 '16 at 0:35
  • Let me try this and I will update you about my findings. This is going to be interesting. – Salesforcesmarty Feb 5 '16 at 2:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.