Cosa sono i batch apex

Un Batch in Apex è un meccanismo che consente di processare una grande mole di dati in modo asincrono.

Tipici scenari di utilizzo possono essere:

  • Aggiornare un insieme di record quando si verifica un determinato evento. Per esempio: cambiare lo status di opportunity a “Closed” quando la Close Date si trova nel passato.
  • Eseguire logiche massive quando si importano o si creano dei dati. In questo caso uno scenario possibile potrebbe essere l’import di record da parte di sistemi esterni (magari database NOSQL) per trasformarli in una serie di record in Salesforce (Account, Opportunity e Quote).
  • Eliminare logicamente o fisicamente dei dati obsoleti.
  • Tutti i casi che prevedono l’utilizzo di risorse non indifferenti e che quindi potrebbero inficiare la User Experience di un utente.

Come funzionano i Batch Apex 

Prima di passare alla scrittura vera e propria di un Batch è necessario capirne il funzionamento, altrimenti si rischia di introdurre non pochi problemi all’interno della Organizzazione.

Il ciclo di vita di un Batch è basato su tre metodi che dovranno essere ridefiniti: Start, Execute, Finish.

  1. Nel metodo Start bisogna inserire la query iniziale di tutti i record che dovranno essere processati.
  2. Nel metodo Execute si inserisce la logica vera e propria da applicare all’insieme dei record.
  3. Un metodo Finish che verrà eseguito quando tutti i record sono stati processati.

Un Batch quindi non esegue un sola volta, ma N volte, infatti il Batch dividerà l’esecuzione in N job distinti (ed indipendenti tra loro).

Bisogna decidere per ogni job il totale dei record processati, in gergo chiamato Chunk (se non si esplicita la dimensione del Chunk di default verranno processati 200 record alla volta).

Quindi il numero di job eseguiti sarà:

N = RecordTotaliDaProcessare / Chunk

Possiamo riassumere il ciclo di vita di un Batch utilizzando il seguente diagramma:

Come scrivere un Batch Apex

Per scrivere un Batch in Apex bisogna creare una classe che implementi Database.Batchable<Object> e ridefinire i tre metodi principali (di cui abbiamo parlato sopra):

  1. Start() dove inserire la query che seleziona tutti i record da processare.
  2. Execute() dove inserire la logica vera e propria.
  3. Finish() in questo metodo si inserisce la logica finale, come ad esempio aggiornare dei record correlati a quelli processati nel metodo Execute.

Un esempio: se nel metodo Execute vengono aggiornate le Opportunity secondo delle regole, nel metodo Finish potremmo aggiornare gli Account relativi alle Opportunity.

Un esempio di Batch in Salesforce:

public class myBatchClass implements Database.Batchable<sObject>{

   String query;

   public myBatchClass (){
      query = 'SELECT Id, name FROM Opportunity WHERE status =\'Completed \'';
   }

   public Database.QueryLocator start(Database.BatchableContext BC){
      return Database.getQueryLocator(query);
   }

   public void execute(Database.BatchableContext BC, List<sObject> scope){

       //your logichere
    }

   public void finish(Database.BatchableContext BC){
   }
}

Il metodo Start può avere come parametro di ritorno un Database.QueryLocator oppure un Iterable

Qual è la differenza?

Utilizzando una Iterable sarà più semplice iterare gli elementi nel metodo Execute, però Iterable ha un limite massimo di record totali processati pari a 50000, invece utilizzando Database.QueryLocator il “limite” di record totali processati è 50 milioni.

Come effettuare il run di un Batch Apex

Per poter fare il run di un batch è necessario scrivere un semplice comando all’interno del vostro codice apex (oppure da Developer Console):

ID batchprocessid = Database.executeBatch(new myBatchClass);

Si può poi utilizzare l’Id del batch esguito per effettuare una query e verificare lo status di esecuzione del batch e altre informazioni:

AsyncApexJob aaj = [SELECT Id, Status, JobItemsProcessed, TotalJobItems, NumberOfErrors 
                    FROM AsyncApexJob WHERE ID =: batchprocessid ];

Utilizzare callouts in Batch Apex

Di default un Batch Apex non consente di effettuare callout verso sistemi esterni. Per consentire l’utilizzo di callout è necessario che la classe estenda, oltre a Batchable, anche l’interfaccia Database.AllowsCallouts.

Un esempio:

public class myBatchClass implements Database.Batchable<sObject>, 
   Database.AllowsCallouts{
}

Scrivere una classe di test per un batch apex

I principali accorgimenti per testare in modo corretto un Batch Apex sono:

  • In una classe di test verrà eseguito soltanto una volta il metodo Execute.
  • I Batch sono dei processi asincroni che girano in thread separati da quello principale. Per essere sicuri che il job abbia terminato, è importante inserire executeBatch all’interno degli statement startTest() e stopTest().
  • Inserite i System.assert subito dopo stopTest().

Governor Limits per i Batch Apex

I principali Governor Limits da rispettare per i Batch Apex sono i seguenti:

  • Fino a 100 job possono eseguire contemporaneamente.
  • In una classe di test, fino a 5 job possono eseguire contemporaneamente.
  • Il numero di massimo di job schedulati in 24 ore può essere: 250.000 oppure 200 moltiplicato per il numero di licenze acquistate per quella Organizzazione, di questi due si considera il numero più grande.
    Da tenere in considerazione che questo limite non riguarda soltanto i job Batch ma è il totale dei job asincroni che girano in 24 ore all’interno della Org: metodi Future, Schedulable, Queuable ecc.
  • Se si utilizza il queryLocator, il Chunk massimo per un job è di 2000; se viene specificato un numero più alto, Salesforce automaticamente lo ridurrà.
  • I metodi Start, Execute e Finish possono implementare fino ad un massimo di 100 callout ognuno.

Prima di implementare un Batch, specialmente se sappiamo in partenza che dovrà processare moltissimi record, è meglio verificare bene i limiti imposti da Salesforce leggendo la guida ufficiale.

Considerazioni sull’utilizzo dei Batch Apex

Alcune considerazioni da tenere in mente quando si vuole implementare un Batch Apex:

  • Le classi che implementano l’interfaccia Batchable non possono contenere metodi future.
  • I metodi all’interno della classe devono essere dichiarati come Public e Global.

I Batch Apex eseguono molto più velocemente se non utilizziamo subquery all’interno del metodo Start, come ad esempio: SELECT Id (SELECT id FROM Contacts o FROM Account).
Meglio invece, effettuare la subquery all’interno di ogni metodo execute.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *