Speed up your HTTP calls with parallele HttpClientRequest API calls! Ideal for batching unit calls.
πππ
Business Case
Use async HttpClientRequest executions for External Delivery that calls a vendor with unit API calls. Here, the Delivery has a Routing of type βExternalβ with a Post-Processing workflow containing: a Signal, an Javascript code for initialization, a File Loading (containing broadlog id & content), Update date to Update braodlogs status to Pending and the Javascript code with API calls:
Note: Updating broadlogs Status=Pending is not required if the Delivery Retrieval Mode is set to Manual. Please check Delivery Setup Chapter.
Javascript code
// get data from previous activity
var query = NLWS.xtkQueryDef.create({queryDef:{
schema:vars.targetSchema, operation: "select", lineCount: 9999999,
select:{node:[
{expr: '@id', alias: '@recordId'},
{expr: "@deliveryId"},
]}
}});
var records = query.ExecuteQuery().getElements();
var endpoint = getOption('endpoint');
var apiKey = getOption('apiKey');
// Async API calls: for faster execution, we do N API call at a time
// @see https://docs.adobe.com/content/help/en/campaign-classic/technicalresources/api/c-HttpClientRequest.html
var recCount = vars.recCount; // optimisation: to make sure it's not a XML parsing, we store it as a Javascript variable
var requests = []; // use to store all HttpClientRequest for "HttpClientRequest.wait(requests)"
// function called after each async API call
var onComplete = function(request, context, status){
try {
// any request field may be used i.e. the API key header
logInfo(req.header["X-API-Key"]);
// any context value may be used, i.e. the record id
var recordId = context.recordId;
// get response data
var response = request.response;
// for example, parse XML
var xmlDoc = DOMDocument.fromXMLString(String(resp.body));
// get a node
var node1 = xmlDoc.getElementsByTagName("node1");
var valueNode1 = State[0].childNodes[0].nodeValue;
// update current temporary table
var sql = "UPDATE "+vars.tableName+" SET sNode1 = '"+valueNode1+"' WHERE iId = "+recordId;
sqlExec(sql);
logInfo('onComplete Success for recordId: '+recordId+', node1: '+valueNode1+', Context_'+context.id+'. Progress: '+(recCount-records.length)+'/'+recCount);
} catch(e) {
logWarning('Exception for response', resp.body);
}
// call next
sendNext(context);
}
// for each record
function sendNext(context) {
// Repeat until the first execute() passes
while(records.length != 0) {
// get and remove first element
var record = records.shift();
// store recordId in context
context.recordId = record.$recordId; // used by onComplete function to update the temp table
var req = new HttpClientRequest(endpoint);
req.complete = onComplete;
req.header["Content-Type"] = "text/xml; charset=utf-8";
req.header["X-API-Key"] = apiKey;
req.method = "POST";
req.body = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sms="SMS">' +
// [...]
'</soapenv:Envelope>';
try {
var hasProxy = false;
var async = true;
var timeout = 2000;
req.execute(hasProxy, async, timeout, context);
requests.push(req);
return;
} catch(error){
logWarning('Error while getting response for broadLogId '+record.$recordId+', continue. Error:', error);
continue; // continue because not called by onComplete
}
}
}
// Start N requests with context as a JSON
sendNext({id: 1});
sendNext({id: 2});
sendNext({id: 3});
sendNext({id: 4});
sendNext({id: 5});
sendNext({id: 6});
// Wait until all requests are completed
HttpClientRequest.wait(requests);
logInfo('Javascript done');
Documentation for HttpClientRequest.execute: Adobe Campaign JsAPI - HttpClientRequest asynchronous
Appendix: External Delivery setup
Post-Processing workflow
Create an empty Workflow fcoAsyncPostProcessing
.
Routing
Create a new /Administration/Platform/External Account
with:
- Name:
fcoAsyncRouting
- Type:
Routing
- Enabled:
Yes
- Delivery Mode:
External
- Post-Processing:
fcoAsyncPostProcessing
Delivery Template
Create a new Delivery with:
- General: Routing:
fcoAsyncPostProcessing
- Analysis: Retrieval mode:
A result file determines sent and failed messages
(upon delivery execution, broadlogs will have Status=Pending. Documentation for Delivery Validation: Adobe Campaign Classic - Sending Direct Mail)