我们遇到了可排队的顶点问题。如果你可以提供帮助,那太棒了?
他们的要求是将Salesforce对象同步到外部系统。
目前有一个触发器执行可排队的顶点作业,该作业在结束时执行调出和更新。
这在我们的测试中非常有效。我们今天也进行了批量测试。然而,随机我们得到以下错误。
我将分享一个示例代码。
错误:1:潜在客户ID:XXXXXXXXXXXXXXXXXX错误:System.CalloutException:您有未提交的待处理工作。请在调用outType之前提交或回滚:System.CalloutException原因:null消息:您有未提交的工作挂起。请在呼叫前提交或回滚
我们只在队列执行结束时进行更新。当我们测试单个或批量负载时,这非常有效。问题是断断续续的。
trigger TRIG_Lead on Lead (before insert, before update, after update, after insert) {
if (Trigger.isAfter) {
if (Trigger.isInsert) {
TRIG_Lead_Handler.afterInsert(Trigger.newMap);
}
if (Trigger.isUpdate) {
TRIG_Lead_Handler.afterUpdate(Trigger.oldMap, Trigger.newMap);
}
}
}
没有共享类的公共TRIG_Lead_Handler {
// A method that will be called by trigger in case of an after insert event
public static void afterInsert(Map<Id, Lead> newMap) {
Map<Id, Lead> optimusLeads = new Map<Id, Lead>();
System.debug('After insert trigger');
// Looping through all leads
for (Id leadId : newMap.keySet()) {
Lead newLead = newMap.get(leadId);
if (newLead.Optimus_Push_Criteria__c
&& newLead.Optimus_External_Id__c == null
&& newLead.Optimus_Push_Scheduled__c
&& !OptimusService.leadScheduledSet.contains(leadId)) {
OptimusService.leadScheduledSet.add(leadId); // to prevent recursive pushes
optimusLeads.put(leadId, newLead);
}
}
if (!optimusLeads.isEmpty()) {
System.enqueueJob(new QuableOptimusService('INSERT', optimusLeads.keySet()));
}
}
public static void afterUpdate(Map<Id, Lead> oldMap, Map<Id, Lead> newMap) {
Map<Id, Lead> convertedLeads = new Map<Id, Lead>();
Map<Id, Lead> optimusLeads = new Map<Id, Lead>();
// Looping through all leads
for (Id leadId : newMap.keySet()) {
// Declaring 2 variables: oldLead and newLead.
// They represent the same lead before and after the update respectively
Lead oldLead = oldMap.get(leadId);
Lead newLead = newMap.get(leadId);
if (newLead.isConverted) {
convertedLeads.put(leadId, newLead);
}
if (newLead.Optimus_Push_Criteria__c
&& newLead.Optimus_External_Id__c == null
&& newLead.Optimus_Push_Scheduled__c && !oldLead.Optimus_Push_Scheduled__c
&& !OptimusService.leadScheduledSet.contains(leadId)) {
OptimusService.leadScheduledSet.add(leadId); // to prevent recursive pushes
optimusLeads.put(leadId, newLead);
}
}
if (!convertedLeads.isEmpty()) {
reparentFeedItemsToConvertedOpportunity(convertedLeads);
}
if (!optimusLeads.isEmpty()) {
System.enqueueJob(new QuableOptimusService('INSERT', optimusLeads.keySet()));
}
}
}
public with share class QuableOptimusService实现Queueable,Database.AllowsCallouts {
String dmlType;
Lead currentProcessedLead;
Set<Id> IdSet;
List<Lead> leadList = new List<Lead>();
Set<Id> syncedIdSet = new Set<Id>();
/**
* Constructor
*/
public QuableOptimusService( String dType, Set<Id> IdSet ) {
this.dmlType = dType;
this.IdSet = IdSet;
}
public void execute(QueueableContext context) {
// Query all the fields required for the service
leadList = [ SELECT Id, Street, PostalCode, City, CreatedDate, Email, Status, Salutation, FirstName, LastName,
Phone, BP_Number__c, MobilePhone, Deal_Comments__c, Degree_of_urgency__c, Housing__c, Language__c,
Lead_Sources_EDF__c, Lead_Sources_Subtypes_EDF__c, Lead_Type__c, Net__c, Name_of_Sales_person__c,
Number_of_Panels__c, Opt_out_communication_PV__c, Payback_Timeframe_in_years__c, Picture__c,
Product_Interest__c, Region_in_Belgium__c, Total_earnings_over_time_horizon__c, Type_of_Web_lead__c,
VAT_Number__c, Sales_Partner__c, Seller_ID__c, Shop_Location__c, Promocode__c, RecordTypeId,
Company, Saving_in__c, Cell_Phone__c, Optimus_External_Id__c
FROM Lead
WHERE Id IN : IdSet AND Optimus_External_Id__c = null ];
List<Lead> leadsToUpdate = new List<Lead>();
OptimusService os = new OptimusService();
try{
Integer i = 0;
for (Lead s : leadList) {
currentProcessedLead = (Lead) s;
if (dmlType != null && dmlType.equalsIgnoreCase('INSERT')) {
currentProcessedLead.Optimus_External_Id__c = os.doLeadCreate(currentProcessedLead);
if(currentProcessedLead.Optimus_External_Id__c != null){
leadsToUpdate.add(currentProcessedLead);
}
} else if (dmlType != null && dmlType.equalsIgnoreCase('UPDATE')) {
os.doLeadUpdate(currentProcessedLead);
}
// Add Synced Lead Ids
syncedIdSet.add(s.Id);
if (++i == 80) {
break;
}
}
// remove synced lead Ids and enqueue again
IdSet.removeAll(syncedIdSet);
if (!IdSet.isEmpty()) {
System.enqueueJob(new QuableOptimusService(dmlType, IdSet));
}
update leadsToUpdate;
} Catch( Exception e) {
System.debug('Error :' +e.getMessage());
}
}
}
公共类OptimusService {
public String doLeadCreate(Lead l) {
system.debug('*** LEAD CREATE');
// login if needed
if (Test.isRunningTest()) accessToken = 'abc';
if (accessToken == null) {
doLogin();
}
// headers
Map<String, String> headers = New Map<String, String>{
'cache-control' => 'no-cache',
'content-type' => 'application/json',
'fm-data-token' => accessToken
};
// body
String body = generateLeadJSON(l);
System.debug('--body--' +body);
// request
HttpRequest req = buildRequest(RECORD_URL + '/' + API_LAYOUT + '/', headers, body);
System.debug('--req--' +req);
// response
HttpResponse res = sendRequest(req);
if (res.getStatusCode() != 200) {
throw new OptimusException('Received error from Optimus Lead Create Webservice: '
+ res.getStatusCode() + ': ' + res.getStatus());
} else {
LeadCreateResponse lcr = handleLeadCreateResponse(res.getBody());
if (lcr != null && lcr.recordId != null) {
return lcr.recordId;
} else{
throw new OptimusException('Lead create response null : '
+ res.getStatusCode() + ': ' + res.getStatus());
}
}
}
public void doLeadUpdate(Lead l) {
system.debug('*** LEAD UPDATE');
// login if needed
if (Test.isRunningTest()) accessToken = 'abc';
if (accessToken == null) {
doLogin();
}
// headers
Map<String, String> headers = New Map<String, String>{
'cache-control' => 'no-cache',
'content-type' => 'application/json',
'fm-data-token' => accessToken
};
// body
String body = generateLeadJSON(l);
System.debug('--body--' +body);
// request
HttpRequest req = buildRequest(RECORD_URL + '/' + API_LAYOUT + '/' + l.Optimus_External_Id__c, headers, body);
System.debug('--req--' +req);
// response
HttpResponse res = sendRequest(req);
if (res.getStatusCode() != 200) {
throw new OptimusException('Received error from Optimus Lead Update Webservice: '
+ res.getStatusCode() + ': ' + res.getStatus());
}
}
@TestVisible
private void doLogin() {
system.debug('*** LOGIN');
// headers
Map<String, String> headers = New Map<String, String>{
'cache-control' => 'no-cache',
'content-type' => 'application/json'
};
// body
String body = generateLoginJSON();
// request
HttpRequest req = buildRequest(AUTH_URL, headers, body);
// response
HttpResponse res = sendRequest(req);
if (res.getStatusCode() == 200) {
LoginResponse logres = handleLoginResponse(res.getBody());
this.accessToken = logres.token;
} else {
throw new OptimusException('Received error from Optimus Login Webservice'
+ res.getStatusCode() + ': ' + res.getStatus());
}
}
private HttpRequest buildRequest(String url, Map<String, String> headers, String body) {
// Instantiate a new HTTP request
HttpRequest req = new HttpRequest();
// Set method and endpoint
req.setEndpoint(url);
req.setMethod('POST');
req.setTimeout(120000);
// Set headers
if (headers != null) {
for (String key : headers.keySet()) {
req.setHeader(key, headers.get(key));
}
}
// Set body
if (body != null && body.length() > 0) {
req.setBody(body);
}
system.debug('*** req: ' + req);
system.debug('*** req.body: ' + req.getBody());
return req;
}
private HttpResponse sendRequest(HttpRequest req) {
// Send HTTP request and get HTTP response
Http http = new Http();
HttpResponse res = http.send(req);
system.debug('*** res.status: ' + res.getStatus());
system.debug('*** res.statuscode: ' + res.getStatusCode());
system.debug('*** res.body: ' + res.getBody());
return res;
}
}
谢谢。
这是在Salesforce Stackexchange here上解决的
基本上,你必须在测试环境中控制你的入队