1
  1. Update 405 records on an object (So it executes the trigger 3 times 200+200+3 i.e, each batch holds 200 records)
  2. There is a process builder which in turn is updating the same object (Will fire the trigger again)
  3. Workflow field update - will fire the trigger again)

So in this example, trigger will run 6*3 times (i.e., per batch it will execute 6 times - 3 before and 3 after) but we need the trigger to execute only 2 times (1 before and 1 after)

i.e., triggers should not execute when process builder or work flow field update updates the record

Recursive Static Variable: Will work only for first 200 records

  • Can you explain more in details what are you trying to achieve, what have you tried (probably with an example) and what does not work. It is hard to understand that based on your question right now. – kurunve Jul 6 '18 at 12:37
  • 1
    While the wording is a bit clumsy, I think it's relatively clear that OP is asking for how to implement a recursion/mutli-run prevention mechanism. David's answer is spot on, so I'm voting to leave this one open. – Derek F Jul 6 '18 at 15:15
4

This is a great example of why so-called recursion protection like this:

public class MyTriggerHandler {
    static Boolean hasAlreadyRun = false;
}

trigger MyTrigger on MyObject__c (after update) {
    if (!MyTriggerHandler.hasAlreadyRun) {
        // Do stuff
        MyTriggerHandler.hasAlreadyRun = true;
    }
}

is a terrible pattern.

Without seeing more of your code, you probably have two options.

The first is to fix the recursion. Fold your Process Builder and your Workflow Rule into the code of your trigger handler. Honestly, I would do this anyway - if you're doing bulk loads on this data you don't need to have extra trigger invocations taking up transaction time anyway.

The second is to use a static collection-based recursion guard, something like this:

public class MyTriggerHandler {
    static Set<Id> recordsAlreadyProcessed = new Set<Id>();

    public static void afterUpdate(List<MyObject__c> newList, Map<Id, MyObject__c> oldMap) {
        List<MyObject__c> toProcess = new List<MyObject__c>();

        for (MyObject__c m : newList) {
            if (!recordsAlreadyProcessed.contains(m.Id)) {
                recordsAlreadyProcessed.add(m.Id);
                toProcess.add(m);
            }
        }

        // Now process `toProcess` only.
}

trigger MyTrigger on MyObject__c (after update) {
    MyTriggerHandler.afterUpdate(Trigger.new, Trigger.oldMap);
}

Note however that this isn't necessarily a copy-and-paste solution. If your trigger should reprocess records that undergo specific changes from workflow rules, or even depend upon those updates, this pattern will break that. You need to carefully evaluate how your trigger and your declarative automations interact before you add any kind of suppression logic, and be aware that using this pattern does have implications for any future implementations of declarative automation you may do.

1

Usually, during bulk data load, it is recommended to deactivate the triggers, process builder's processes, workflow rules, so that bulk data load will not consume much time and you will not end up with unexpected results due to recursion.

There are two options to make Salesforce system to sync with data updates.

  1. You can prepare csv file with those fields which are getting updated by processes and workflow rules

  2. You need to create a separate batch process to update those data considering the logic written in process builder and workflow rules.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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