我有一个 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';
}
这有点晚了。性能不会有太大变化,但从逻辑上讲,最好尽早检查反序列化列表然后返回,而不是在从中找出线索之后返回。
我认为您不必返回字符串。您可以轻松退货
List<Response>
,SF会为您连载。
您想如何处理问题?能省点就省点吧?您可以针对任何问题插入 helper sObject 并运行报告。或者使用“立即发布”的平台事件,以便某些监控系统甚至特殊的顶点触发器可以处理它们。
我可能会包含错误计数器,因此如果失败率为 100%,则返回 201 以外的内容
如果它发送 > 10K 行(或者副作用将导致 > 10K dml)怎么办...如果这是一个合法的问题,我可能会重写它来启动批处理作业(批处理可以占用范围并迭代)除此之外,他们并不总是必须以查询开始)。奖励积分你可以
implements Database.RaisesPlatformEvents
并且工作几乎完成,SF将为你做很多错误处理,而不需要手动“保存点-尝试-捕获-回滚-插入任务或其他”
至于实际的映射代码......它不是很好,但也不是很糟糕。您可能对 null 检查有点过于天真 - 对于某些变量
String.isNotBlank
会更好,具体取决于源生成的 JSON。
我会将源-目标字段映射保留在其他地方(自定义设置?自定义元数据?),这样您就不必在每次添加新字段时重新编译、部署等。
如果您真的很喜欢,您可以阅读有关 JSON.serialize 的内容,其中包含跳过空值的参数(例如,您可以反序列化输入,将其序列化回跳过空值,第二次反序列化,干净)。或者盲目地根据输入设置所有字段,然后 sObject.getPopulatedFieldsAsMap 并迭代它们检查什么是空的......但对于需要的东西来说感觉有点太聪明了。有时候简单就是最有效的。
它是否必须是自定义 REST API?如果您可以控制源格式,您可以考虑使用
composite
标准 api,减少工作量。看看我的 https://salesforce.stackexchange.com/a/274696/799 (包括“allOrNone”标头)。正常的 upsert 不能很好地处理多个记录,这是真的 - 但这已经足够接近了!
嗯……代码并不总是答案。如果您绝对确定标准 API 不会解决问题 - 您知道可以通过 REST api 调用 flows 吗?