如何修复 System.LimitException:Apex CPU 时间限制超出了由带有电子邮件警报的工作流引起的?
How to fix System.LimitException: Apex CPU time limit exceeded caused by workflows with email alert?
我正在尝试对 100 条记录执行批测试方法并出现 CPU 运行时限制错误。
我在我的代码中放置了 Limits.getCpuTime() 方法并注意到我的没有工作流段的代码需要 3148 毫秒才能完成。但是,当我激活两个分别向一个用户发送电子邮件的工作流时,我收到 CPU 运行时限制错误。在没有这两个工作流的情况下,我的过程总共需要大约 10 秒才能完成,而激活它们则需要大约 20 秒。
@IsTest
static void returnIncClientAddress(){
//Select Required Records
User incidentClient = [SELECT Id FROM User WHERE Username = 'bbaggins@shire.qa.com' LIMIT 1];
BMCServiceDesk__Category__c category = [SELECT Id FROM BMCServiceDesk__Category__c WHERE Name = 'TestCategory'];
BMCServiceDesk__BMC_BaseElement__c service = [SELECT ID FROM BMCServiceDesk__BMC_BaseElement__c WHERE Name = 'TestService'];
BMCServiceDesk__BMC_BaseElement__c serviceOffering = [SELECT ID FROM BMCServiceDesk__BMC_BaseElement__c WHERE Name = 'TestServiceOffering'];
//Create Incidents
List<BMCServiceDesk__Incident__c> incidents = new List<BMCServiceDesk__Incident__c>();
for(integer i = 0; i < 100; i++){
BMCServiceDesk__Incident__c incident = new BMCServiceDesk__Incident__c(
BMCServiceDesk__FKClient__c = incidentClient.ID,
BMCServiceDesk__FKCategory__c = category.ID,
BMCServiceDesk__FKServiceOffering__c = serviceOffering.ID,
BMCServiceDesk__FKBusinessService__c = service.ID,
BMCServiceDesk__FKStatus__c = awaiting_for_handling
);
incidents.add(incident);
}
test.startTest();
insert incidents;
test.stopTest();
}
我希望电子邮件工作流和警报能够在 CPU 时间内批量处理和发送,但似乎 Salesforce 需要花费大量时间来检查工作流规则和执行它们需要的时候。流程的大部分时间似乎都花在了发送工作流的电子邮件上(实际上并没有这样做,因为它是一种测试方法)。
您无法控制工作流规则的执行时间。您可以尝试将它们转换为 Apex 并进行基准测试,看看这是否会导致时间消耗的改善,但我怀疑真正的解决方案是您将不得不减少批量测试。
交易的 CPU 限制是 10 秒。如果你的单元测试代码在没有工作流的情况下已经花费了大约 10 秒来完成(我不确定你的 3148 毫秒和 10 秒指的是什么界限),你真的只有两个选择:
- 使插入此对象的自动化总和 运行 更快;
- 减少您在此单元测试中处理的数据量。
不清楚您在这里实际测试的是什么,但如果它是 Apex 触发器,您应该确保它被适当地批量化并且不会消耗不必要的 CPU 时间,包括通过触发器递归。查看日志中的调用堆栈(或简单地添加 System.debug()
语句)可能对此有所帮助。
最后 - 确保在测试方法中编写断言。没有断言的测试方法几乎毫无价值。
BMCServiceDesk__Incident__c 或工作流修改的对象上是否有触发器?更新触发器可能会导致代码在同一执行上下文中执行多次,从而导致您达到 cpu 限制。如果满足特定条件,请考虑防止重新进入触发器或仅对 运行 个触发器执行检查。
否则,请考虑重构代码,如果可能的话,尽可能在同一个循环中执行工作,因为循环尤其是嵌套循环会增加您的 cpu 使用率。通常工作流本身不会提高 CPU 限制,除非由于工作流更新而执行触发器。
我正在尝试对 100 条记录执行批测试方法并出现 CPU 运行时限制错误。
我在我的代码中放置了 Limits.getCpuTime() 方法并注意到我的没有工作流段的代码需要 3148 毫秒才能完成。但是,当我激活两个分别向一个用户发送电子邮件的工作流时,我收到 CPU 运行时限制错误。在没有这两个工作流的情况下,我的过程总共需要大约 10 秒才能完成,而激活它们则需要大约 20 秒。
@IsTest
static void returnIncClientAddress(){
//Select Required Records
User incidentClient = [SELECT Id FROM User WHERE Username = 'bbaggins@shire.qa.com' LIMIT 1];
BMCServiceDesk__Category__c category = [SELECT Id FROM BMCServiceDesk__Category__c WHERE Name = 'TestCategory'];
BMCServiceDesk__BMC_BaseElement__c service = [SELECT ID FROM BMCServiceDesk__BMC_BaseElement__c WHERE Name = 'TestService'];
BMCServiceDesk__BMC_BaseElement__c serviceOffering = [SELECT ID FROM BMCServiceDesk__BMC_BaseElement__c WHERE Name = 'TestServiceOffering'];
//Create Incidents
List<BMCServiceDesk__Incident__c> incidents = new List<BMCServiceDesk__Incident__c>();
for(integer i = 0; i < 100; i++){
BMCServiceDesk__Incident__c incident = new BMCServiceDesk__Incident__c(
BMCServiceDesk__FKClient__c = incidentClient.ID,
BMCServiceDesk__FKCategory__c = category.ID,
BMCServiceDesk__FKServiceOffering__c = serviceOffering.ID,
BMCServiceDesk__FKBusinessService__c = service.ID,
BMCServiceDesk__FKStatus__c = awaiting_for_handling
);
incidents.add(incident);
}
test.startTest();
insert incidents;
test.stopTest();
}
我希望电子邮件工作流和警报能够在 CPU 时间内批量处理和发送,但似乎 Salesforce 需要花费大量时间来检查工作流规则和执行它们需要的时候。流程的大部分时间似乎都花在了发送工作流的电子邮件上(实际上并没有这样做,因为它是一种测试方法)。
您无法控制工作流规则的执行时间。您可以尝试将它们转换为 Apex 并进行基准测试,看看这是否会导致时间消耗的改善,但我怀疑真正的解决方案是您将不得不减少批量测试。
交易的 CPU 限制是 10 秒。如果你的单元测试代码在没有工作流的情况下已经花费了大约 10 秒来完成(我不确定你的 3148 毫秒和 10 秒指的是什么界限),你真的只有两个选择:
- 使插入此对象的自动化总和 运行 更快;
- 减少您在此单元测试中处理的数据量。
不清楚您在这里实际测试的是什么,但如果它是 Apex 触发器,您应该确保它被适当地批量化并且不会消耗不必要的 CPU 时间,包括通过触发器递归。查看日志中的调用堆栈(或简单地添加 System.debug()
语句)可能对此有所帮助。
最后 - 确保在测试方法中编写断言。没有断言的测试方法几乎毫无价值。
BMCServiceDesk__Incident__c 或工作流修改的对象上是否有触发器?更新触发器可能会导致代码在同一执行上下文中执行多次,从而导致您达到 cpu 限制。如果满足特定条件,请考虑防止重新进入触发器或仅对 运行 个触发器执行检查。 否则,请考虑重构代码,如果可能的话,尽可能在同一个循环中执行工作,因为循环尤其是嵌套循环会增加您的 cpu 使用率。通常工作流本身不会提高 CPU 限制,除非由于工作流更新而执行触发器。