Tworzenie rekordu wyzwalacza nie działa w przypadku aktualizacji zbiorczej [duplikat]

Nov 20 2020

Mamy proces, w którym po zaktualizowaniu rekordów za pomocą Sync_Prospect_to_Pardot__c do wartości true, powinien utworzyć rekord pi__ObjectChangeLog__c dla każdego zaktualizowanego rekordu. Jednak gdy używam programu ładującego dane do aktualizacji 250 rekordów z włączonym Bulk API, tworzonych jest tylko 200 rekordów pi__ObjectChangeLog__c. Jeśli to ustawienie jest odznaczone, wszystkie 250 tworzą. Zarejestrowałem zgłoszenie do działu wsparcia Salesforce i powiedzieli, że to nie problem z programem ładującym dane i nie dostarczą opinii na temat kodu, ponieważ jest on poza zakresem. Wsparcie Pardot nie było pomocne, ponieważ używamy niestandardowego procesu do tworzenia dzienników zmian obiektów. Wyraźnie coś się tu dzieje, a kod nie różni się niczym od tego, co napisałem dla reszty organizacji. Nie widzimy problemów przy używaniu zbiorczego interfejsu API do uruchamiania żadnego z tych procesów.

Obiekt pi__ObjectChangeLog__c jest oznaczony jako „Zezwalaj na zbiorczy dostęp do interfejsu API”.

Czy to jest kod? Jeśli nie, jakie inne rzeczy muszę sprawdzić? Otrzymuję te same wyniki, niezależnie od tego, czy początkowy obiekt jest kontaktem, czy przewodnikiem.

Oto składniki. Zauważ, że używamy SFDC Trigger Framework Kevina O'Hary zgodnie z zaleceniami Trailhead .

Cyngiel

trigger LeadTrigger on Lead (before insert, before update, before delete, after insert, after update, after delete, after undelete) {
    Map<String, Trigger_Settings__c> triggerSettings = Trigger_Settings__c.getAll();
    
    if(triggerSettings.get('LeadTrigger') <> null && triggerSettings.get('LeadTrigger').Execute_Trigger__c)
        new LeadTriggerDispatcher().run();
}

Dyspozytor

public without sharing class LeadTriggerDispatcher extends TriggerHandler {
//Trigger context variables are still available but need to be cast: trigger.new, trigger.newMap, trigger.oldMap
    List<Lead> leads = (List<Lead>) trigger.new;
    Map<Id, Lead> leadsOldMap = (Map<Id, Lead>) trigger.oldMap;
    Map<Id, Lead> leadsNewMap = (Map<Id, Lead>) trigger.newMap;
    Map<String, Trigger_Settings__c> triggerSettings = Trigger_Settings__c.getAll();

    protected override void afterUpdate() {
        //declare variables
        Set<sObject> leadsForSync = new Set<sObject>();

        //loop through to find qualifying records
        for(Lead lead : leads) {
            //leads are eligible for sync if their sync to prospect field changes, but no email changes were made. By default an OCL gets created if the email is updated
            if(leadsOldMap.get(lead.Id).Sync_Prospect_to_Pardot__c == false && leadsNewMap.get(lead.Id).Sync_Prospect_to_Pardot__c == true)
                leadsForSync.add((sObject)lead);
        }

        //execute methods
        if(!leadsForSync.isEmpty() && !TriggerHandler.isBypassed('PardotSyncManager') && triggerSettings.get('PardotSyncManager') <> null && triggerSettings.get('PardotSyncManager').Execute_Trigger__c) {
            TriggerHandler.bypass('PardotSyncManager');
            PardotSyncManager.createObjectChangeLog(leadsForSync);
        }
    }
}

Klasa

public without sharing class PardotSyncManager {
    //createObjectChangeLog takes a set of lead or contact records and creates an OCL record for those records. Called from the contact or lead dispatcher
    public static void createObjectChangeLog(Set<sObject> records) {
        system.debug('PardotSyncManager Start');

        system.debug('records size: ' + records.size());

        //oclsForInsert stores a list of OCLs that need to be inserted
        List<pi__ObjectChangeLog__c> oclsForInsert = new List<pi__ObjectChangeLog__c>();

        //Iterate through all records in the scope
        for(sObject record : records) {
            system.debug('record Ids: ' + record.Id);
            //Check if the record is a contact. If so, then parse the sObject to a contact and then create an OCL for that contact.
            if(String.valueOf(record.Id).substring(0,3) == '003') {
                Contact contact = (Contact)record;
                oclsForInsert.add(new pi__ObjectChangeLog__c(pi__ObjectEmail__c = contact.Email, pi__ObjectFid__c = contact.Id, pi__ObjectType__c = 1, pi__ObjectState__c = 1));
            }
            //Check if the record is a lead. If so, then parse the record into a lead and then create an OCL for that lead.
            else if(String.valueOf(record.Id).substring(0,3) == '00Q') {
                system.debug('lead qualified');
                Lead lead = (Lead)record;
                oclsForInsert.add(new pi__ObjectChangeLog__c(pi__ObjectEmail__c = lead.Email, pi__ObjectFid__c = lead.Id, pi__ObjectType__c = 2, pi__ObjectState__c = 1));
            }
        }

        //try to insert the OCL records
        try {
            system.debug('ocls for insert: ' + oclsForInsert.size());
            insert oclsForInsert;
        }
        //If there's an error, post the error to the debug log
        catch(Exception e) {
            system.debug('EXCEPTION in PardotSyncManager.createObjectChangeLog at row ' + e.getLineNumber() + ': ' + e.getMessage());
        }

        system.debug('PardotSyncManager Complete');
    }
}

Odpowiedzi

1 HR Nov 20 2020 at 03:52

TriggerHandler.isBypassed odwołuje się do kodu wyzwalacza, aby sprawdzić, czy został już wykonany, czy nie.

Ale Bulk API przetwarza wszystkie rekordy w ramach jednej transakcji, co oznacza, że ​​zmienne statyczne nigdy nie są resetowane.

Proszę odnieść się do tych - Bulk API i Static Variable State

MarkPond Nov 20 2020 at 03:55

Musisz wyczyścić obejście w swoim programie rozsyłającym po PardotSyncManagerzakończeniu wykonywania kodu.

Skutecznie sprawiając, że twój blok if wygląda tak:

//execute methods
if (
  !leadsForSync.isEmpty() &&
  !TriggerHandler.isBypassed('PardotSyncManager') && // this is causing it to only run on the first iteration
  triggerSettings.get('PardotSyncManager') <> null &&
  triggerSettings.get('PardotSyncManager').Execute_Trigger__c
) {
  // turn off the trigger handler
  TriggerHandler.bypass('PardotSyncManager');

  // do the work
  PardotSyncManager.createObjectChangeLog(leadsForSync);

  // turn the trigger handler back on
  TriggerHandler.clearBypass('PardotSyncManager'); // because this bypass removal was not here
}