如何处理Apex批处理中的SerialBatchApexRangeChunkHandler内部Salesforce.com错误
我正在批量更新一些帐户记录。但是,每当更新由于某些验证逻辑而失败时(在本例中,数字太长),批处理就会陷入处理模式,我必须手动中止它。在日志中,我看到操作:SerialBatchApexRangeChunkHandler状态:Internal Salesforce.com Error。如果我删除Database.Stateful,那么批处理就会完成,但是我需要在电子邮件中提供错误详细信息,所以我必须实现它 如果需要更多细节,请帮助我并让我知道如何处理Apex批处理中的SerialBatchApexRangeChunkHandler内部Salesforce.com错误,salesforce,apex,Salesforce,Apex,我正在批量更新一些帐户记录。但是,每当更新由于某些验证逻辑而失败时(在本例中,数字太长),批处理就会陷入处理模式,我必须手动中止它。在日志中,我看到操作:SerialBatchApexRangeChunkHandler状态:Internal Salesforce.com Error。如果我删除Database.Stateful,那么批处理就会完成,但是我需要在电子邮件中提供错误详细信息,所以我必须实现它 如果需要更多细节,请帮助我并让我知道 global class testBatchSetti
global class testBatchSettingsAndDebug implements Database.Batchable<sobject>, Database.Stateful {
global String[] email= new String[] {'email@domain.com'};
global List<Database.saveResult> dsrs = new List<Database.saveResult>();
global String errorMessages {get; set;}
global integer count=0;
global List<String> exception_List;
global testBatchSettingsAndDebug (){
errorMessages ='';
}
//Start
global Database.QueryLocator start (Database.BatchableContext bc){
return Database.getQueryLocator('select id from Account limit 10');
}
//Excecute
global void execute (Database.BatchableContext bc, List<sobject> scope){
List<Account > accToUpdateLsit = new List<Account >();//List to hold accs to update
for (sObject objScope: scope) {
Account accObj = (Account )objScope ;//type casting from generic sOject to acc
accObj.NumberofLocations__c= 123456;
accToUpdateLsit.add(accObj);
}
count=accToUpdateLsit.size();
System.debug('Number of Records to update: '+accToUpdateLsit.size());
if (accToUpdateLsit != null && accToUpdateLsit.size()>0) {//Check if List is empty or not
dsrs = Database.update(accToUpdateLsit, false);
System.debug('Records are successfully updated '+accToUpdateLsit);//Update the Records
}
for(Database.SaveResult dsr : dsrs){
if(!dsr.isSuccess()){
errorMessages += string.valueof(dsr.geterrors() + '\n');
}
}
system.debug('Error occured: '+errorMessages);
}
//Finish
global void finish (Database.BatchableContext BC){
System.debug('**Record Updated**'+count);
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
//Below code will fetch the job Id
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()];//get the job Id
System.debug('Jobid is'+BC.getJobId());
//below code will send an email to User about the status
mail.setToAddresses(email);
mail.setReplyTo('email@domain.com');//Add here your email address
mail.setSenderDisplayName('Account Batch Notification');
mail.setSubject('Account Batch Batch Processing '+a.Status);
mail.setPlainTextBody('The Batch Apex job processed: '+a.TotalJobItems+' batches with: '+a.NumberOfErrors+' failures: '+' Error Messages:'+errorMessages );
Messaging.sendEmail(new Messaging.Singleemailmessage [] {mail});
System.debug('**Job completed**');
}
}
全局类TestBatchSettings和Debug实现Database.Batchable、Database.Stateful{
全局字符串[]电子邮件=新字符串[]{'email@domain.com'};
全局列表dsrs=新列表();
全局字符串错误消息{get;set;}
全局整数计数=0;
全局列表异常列表;
全局testBatchSettingsAndDebug(){
errorMessages='';
}
//开始
global Database.QueryLocator启动(Database.BatchableContext bc){
return Database.getQueryLocator('select id from Account limit 10');
}
//过分的
全局void execute(Database.BatchableContext bc,列表范围){
List ACCTOUPDATESIT=new List();//保存要更新的accs的列表
对于(sObject对象范围:scope){
Account accObj=(Account)objScope;//从泛型sOject到acc的类型转换
accObj.地点数量=123456;
ACCTOUPDATESIT.add(accObj);
}
count=acctupdatesit.size();
System.debug('要更新的记录数:'+ACCTOUPDATESIT.size());
如果(ACCTOUPDATESIT!=null&&ACCTOUPDATESIT.size()>0){//检查列表是否为空
dsrs=Database.update(acctupdatesit,false);
System.debug('记录已成功更新'+ACCTOUPDATESIT);//更新记录
}
对于(Database.SaveResult dsr:dsrs){
如果(!dsr.issucess()){
errorMessages+=string.valueof(dsr.geterrors()++'\n');
}
}
system.debug('发生错误:'+错误消息);
}
//完成
全局void完成(Database.BatchableContext BC){
系统调试('**记录更新**'+计数);
Messaging.SingleEmailMessage mail=新建消息。SingleEmailMessage();
//下面的代码将获取作业Id
AsyncApexJob a=[从AsyncApexJob a中选择a.TotalJobItems、a.Status、a.NumberOfErrors、a.JobType、a.JobItemsProcessed、a.ExtendedStatus、a.CreatedById、a.CompletedDate,其中id=:BC.getJobId()];//获取作业id
debug('Jobid是'+BC.getJobId());
//下面的代码将向用户发送有关状态的电子邮件
mail.SetToAddresss(电子邮件);
mail.setReplyTo('email@domain.com“);//在这里添加您的电子邮件地址
mail.setSenderDisplayName(“帐户批处理通知”);
mail.setSubject('科目批处理'+a.Status);
mail.setPlainTextBody('处理的批处理作业:'+a.TotalJobItems+'批处理:'+a.NumberOfErrors+'失败:'+'错误消息:'+errorMessages');
Messaging.sendmail(newmessaging.Singleemailmessage[]{mail});
调试(“**作业已完成**”);
}
}
看起来你可以做工作中提到的事情,比如:
声明您的数据库。saveResult那么为什么您只查询帐户ID,而设置NumberofLocations\uu\c字段呢?这是行不通的。或者这只是一个例子?这只是一个例子来说明我所面临的问题。在实际代码中,它具有基于业务逻辑的where逻辑。但问题是相同的,当更新过程中由于某些验证逻辑而出现错误时,批处理会被卡住。我在一个中断批处理的流程(使用process builder创建)中遇到了类似的问题。但我遇到了一个“正常”Salesforce错误,批处理停止了。在我的情况下,唯一的解决方案是以一种不会干扰批处理的方式更改流程。您是否尝试使用Batchsize 1运行它?也许你会得到更好的错误结果我的要求很简单。假设我正在更新10条记录,如果其中5条由于任何验证而未能更新,我希望在电子邮件中显示计数、记录ID和错误。我不知道为什么不会发生这种情况。请将您的答案更新为“将Database.SaveResult声明为transient”。)我不能做数据库更新(ACCTOUPDATESIT,true);因为我必须接受部分更新。我将Database.SaveResult声明为transient。工作得很好。