Salesforce批量作业报错:SBQQ队列可执行任务数量超限
核心原因
这个错误是Salesforce CPQ(SBQL命名空间)的内部限制导致的:CPQ规定在单个事务中,最多允许添加2个其内部的Queueable作业,而你的批量作业在同一个execute事务中循环处理Contract记录时,每次调用RAM_Uplift工具类都会触发CPQ内部的Queueable任务,累计数量超过2就触发了这个LimitException。
即使你是逐个处理记录,只要所有处理逻辑都在Batch的同一个execute事务中,CPQ内部的Queueable任务计数就会累加,不会因为单条处理而重置限制。
具体排查方向
- 检查
RAM_Uplift工具类的实现:确认是否在处理单个Contract时,调用了CPQ提供的方法(例如SBQQ.UpliftService或类似的CPQ服务类),这类方法内部会自动生成CPQ专属的Queueable作业,而CPQ对这类作业的单事务数量限制为2,远低于Salesforce标准的Queueable单事务50个的限制。 - 确认Batch的
execute方法是单事务:Salesforce Batch Apex的execute方法默认将整个Chunk的处理放在一个事务中,无论Chunk内有多少条记录,所有操作共享同一个事务的资源限制。
解决方案
方案1:调整Batch Chunk Size
将Batch的start方法中返回的QueryLocator或Iterable的Chunk Size设置为2,确保每个execute事务最多处理2条Contract记录,对应触发2个CPQ内部Queueable作业,刚好符合限制:
public Database.QueryLocator start(Database.BatchableContext bc) { String query = 'SELECT Id FROM Contract WHERE ...'; return Database.getQueryLocator(query); } // 调用Batch时指定chunk size Database.executeBatch(new UpliftBatch(), 2);
方案2:用自定义Queueable隔离每个Contract的处理
将单条Contract的处理逻辑封装到自定义Queueable类中,让每条记录的处理在独立事务中执行,这样每个事务只会触发1个CPQ内部Queueable作业,不会触发累计限制:
// 自定义Queueable类 public class UpliftContractProcessor implements Queueable { private Id contractId; public UpliftContractProcessor(Id cId) { contractId = cId; } public void execute(QueueableContext context) { Contract targetContract = [SELECT Id FROM Contract WHERE Id = :contractId]; RAM_Uplift.processContract(targetContract); } } // 修改Batch的execute方法 public void execute(Database.BatchableContext bc, List<Contract> scope) { for(Contract c : scope) { System.enqueueJob(new UpliftContractProcessor(c.Id)); } }
注意:Salesforce标准限制单个事务最多可添加50个Queueable作业,因此如果Batch的Chunk Size超过50,需要调整Chunk Size为50,避免触发标准Queueable限制。
方案3:检查CPQ批量处理能力
查看CPQ是否提供了批量处理Uplift的API,避免逐个触发Queueable作业。例如,是否存在SBQQ.UpliftService.processMultiple之类的方法,可一次性处理多个Contract,从而减少Queueable作业的生成数量。
内容的提问来源于stack exchange,提问作者A Person

