Начало работы с Batch Apex

Введение

Для случаев, когда требуется обработать более чем 50 000 записей, Batch Apex приходит на выручку. Batch Apex облегчает обработку записей, разбивая их на небольшие объемы, а также это очень просто в реализации.

1. Implementing of Batch Apex
2. Scheduling of Batch Apex
3. Chaining of Batch Apex
4. Testing of Scheduled Batch Apex
5. Стоит запомнить

Implementing of Batch Apex

Необходимо имплементировать интерфейс Database.batchable.
В этом интерфейсе присутствуют такие методы:

  • Start() - запрашивает записи для обработки
  • Execute() - логика самой обработки
  • Finish() - выполняет последним, тут, как правило, иногда оставляют отправку email или запуск другого Batch class.

Все 3 должны быть имплементированы.

Предположим, что нам необходимо сделать задачу, где нужно для каждого Contact создать Case. И кол-во контактов превышает 50 000.

Batchexample
global class BatchExample implements Database.Batchable<sObject>{
    global database.querylocator start(Database.BatchableContext BC)
    {
        return Database.getQueryLocator(
            'SELECT ID, AccountID FROM Contact'
        );
    }
 
    global void execute(Database.BatchableContext BC, List<Contact> scope)
    {
        List<Case> newCases = new List<Case>();
        for(Contact cnt : scope) {
            newCases.add(new Case(Status = 'New', 
                                  Origin = 'Phone',
                                  AccountId = cnt.AccountId,
                                  ContactId = cnt.Id));
        }

        insert newCases;
    }
    
    global void finish(Database.BatchableContext BC)
    {
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
       
        AsyncApexJob a = [SELECT a.TotalJobItems, 
                                 a.Status, 
                                 a.NumberOfErrors,
                                 a.JobType, 
                                 a.JobItemsProcessed, 
                                 a.ExtendedStatus, 
                                 a.CreatedById,
                                 a.CompletedDate 
                          FROM AsyncApexJob a 
                          WHERE id = :BC.getJobId()];

        String[] email = new String[]{'your email'};
        mail.setToAddresses(email);
        mail.setReplyTo('Your email for reply'); 
        mail.setSenderDisplayName('Apex Batch Processing Module');
        mail.setSubject('Batch Processing '+ a.Status);
        mail.setPlainTextBody('The Batch Apex job processed '+ a.TotalJobItems + 
                              'batches with ' + a.NumberOfErrors + 
                              'failures ' + 
                              'Job Itemprocessed are ' + a.JobItemsProcessed);
        Messaging.sendEmail(new Messaging.Singleemailmessage [] {mail});
    }
}

Запустить Batch class можно через Anonymous Console с помощью:

Database.executeBatch(new BatchExample(), 200);

Где 200 - это размер пачки записей, которая будет обработана за раз. Также, этот метод может возвращать Id запущенного процесса.

В результате для каждого контакта будет создан свой case.

Scheduling of Batch Apex

Частый случай когда батч класс должен запускаться по расписанию. Раз в день, раз в неделю, раз в месяц, — как захочет заказчик :slight_smile:

Первый способ

Для этого Apex Class должен имплементировать интерфейс Schedulable

BatchExampleSchedule
global class BatchExampleSchedule implements Schedulable { 

    global void execute(SchedulableContext ctx) {
        BatchExample myBatchExample = new BatchExample();
        database.executebatch(myBatchExample);
    }
}

Он будет запускать BatchExample, как мы сделали это ранее через Anonynmous Console. Но, когда же он будет его запускать ?

  1. Переходим в Apex Classes из Quick Find, и нажимаем Schedule Apex.

  2. Указываем имя и созданный Schedule Class. Жмём Save
    image

Второй способ

В классе, который имплементирует Schedulable интерфейс.
Указать дату запуска с помощью:

global void execute(SchedulableContext ctx) {
        BatchExample myBatchExample = new BatchExample();
        String cronStr = '20 30 8 10 2 ?';
        String jobID = System.schedule('Create Cases', cronStr, myBatchExample); 
 }

Chaining of Batch Apex

Начиная с версии API 26.0 из batch класса можно вызвать следующий batch class.
Допускается максимум 5 последовательных вызовов. Заменим в нашем примере отправку email на вызов следующего батч класса.

Chaining Batch Class
global class BatchExample implements Database.Batchable<sObject>{
    global database.querylocator start(Database.BatchableContext BC)
    {
        return Database.getQueryLocator(
            'SELECT ID, AccountID FROM Contact'
        );
    }
 
    global void execute(Database.BatchableContext BC, List<Contact> scope)
    {
        List<Case> newCases = new List<Case>();
        for(Contact cnt : scope) {
            newCases.add(new Case(Status = 'New', 
                                  Origin = 'Phone',
                                  AccountId = cnt.AccountId,
                                  ContactId = cnt.Id));
        }

        insert newCases;
    }
    
    global void finish(Database.BatchableContext BC)
    {
        BatchChaniningExample chaingBatch = new BatchChaniningExample ();
        Id batchProcessId = Database.executeBatch(chaingBatch);
    }
}

Testing of Scheduled Batch Apex

Осталось самое важное для деплоя: написание тестов покрывающих наш код.

Такой тест покроет не только Schedule, но и Batch класс.

BatchExampleScheduleTest

@isTest
public with sharing class BatchExampleScheduleTest {

@TestSetup
static void setup(){
    String test = 'test';
    Account acc = new Account(Name = test);
    insert acc;

    Contact ctn = new Contact(AccountId = acc.Id, LastName = test);
    insert ctn;

}

@isTest
public static void scheduleTest() {
    Test.startTest();
        BatchExampleSchedule bes = new BatchExampleSchedule();
        String sch = '0 0 2 * * ?'; 
        System.schedule('Test Schedule', sch, bes); 
    Test.stopTest();
}

}

Стоит запомнить

  • Не более 5 batch процессов могут быть вызваны по цепочке, или запущенны одновременно.

  • Максимальное кол-во вызовов batch Apex методов в течении 24 часов — не более 250 000. Если только ваша лицензия не позволяешь больше.

  • QueryLocator может вернуть максимум 50 миллионов записей. Иначе, возникает ошибка и процесс будет остановлен.

  • Методы start, execute и finish могут делать до 100 callout каждый. Имплементируйте AllowsCallouts для создания калаутов в батч классе.

  • Future методы не могут быть вызваны из Batch Apex.

  • Все методы и класс должны быть отмечены public или global

2 Likes