2

I made a program using batch, when i tried to update the value, status in batch is succesfully, but i got error message in SerialBatchApexRangeChunkHandler, like this:

enter image description here

I tried to using this query to get error, but it just get status on batch, not the SerialBatchApexRangeChunckHandler, so it will be always success, meanwhile my program is not updated because of this SerialBatchApexRangeChunckHandler Error. Do you guys have any idea about it? thankyou

  public void checkBatchStatus() {
        AsyncApexJob job = [SELECT Id, Status FROM AsyncApexJob WHERE Id =: batchId];
        batchStatus = job.Status;
        if(batchStatus == 'Completed') {
            batchStatusText='';
            apexpages.addMessage(new ApexPages.message(Apexpages.Severity.INFO,'Update Sales Plan Successfully'));
            pollerBool = false;
        } else {
            batchStatusText = 'Please wait while your request is being processed!! ';
            pollerBool = true;
        }
    }

This is my batch class

global class BulkValidateSalesPlanBatchUpdate implements Database.Batchable<sObject>,Database.Stateful {
    global Id[] updateSPDIds {get;set;}
    global Map<Id, Boolean> updateOpexList {get;set;}
    global Map<Id, Date> updateDeliveryScheduleList {get;set;}
    global Map<Id, Decimal> updateSimulationSalesPriceList {get;set;}
    global Map<Id, Boolean> insertedPPD {get;set;}
    global Integer recordsProcessed = 0;
    
    global Database.QueryLocator start(Database.BatchableContext BC ){
        String query ='SELECT Id, Prospect__r.Id FROM Sales_Plan_Detail__c WHERE Id IN :updateSPDIds';
        return Database.getQueryLocator(query);
    }
    
    global void execute (Database.Batchablecontext BC, list<Sales_Plan_Detail__c> scope){
        insertedPPD = new Map<Id, Boolean>();
        List<Sales_Plan_Detail__c> spdToUpdate = new List<Sales_Plan_Detail__c>();
        List<Prospect_Product_Detail__c> prospectToUpdate = new List<Prospect_Product_Detail__c>();
        
        for(Sales_Plan_Detail__c ent : scope){
            Sales_Plan_Detail__c spd = new Sales_Plan_Detail__c();
            Prospect_Product_Detail__c ppd = new Prospect_Product_Detail__c();
            
            ppd.Id = ent.Prospect__r.Id;
            spd.Id = ent.Id;
            if(updateOpexList.containsKey(ent.Id)) {
                spd.Checklist_Opex__c = updateOpexList.get(ent.Id);
            }
            if(updateSimulationSalesPriceList.containsKey(ent.Id)) {
                spd.Simulation_Sales_Price__c = updateSimulationSalesPriceList.get(ent.Id); 
            }
            if(updateDeliveryScheduleList.containsKey(ent.Id)) {
                ppd.Delivery_Schedule__c = updateDeliveryScheduleList.get(ent.Id);
                if(!insertedPPD.containsKey(ppd.Id)) {
                    insertedPPD.put(ppd.Id, TRUE);
                    prospectToUpdate.add(ppd);
                }
            }
            spdToUpdate.add(spd);
            recordsProcessed = recordsProcessed + 1;
        }
        update spdToUpdate;
        update prospectToUpdate;
    }    
    
    global void finish(Database.Batchablecontext BC){
         System.debug(recordsProcessed + 'records processed!');
    }
}

1 Answer 1

3

Don't wait for these chunk errors. Instead write your batch to collect and report them.

Ensure your batch execute uses something like allOrNone as false in your DML operations (via the Database functions rather than DML keywords) then the exception is not thrown and you can react to the errors in the results returned to you.

For reporting these issues, hold them in batch state for sending in an email (for example) from the batch finish method. To handle batch state like this, implement Database.Stateful in your batch.

UPDATE: In response to your inclusion of code in an edit:

If you look at your batch this has the following two statements:

update spdToUpdate;
update prospectToUpdate;

It is from these that you may see exceptions of the like you listed being thrown.

Equivalent to using the update DML keyword is the Database.update() function. However, the function has additional capabilities; it can be told to not throw out all changes but rather to update as many of the records it is given as it can, returning results indicating success or failure for each record. This is enabled by setting the function's allOrNone parameter to false and by capturing the returned results:

Database.SaveResult[] spdResults = Database.update(sptToUpdate, false);
Database.SaveResult[] prospectResults = Database.update(prospectToUpdate, false);

You then need to take those results and find the data representing those errors that happened. First, make sure you have some new state to track this information in your batch (which is already Stateful if you look at what it implements):

public class BulkValidateSalesPlanBatchUpdate implements ... {
    // Holds the failures that happen during batch execution
    private List<String> failures = new List<String>();
    ...

(Note I suggest your batch be public rather than global - and the same for your member variables (likely want to be private) and methods; it is very, very unlikely it actually needs to be global. This access modifier has very specific usage.)

Now you have that, just collect the failures in execute after those Database.update calls, e.g.:

// Now collect the failures together for sending out once the batch finishes
List<Database.SaveResult> allResults = new List<Database.SaveResult>(spdResults);
allResults.addAll(prospectResults);

for (Database.SaveResult result : allResults) {
    if (!result.isSuccess()) {
        for (Database.Error error : result.getErrors()) {
            failures.add(error.getMessage());
        }
    }
}

The final piece is to ensure that the failures are added to some notification, such as an email, from within the finish method. You'll find a gist for this here. Just generate the email body with the list of strings in some way.

You can make this more comprehensive and include detail of the specific record (e.g. ID) for which the update failed if you want. I leave that as an exercise for you.

1
  • Hy, thank you for the answer, but iam still new in salesforce, iam kinda confused about it, if u dont mind, i already edit my question, and there is my batch code, can you explain based on it? or tell me where is that i should change? it means alot, thanks Commented Apr 6, 2022 at 7:44

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .