Hello
I wrote a collection runner and am using an API whose token expires after an hour. Unfortunately, due to the amount of JSON objects returned in another API call I am using in my code, it can take up to 10-15 seconds for one API call. This causes my code to run longer than an hour. I am wondering how I can refresh my token after an hour. Any tips or tricks?
const moment = require('moment');
const today = moment().startOf('day').format("YYYY-MM-DDTHH:mm:ssZ");
function buildQueryString(params) {
return Object.keys(params)
.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
.join('&');
}
function formatDateToZohoCRM(date) {
const centralDate = new Date(date.toLocaleString("en-US", { timeZone: "America/Chicago" }));
return centralDate.toISOString().split('.')[0];
}
const mileageDate = new Date();
const formattedDate = formatDateToZohoCRM(mileageDate);
let RecCnt = pm.environment.get('RecCnt') || 0;
let UpdtCnt = pm.environment.get('UpdtCnt') || 0;
let flag_error = pm.environment.get('flag_error') || 0;
let pm_map_error = pm.environment.get('pm_map_error') || {};
const currentDate = new Date();
const endtime = Math.floor(currentDate.getTime() / 1000);
const stime = new Date(currentDate.getTime() - 7 * 24 * 60 * 60 * 1000);
const starttime = Math.floor(stime.getTime() / 1000);
pm.environment.set("starttime", starttime.toString());
pm.environment.set("endtime", endtime.toString());
const zonarP = pm.environment.get("zonar_p");
const zonarU = pm.environment.get("zonar_u");
const enableUpdates = true;
const perPage = 200;
const maxRecords = 1000;
let offset = pm.environment.get('offset') || 0;
let totalProcessed = pm.environment.get('totalProcessed') || 0;
let allResults = pm.environment.get('allResults') ? JSON.parse(pm.environment.get('allResults')) : [];
console.log("enableUpdates: " + enableUpdates);
const csvFileRow = pm.environment.get('csvFileRow') ? JSON.parse(pm.environment.get('csvFileRow')) : ["VIN,MPG,Odometer,Distance"];
function fetchAllTrucks(offset, limit) {
return new Promise((resolve, reject) => {
pm.sendRequest({
url: `https://www.zohoapis.com/crm/v6/coql`,
method: 'POST',
header: {
'Authorization': `Zoho-oauthtoken ${pm.environment.get('zoho_access_token')}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
"select_query": `SELECT id, Name, Mileage_Last_Updated, Zonar_GPS_ID, Current_Mileage, Lease_Start_Date FROM Trucks WHERE ((Truck_Status = '-Delivered' and Zonar_GPS_ID is not null) and (Mileage_Last_Updated < '${today}' or Mileage_Last_Updated is null)) LIMIT ${limit} OFFSET ${offset}`
})
}, (err, response) => {
if (err) {
reject(err);
} else {
try {
const responseBody = response.text();
if (!responseBody.trim()) {
console.log('Error: No remaining truck data for COQL call');
resolve([]);
} else {
const jsonData = JSON.parse(responseBody);
if ('data' in jsonData) {
resolve(jsonData.data);
} else {
console.log("Error: 'data' key not found in the JSON response");
resolve([]);
}
}
} catch (error) {
reject(new Error("Failed to parse response: " + error.message));
}
}
});
});
}
function fetchZonarData(paramMap) {
const queryParams = buildQueryString(paramMap);
return new Promise((resolve, reject) => {
pm.sendRequest({
url: `https://omi.zonarsystems.net/interface.php?${queryParams}`,
method: 'GET',
timeout: 5000
}, (err, response) => {
if (err) {
reject(err);
} else {
resolve(response.json());
}
});
});
}
function updateRecord(module, id, data) {
return new Promise((resolve, reject) => {
pm.sendRequest({
url: `https://www.zohoapis.com/crm/v2/${module}/${id}`,
method: 'PUT',
header: {
'Authorization': `Zoho-oauthtoken ${pm.environment.get('zoho_access_token')}`
},
body: {
mode: 'raw',
raw: JSON.stringify({ data: [data] })
}
}, (err, response) => {
if (err) {
reject(err);
} else {
resolve(response.json());
}
});
});
}
function sendEmail(subject, message, csvFileName, csvContent) {
return new Promise((resolve, reject) => {
pm.sendRequest({
url: `https://graph.microsoft.com/v1.0/users/${pm.environment.get("microsoft_user_id")}/sendMail`,
method: 'POST',
header: {
Authorization: `Bearer ${pm.variables.get("microsoft_access_token")}`,
'Content-Type': "application/json"
},
body: JSON.stringify({
message: {
subject: subject,
body: {
contentType: "html",
content: `${message}`
},
toRecipients: [{
emailAddress: {
address: pm.environment.get("it_email")
}
}],
attachments: [{
"@odata.type": "#microsoft.graph.fileAttachment",
"name": csvFileName,
"contentType": "text/csv",
"contentBytes": Buffer.from(csvContent).toString('base64')
}]
},
saveToSentItems: "true"
})
}, (err, res) => {
if (err) {
reject(err);
} else {
resolve(res);
}
});
});
}
(async function () {
try {
while (totalProcessed < maxRecords) {
const records = await fetchAllTrucks(offset, perPage);
if (records.length === 0) {
break;
}
const remainingRecords = maxRecords - totalProcessed;
const recordsToProcess = records.slice(0, remainingRecords);
allResults = allResults.concat(recordsToProcess);
totalProcessed += recordsToProcess.length;
if (totalProcessed >= maxRecords) {
break;
}
offset += perPage;
pm.environment.set('offset', offset);
pm.environment.set('totalProcessed', totalProcessed);
pm.environment.set('allResults', JSON.stringify(allResults));
pm.environment.set('RecCnt', RecCnt);
pm.environment.set('UpdtCnt', UpdtCnt);
pm.environment.set('flag_error', flag_error);
pm.environment.set('pm_map_error', pm_map_error);
pm.environment.set('csvFileRow', JSON.stringify(csvFileRow));
// Break the loop to avoid timeout
postman.setNextRequest(null);
return;
}
for (let truck of allResults) {
let final = {};
let final2 = {};
const vin = truck.Name;
const gpsID = truck.Zonar_GPS_ID;
if (gpsID) {
RecCnt++;
const trkID = truck.id;
const InserviceDate = truck.Lease_Start_Date;
const currentMileage = truck.Current_Mileage;
const paramMap = {
customer: custid,
username: zonarU,
password: zonarP,
action: "showposition",
operation: "path",
format: "json",
starttime: starttime,
endtime: endtime,
version: "2",
logvers: "3.8",
reqtype: "vin",
target: vin
};
try {
const actResp = await fetchZonarData(paramMap);
if (actResp.error) {
throw new Error(`Odometer Script Failed on ${vin} with the following error ${actResp}`);
}
const pathEvents = actResp.pathevents;
const assetCount = pathEvents.assetcount;
if (assetCount > 0) {
const asset = pathEvents.assets;
const recordCount = asset[0].eventcount;
let last_odometer = 0, last_distance = 0, first_distance = 0, last_fuel_counter = 0, first_fuel_counter = 0, distance_traveled = 0, mpg = 0;
if (recordCount > 0) {
const events = asset[0].events;
if(recordCount == 1)
{
count = 0;
}
else
{
count = 1;
}
first_distance = parseInt(events[count].distance_traveled || 0, 10);
first_fuel_counter = parseInt((events[count].fuel_counter ? events[count].fuel_counter.replace(",", "") : 0), 10);
last_odometer = parseInt(events[recordCount - 1].odometer || 0, 10);
last_distance = parseInt(events[recordCount - 1].distance_traveled || 0, 10);
last_fuel_counter = parseInt((events[recordCount - 1].fuel_counter ? events[recordCount - 1].fuel_counter.replace(",", "") : 0), 10);
if (last_distance > 0 && !isNaN(last_fuel_counter) && !isNaN(first_fuel_counter)) {
distance_traveled = last_distance - first_distance;
const fuel_consumed = last_fuel_counter - first_fuel_counter;
mpg = ((distance_traveled / fuel_consumed) * 10).toFixed(1);
}
}
if (mpg > 0) final.MPG = parseInt(mpg);
final.Mileage_Driven = distance_traveled;
if (parseInt(last_odometer) > parseInt(currentMileage))
{
final.Current_Mileage = last_odometer;
final2.Current_Mileage = last_odometer;
}
final.Mileage_Last_Updated = formattedDate;
final2.Solution_Center_Start_Date = InserviceDate || "";
if (enableUpdates) {
try {
const update = await updateRecord('Trucks', trkID, final);
const truckRecStatus = update.data[0].status;
const updateTruckRecDetails = update.data[0].details;
if (truckRecStatus != "success") {
throw new Error(`Truck Rec Failed to Update: ${vin}`);
} else {
UpdtCnt++;
}
const pmID = await new Promise((resolve, reject) => {
pm.sendRequest({
url: `https://www.zohoapis.com/crm/v2/Trucks/${trkID}/Truck_PM`,
method: 'GET',
header: {
'Authorization': `Zoho-oauthtoken ${pm.environment.get('zoho_access_token')}`
}
}, (err, response) => {
if (err) {
reject(err);
} else {
const responseBody = response.text();
if (!responseBody.trim()) {
console.log('Error: No data for Truck PM Rec, empty input');
resolve([]);
} else {
const jsonData = JSON.parse(responseBody);
if ('data' in jsonData) {
resolve(jsonData.data);
} else {
console.log("Error: 'data' key not found in the JSON response");
resolve([]);
}
}
}
});
});
for (let rec of pmID) {
const pm_update = await updateRecord('Truck_PM', rec.id, final2);
const pm_rec_status = pm_update.data[0].status;
const pm_rec_details = pm_update.data[0].details;
if (pm_rec_status != "success") {
throw new Error(`TruckPM Rec Failed to Update: ${vin}`);
} else {
// Update successful
}
}
} catch (error) {
pm_map_error[vin] = error.message;
flag_error = 1;
console.error(error);
}
}
csvFileRow.push(`${vin},${mpg},${last_odometer},${distance_traveled}`);
}
} catch (error) {
pm_map_error[vin] = error.message;
flag_error = 1;
console.error(error);
}
}
}
const csvFileName = `truck_export_${endtime}.csv`;
const csvContent = csvFileRow.join('\n');
pm.environment.set('csvFileContent', csvContent);
if (flag_error === 1) {
await sendEmail('Schedule - Zonar Updates for Truck and PM Records', `Schedule Failed: <br><br>${JSON.stringify(pm_map_error, null, 2)}<br><br>`, csvFileName, csvContent);
console.log("Schedule - Zonar Updates for Truck and PM Records Failed: " + JSON.stringify(pm_map_error, null, 2));
} else {
await sendEmail('Schedule - Zonar Updates for Truck and PM Records - Completed Update', `Odometer Script Completed Update<br><br>Total Records Updated = ${UpdtCnt}<br><br>Total Record Count = ${RecCnt}<br><br>`, csvFileName, csvContent);
console.log("Schedule - Zonar Updates for Truck and PM Records - Completed Update: " + `Total Records Updated = ${UpdtCnt}, Total Record Count = ${RecCnt}`);
}
// Clear interval if exists
if (typeof intervalId !== 'undefined') {
clearInterval(intervalId);
}
} catch (error) {
console.error(error);
}
})();
Thanks