Taggarkiv: Data Source

ServiceNow’s OOB utmaningar kring att ta emot strömmat data i stora mängder (läs response paket större än 32 Mb för datatypen String). För att gå runt utmaningen har jag löst det genom att spara svaret oströmmat som ett attachment (datatyp: String)


var r = new sn_ws.RESTMessageV2("xxxx", "yyyy");
r.setBasicAuth(ssss, rrrr);
var response = r.execute();
response.waitForResponse(200);
//Write the huge attachment from response body
var attachSysId = this.attachment.write(<GlideRecord>, <filnamn>, 'plain/text', response.getBody());

Nu har vi svaret som en bifogad fil så nu behöver vi göra det lilla ”magiska” och strömma tillbaka svaret i mindre portioner.


var arrayNumber = this.getStreamAndParseArray(attachSysId);

getStreamAndParseArray: function(attachSysId) {
var inputStream = this.attachment.getContentStream(attachSysId);
var reader = new GlideTextReader(inputStream);
var ln = ' ';
this["responseArray1"] = [];
var arrayNumber =  1;
var threadhold = 15000;
while ((ln = reader.readLine()) != null) {
    if (this.loopIndex == (threadhold * arrayNumber)) {
	/*If the response from XXXX are to big to handle the normal ServiceNow way we need to split the huge attachment into smaller chunks. In this case I have choosen the number of 15000 records per String Array*/
	arrayNumber++;
	this["responseArray"+arrayNumber] = []; 
    }
    this["responseArray"+arrayNumber].push(ln);
    this.loopIndex++;
    }
    return arrayNumber;
}

Efter jobbet att gå igenom hela strömmen uppdelat på xx antal array (responseArray) så ska jag ladda en Datakälla (data source) som sedan gör själva jobbet och det går med speed lightning. Lösningen jag valde här är att skapa en CSV fil som är enkel och mycket snabb, obefintlig ”overhead” som ex finns för både SOAP och REST protokollen. Varje Array blir en fil som sparas i vald datakälla som då laddas och transformeras osv tills alla Array är klara.


doLoadAndTransform: function(arrayNumber, dataSource, filename, attachSysId, firstTransformName) {
//Parse and create a new CSV file, more easy for ServiceNow to handle
for (var parsedArrayCount = 1; parsedArrayCount <= arrayNumber; parsedArrayCount++) {
	gs.log('XXXX parsed # array: ' + this["responseArray" + parsedArrayCount].length);
	var stringJson = '{"import": [' + this["responseArray" + parsedArrayCount] + ']}';
	var parsedJson = JSON.parse(stringJson);
	var csv = this.createCSVObject(parsedJson['import']);
	//Attach the newly created CSV file to our Data Source
	attachSysId = this.attachment.write(dataSource, filename, 'plain/text; charset=utf-8', csv);
	//Initiate DataSourceLoader and call the load function to do the actual load and tranforms
	var ret = this.dt.load(dataSource.getValue('sys_id'), firstTransformName, false);
	gs.log('XXXX DataSource loaded for array #' + parsedArrayCount + ' of total #' + arrayNumber);
	//Delete the current Array file/attachment from the Data Source record
	gs.log('XXXX try to delete loaded attachment');
	this.deleteAttachments(filename, dataSource.getValue('sys_id'));
	}
}

Ett exempel att skapa en CSV variable från ett JSON


createCSVObject: function(json) {
  var fields = Object.keys(json[0]);
  var replacer = function (key, value) {
	return value === null ? '' : value;
  };
  var csv = json.map(function (row) {
	return fields.map(function (fieldName) {
	return JSON.stringify(row[fieldName], replacer);
  }).join(';');
  });
  csv.unshift(fields.join(';'));
  csv = csv.join('\r\n');
  return csv;
}

Frågor eller synpunkter, kommentera gärna!