[SalesForce] How to handle error records in Batch apex

I have a simple requirement to write a batch which will loop through all the records for 'Object__c' and update a custom field on the object(Logic is irrelevant here).

Here is the batch class I developed:

public class SimpleBatch implements Database.Batchable<sObject>{

    public Database.QueryLocator start(Database.BatchableContext BC){
        return Database.getQueryLocator('SELECT Id,Name,Start_Date__c,End_Date__c,Active__c FROM 
                        Object__c WHERE Start_Date__c!=NULL AND End_Date__c!=NULL');
    }

    public void execute(Database.BatchableContext BC,List<Package__c> scope){
        Date todayDate = Date.today();
        List<Object__c> objsToUpdate = new List<Object__c>();
        for(Object__c obj:scope){
            if((obj.Start_Date__c <= todayDate) && (obj.End_Date__c >=todayDate)){
                if(pkgObj.Active__c != 'Yes'){
                    pkgObj.Active__c = 'Yes';
                    objsToUpdate.add(obj);
                }
            }else if((obj.Start_Date__c > todayDate) || (obj.End_Date__c < todayDate)){
                if(obj.Active__c != 'No'){
                    obj.Active__c = 'No';
                    objsToUpdate.add(obj);
                }
            }
        }
        update objsToUpdate;
    }

    public void finish(Database.BatchableContext BC){
        //code to send email that batch finished successfully.
    }

}

Lets assume there are 1000 records to process and I am running the job with a batch size of 200 records.

  1. Batch 1 – First set of 200 records – Records failed with validation
    errors.
  2. Batch 2 – Second set of 200 records – Records failed with
    validation errors.
  3. Batch 3 – Third set of 200 records – Records
    failed with validation errors.
  4. Batch 4 – Fourth set of 200 records –
    Records failed with validation errors.
  5. Batch 5 – Fifth set of 200
    records – successfully processed, No errors.

Here is the problem: Even though first batches failed, The email is sent from the finish method saying that batch successfully processed.

Only When I look into the logs, I will know that there are some records failed otherwise everything looks to seem fine even though 4 batches failed.

Any best practices or advice on how to handle this situation.

Best Answer

Some things to do:

  1. Have your batch class implement Database.stateful
  2. Declare some variables that are initialized in the constructor to 0. These variables count successes and errors; also a string variable that remembers the records that failed and why (initialized to empty string).
  3. Use Database.update with allOrNothing = false instead of update within execute(). Interrogate each member of Database.SaveResult[] for isSuccess() and count succcesses and failures in your stateful variables from #2. Log in the stateful variable all the errors (id of record, name of record, and error message/exception)
  4. In the finish method, send an email to the sysad of count of successes/failures + string variable of all the failures.
  5. In finish() method, write your batch results to a custom Log__c record(s)