提问人:bnthsrikanth 提问时间:11/15/2023 最后编辑:bnthsrikanth 更新时间:11/16/2023 访问量:43
是否有任何改进代码性能的余地?
Is there any scope to improve my code performance?
问:
我有一个 Salesforce Apex REST 服务 (LeadService),它以 JSON 格式处理传入的潜在客户。此外,我正在寻找增强错误处理并使代码更易于维护的方法。为优化批量更新插入过程和增强整体代码结构提供建议或改进
@RestResource(urlMapping='/api/lead')
global class Service {
@HttpPost
global static string createdata(){
RestResponse res = Restcontext.response;
String requestBody = RestContext.request.requestBody.toString();
try {
// Deserialize JSON data into a list of LeadDataDeserializer objects
List<LeadDataDeserializer> externalLeads = (List<LeadDataDeserializer>)
JSON.deserializeStrict(requestBody, List<LeadDataDeserializer>.class);
// Transform LeadDataDeserializer objects into Lead data
List<Lead> students = new List<Lead>();
for(LeadDataDeserializer info : externalLeads) {
Lead t_leads = setLeadFields(info);
t_leads.company='Test Company';
students.add(t_leads);
}
if(students.isEmpty()){
res.statusCode=400;
return 'Empty list';
}
else{
List<Response> responseretn=new List<Response>();
Database.UpsertResult[] srList = Database.upsert(students, Lead.External_Id__c, false);
// Process upsert results if needed
Integer i=0;
for(Database.UpsertResult upResult:srList){
if(upResult.isSuccess()){
responseretn.add(new Response(upResult.getId(),true,students[i].MobilePhone));
}
else{
System.debug(upResult.getErrors());
responseretn.add(new Response(upResult.getId(),false,students[i].MobilePhone));
}
i+=1;
}
String jsonReqBody=JSON.serialize(responseretn);
res.statusCode = 201;
return jsonReqBody;
}
} catch(Exception e) {
// Handle exceptions
res.Statuscode = 500;
return 'Internal Server Error';
}
}
//Response wrapper to return
public class Response{
public string leadId{get;set;}
public boolean isSuccess{get;set;}
public string mobilePhone{get;set;}
public Response(String leadId,Boolean isSuccess,String mobilePhone){
this.leadId=leadId;
this.isSuccess=isSuccess;
this.mobilePhone=mobilePhone;
}
}
public static Lead setLeadFields(LeadDataDeserializer info){
Lead extLead=new Lead();
extLead.LastName=info.Name;
extLead.CountryCode__c=info.countryCode;
extLead.MobilePhone=info.phoneNumber;
extLead.mx_WhatsApp_Number__c=extLead.MobilePhone;
extLead.mx_IP_Address__c=info.ipAddress;
extLead.External_Id__c=extLead.MobilePhone;
if(info.leadStage!=null){
extLead.Status=info.leadStage;
}
if(info.campaignName!=null){
extLead.mx_Campaign_Name__c=info.campaignName;
}
if(info.campaignSource!=null){
extLead.SourceCampaign__c=info.campaignSource;
}
//20 more if conditions with null check like above (serializeddata.field!=null)
return extLead;
}}
我使用多个 if 语句来处理仅包含具有值的字段,并且如果来自集成的值为空,则不会覆盖上一个记录值
如何有效地处理这个问题?
答:
if(students.isEmpty()){
res.statusCode=400;
return 'Empty list';
}
这有点晚了。性能不会有太大变化,但从逻辑上讲,最好早点检查反序列化列表,然后返回,而不是在从中获取潜在客户之后。
我认为您不必返回字符串。您可以轻松返回,SF 将为您序列化。List<Response>
你想如何处理问题?尽你所能保存?您可以为任何问题插入帮助程序 sObject 并运行有关该问题的报告。或者使用带有“立即发布”的平台事件,以便一些监控系统甚至特殊的顶点触发器可以处理它们。
我可能会包括错误计数器,所以如果它是 100% 的失败率,则返回 201 以外的其他内容
如果它发送> 10K 行怎么办(否则副作用将导致> 10K dmls)......如果这是一个合理的问题,我可能会重写它以启动批处理作业(批处理可以获取范围并迭代它,它们并不总是必须从查询开始)。您可以和工作几乎完成的奖励点,SF 将为您做很多错误处理,而无需手动“保存点-尝试-捕获-回滚-插入任务或其他任何任务”implements Database.RaisesPlatformEvents
至于实际的映射代码......它不是很好,但也不是很糟糕。对于空检查,你可能觉得它有点太幼稚了 - 因为某些变量会更好,这取决于源生成的 JSON。String.isNotBlank
我会将源-目标字段映射保存在其他地方(自定义设置?自定义元数据?),这样您就不必在每次添加新字段时重新编译、部署等。
如果你真的觉得很奇特,你可以阅读有关JSON.serialize的信息,并带有跳过空值的参数(例如,你可以反序列化输入,在跳过空值的情况下将其序列化回来,第二次反序列化,干净)。或者盲目地根据输入设置所有字段,然后 sObject.getPopulatedFieldsAsMap 并遍历它们,检查什么是空的......但对于需要的东西来说,感觉有点太聪明了。有时简单是最有效的。
它甚至必须是自定义 REST API 吗?如果你能控制源格式,你可以考虑复合
而不是标准api,减少工作量。看看我的 https://salesforce.stackexchange.com/a/274696/799(包括“allOrNone”标题)。正常的更新插入不能很好地处理多个记录,没错 - 但这已经足够接近了!
嗯......代码并不总是答案。如果您绝对确定标准 API 不会削减它 - 您知道可以通过 REST API 调用流吗?
====
编辑
这是一个很好的示例(您可以在“匿名执行”中运行它
public class Wrapper {
public Boolean isActive;
public String name;
public String email;
public String phone;
}
String text = '['+
' {'+
// ' \"isActive\": false,'+
' \"name\": \"Blankenship Ryan\",'+
' \"email\": \"[email protected]\",'+
' \"phone\": \"+1 (803) 465-3324\"'+
' },'+
' {'+
' \"isActive\": false,'+
// ' \"name\": \"Herring Blevins\",'+
' \"email\": \"[email protected]\",'+
' \"phone\": \"+1 (938) 592-2521\"'+
' },'+
' {'+
' \"isActive\": true,'+
' \"name\": \"Paige Holman\",'+
// ' \"email\": \"[email protected]\",'+
' \"phone\": \"+1 (968) 576-3874\"'+
' },'+
' {'+
' \"isActive\": false,'+
' \"name\": \"Meadows Clemons\",'+
' \"email\": \"[email protected]\"'+ // removed comma here
// ' \"phone\": \"+1 (806) 463-3276\"'+
' },'+
' {'+
' \"isActive\": true,'+
' \"name\": \"Shawna Holt\",'+
' \"email\": \"[email protected]\",'+
' \"phone\": \"+1 (956) 542-2138\"'+
' },'+
' {'+
// ' \"isActive\": false,'+
// ' \"name\": \"Tonya Britt\",'+
// ' \"email\": \"[email protected]\",'+
// ' \"phone\": \"+1 (845) 543-2721\"'+
' }'+
']';
System.debug(text);
List<Wrapper> wrappers = (List<Wrapper>) JSON.deserializeStrict(text, List<Wrapper>.class);
System.debug('nulls should show');
System.debug(wrappers);
List<Wrapper> wrappers2 = new List<Wrapper>();
for(Wrapper w : wrappers){
String stripped = JSON.serialize(w, true);
System.debug('should have no nulls: ' + stripped);
Wrapper w2 = (Wrapper) JSON.deserialize(stripped, Wrapper.class);
System.debug('but deserialized - they pop back: ' + w2);
}
反序列化才是问题所在,即使您的源系统不发送 null。
在 https://salesforce.stackexchange.com/questions/257158/json-serialize-is-it-possible-to-suppress-null-values-of-a-map 中有一些技巧,您可以使用或循环遍历潜在客户的 getPopulatedFieldsAsMap,并将它们复制到最终潜在客户,只有当它们不是 null 时才会进行更新插入......但这听起来有点聪明,你可读的 if 列表没有错。是的,这很无聊,也许可以从一些配置中读取......但它有效。
评论
global static List< Response> createdata(){
评论