1

I am thinking of a way to bypass triggers from both Flow and Apex when I execute the DML statements on my batch class.

Framework setup:

I have a Hierarchy Custom Setting that has checkbox fields per Object.

Apex Trigger Handler:

public class AccountTriggerHandler implements TriggerHandler {
    public Boolean isDisabled() {
        return !Trigger_Setting__c.getInstance().Account__c;
    }

    // trigger code
}

On the Flow, the Hierarchy Custom Setting is retrieved at the first node.

Flow Example

I was optimistic that because of the cached nature of custom settings that it will be a simple assignment of the Trigger Setting to false before the DML then revert back to true after the DML. Unfortunately, it does not work this way and I have to do a update operation on the custom setting for this to work.

Trigger_Setting__c triggerSetting = Trigger_Setting__c.getInstance();
triggerSetting.Account__c = false;
update triggerSetting;

update accounts;

triggerSetting.Account__c = true;
update triggerSetting;

I think this should have no issues on other users ability to run automations because I have set up the hierarchy custom setting on user level and should not affect other users when an Account operation is made during the batch job execution - there is a dedicated user that will run the scheduled batch job.

Just want to know the community's thoughts if there is a better way to do this.

2 Answers 2

1

As you've observed, Custom Settings have to be updated. What you want is an in-memory solution. Here's a sample implementation to get started.

public class SystemFlags {
    // Example flag
    public enum Flag { ACCOUNT_TRIGGER_DISABLED }
    static Map<Flag, Boolean> flags = new Map<Flag, Boolean>();
    public class Parameters {
        @InvocableVariable public String name;
        @InvocableVariable public Boolean readFlag;
        @InvocableVariable public Boolean writeFlag;
        @InvocableVariable public Boolean value;
    }
    // Method to get or set the flag in a flow
    @InvocableMethod public static Parameters[] operation(Parameters[] params) {
        Map<Flag, Boolean> tempValues = new Map<Flag, Boolean>();
        // Give the illusion that flags are handled in parallel for bulk execution
        for(Parameters param: params) {
            if(param.readFlag == true) {
                param.value = flags.get(Flag.valueOf(param.name));
            }
            if(param.writeFlag == true) {
                tempValues.put(Flag.valueOf(param.name), param.value);
            }
        }
        flags.putAll(tempValues);
        return params;
    }
    // Methods used to set or get the flag in Apex code
    public static void setFlag(Flag name, Boolean value) {
        flags.put(name, value);
    }
    public static Boolean getFlag(Flag name) {
        return flags.get(name);
    }
}

For usage, each trigger would check if a named flag is set, and change their logic based on the flag:

public class AccountTriggerHandler {
  public static void beforeInsert(Account[] records) {
    if(SystemFlags.getFlag(SystemFlags.Flag.ACCOUNT_TRIGGER_DISABLED)) {
      return;
    }
    // Do more logic
  }
}

Likewise, your Flow can read the flag to determine if it should continue using an Apex Action.

To set a flag, you can do do from a Flow or from Apex. Your Apex becomes:

SystemFlags.setFlag(SystemFlags.Flag.ACCOUNT_TRIGGER_DISABLED);
update accounts;
SystemFlags.setFlag(SystemFlags.Flag.ACCOUNT_TRIGGER_DISABLED);

You could also make this more robust by being able to set multiple flags at once, etc.

Not only is this great for bulk operations, but I find a setup like this is also useful in unit tests, where you want to quickly set records into some state before starting the main test. In particular, you can save on governor limits by having your triggers not run when they're not needed.

2
  • Thanks for sharing this! Adding a custom setting in the entry conditions then we can also control the automations via UI. This would have been perfect if only we can call Apex Actions on Before Save Triggered Flows. Maybe just have to wait for that day.
    – Dave
    Commented Jul 4 at 14:13
  • @Dave Agree. Not having Apex in before save record-triggered flows is a frustrating limitation. They should just limit DML operations, like they do for Visualforce constructors.
    – sfdcfox
    Commented Jul 4 at 16:49
0

You can assign a custom permission to the running user and skip the flow and triggers if the running user has this custom permission. I would recommend to use a trigger framework where you can bypass the triggers using custom setting/custom permission. I think you are already doing it. But, I will not recommend updating the custom setting in the code.

You must log in to answer this question.

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