2

I have a straightforward autolaunched Flow (triggered by PB). It looks up some characteristics of a CampaignMember and based on that, returns a score ("fireball") value. The two subflows here write to utility objects for tracing and are not part of the logic of the Flow.

enter image description here

The data for the Flow is held in a Custom Metadata table and queried from the pink "Get Records" node as follows.

enter image description here

Most of the time CampaignMembers are written one at a time. However, in the case of a Lead conversion, if the Lead has multiple CampaignMembers, then the system processes all the Members in one transaction, and the Flow fails with the following message:

Error Occurred: This error occurred when the flow tried to look up records: Disjunctions not supported.

(emphasis mine) Essentially meaning OR queries aren't supported. Googling further, I found this which refers to the documentation, which states:

When you define multiple filters, the filter logic usually defaults to AND. However, if multiple filters have the same field selected and use the equals operator, the filters are combined with OR.

So when more than one CampaignMember is in the transaction, the system is optimizing the query behind the scenes in a way that contains an OR, which is not allowed for custom metadata queries.

At the moment, the item is set to simply return a default value if it encounters an error, but that is not necessarily the correct value.

I see only two options here:

  1. Code it - which is fine, but I am really trying to do what I can declaratively
  2. Use an ordinary object for the lookup instead of custom metadata

What I'd really like to do is to force the batch size of this transaction to 1, since performance isn't a huge consideration and the transaction volume is small.

Any suggestions? Thanks in advance.

1 Answer 1

1

The auto bulkification has always been a problem from my perspective. You need to put the records into an Sobject Collection yourself then loop through them to achieve your Batch = 1. You can do something like here which I wrote a few versions ago. With support of Sobjects in Flows now this class can be optimized to use that instead. This will collect the "auto bulkified" records and put them into an Sobject Collection for output. Currently there is not a way to do that without some code.

In the Flow you also have to add a decision after this class to check if SobjColl var is null or not so you match the # of Interviews started. Technically this class will return 1 Sobject Collection variable for EACH record submitted to it; however all of them should be NULL except 1 which will hold everything. This is intentional as the Flow will error if it starts with X interviews and later has X-[number].

public with sharing class AuditReportBulkifyClass {

@InvocableMethod(label='Collect Bulkified Records')
public static List<List<AuditReport__c>> gatherRequests(Request[] requests) {

    // Gather bulkified records from Flow
    Map<Id, AuditReport__c> parents = new Map<Id, AuditReport__c>();

    for(Request request : requests) {
        parents.put(request.recordId, null);
    }

        parents = new Map<Id, AuditReport__c>([
            SELECT Id,RecordTypeId
           FROM AuditReport__c
        WHERE Id IN :parents.keySet()
    ]);

    // Flows must return List<List> for Sobject Collections. This is returned as Sobject Collection to Flow
    List<List<AuditReport__c>> responseColl = new List<List<AuditReport__c>>();

    // Add all of the values to an initial List
    List<AuditReport__c> responseList = new List<AuditReport__c>();
    responseList.addAll(parents.values());

    System.debug('Size of ResponseList ' + responseList.size());

    // Adds actual values we will use to the List of List
    responseColl.add(responseList);
    System.debug('Return responseColl size ' + responseColl.size());

    // Initialize a new list which will return empty to ensure return same number of interviews back to Flow
    List<AuditReport__c> emptyList = new List<AuditReport__c>();

    // Iterate through number of interviews - 1 and assign to empty list
    for (Integer i=0; i<responseList.size()-1; i++){
        responseColl.add(emptyList);
        }
    return responseColl;
}

public with sharing class Request {
    @InvocableVariable(label='Record ID' required=true)
    public Id recordId;}}
2
  • Thank you for the answer... I ended up creating an Apex plugin for the Flow to run the query. Jun 15, 2020 at 22:03
  • I have documented my code and overall approach to a generic lookup service here: stupidcrmtricks.com/2020/06/… Jun 17, 2020 at 15:32

You must log in to answer this question.

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