La création d’enregistrements de déclenchement ne fonctionne pas dans la mise à jour groupée [duplicate]

Nov 20 2020

Nous avons un processus où lorsque les enregistrements sont mis à jour avec Sync_Prospect_to_Pardot__c à true, il doit créer un enregistrement pi__ObjectChangeLog__c pour chaque enregistrement mis à jour. Cependant, lorsque j'utilise le chargeur de données pour mettre à jour 250 enregistrements avec l'API Bulk activée, seuls 200 enregistrements pi__ObjectChangeLog__c sont créés. Si je n'ai pas coché ce paramètre, tous les 250 créent. J'ai enregistré un ticket avec l'assistance Salesforce et ils ont dit que ce n'était pas un problème avec le chargeur de données et qu'ils ne fourniraient pas de commentaires sur le code car il est hors de portée. La prise en charge de Pardot n'a pas été utile car nous utilisons un processus personnalisé pour créer les journaux de modification d'objet. Il se passe clairement quelque chose ici et le code n'est rien de différent de ce que j'ai écrit pour le reste de l'organisation. Nous ne voyons aucun problème d'utilisation de l'API en bloc pour déclencher l'un de ces processus.

L'objet pi__ObjectChangeLog__c est marqué comme "Autoriser l'accès à l'API en masse".

Le problème est-il le code? Sinon, quelles autres choses dois-je vérifier? J'obtiens les mêmes résultats que le sobject de départ soit un contact ou un prospect.

Voici les composants. Notez que nous utilisons le SFDC Trigger Framework de Kevin O'Hara comme recommandé par Trailhead .

Déclencheur

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();
}

Répartiteur

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);
        }
    }
}

Classe

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');
    }
}

Réponses

1 HR Nov 20 2020 at 03:52

TriggerHandler.isBypassed est référencé dans le code de déclenchement pour vérifier s'il est déjà exécuté ou non.

Mais l'API Bulk traite tous les enregistrements sous une seule transaction, ce qui signifie que les variables statiques ne sont jamais réinitialisées.

Veuillez vous référer à ceux-ci - API en masse et état de variable statique

MarkPond Nov 20 2020 at 03:55

Vous devez effacer le contournement dans votre répartiteur une fois que le PardotSyncManagercode est terminé.

Pour que votre bloc if ressemble à ceci à la place:

//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
}