-
-
Save schlos/3d0a9c489c3f233439d02f56f321a747 to your computer and use it in GitHub Desktop.
outerLoop for Google Apps Script triggered functions is some boilerplate that encapsulates best practice ways to deal with running workloads that may take longer to process that the time available in an Apps Script triggered run.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//load configuration details and start logging - creates and sets up sheets the first time they are run | |
var CONFIG_SPREADSHEET_KEY = '<ssid_goes_here>'; | |
var Config = SettingsManager.load(CONFIG_SPREADSHEET_KEY); //Add Mafviu9bMfg9xVu21LGfpWnHAGDwXQ1CH in Resources > Libraries | |
Logger = BetterLog.useSpreadsheet(Config['logSpreadsheetId'].value);//Add MYB7yzedMbnJaMKECt6Sm7FLDhaBgl_dE in Resources > Libraries | |
// trigger this function | |
function outerLoop() { | |
try { | |
// to calc elapsed time | |
var isOverMaxRuntime = false, | |
startTime = new Date(); | |
// Deletes all occurrences of the Repeating trigger we don't end up with undeleted time based triggers all over the place | |
ScriptApp.getProjectTriggers().forEach(function(i) { | |
if (i.getHandlerFunction()==='outerLoopRepeating') {ScriptApp.deleteTrigger(i);} | |
}); | |
//Logger.finer('Entering the "%s" function', arguments.callee.name); | |
// Handle max execution times in our outer loop | |
// Get start index if we hit max execution time last run | |
var start = parseInt(PropertiesService.getScriptProperties().getProperty(arguments.callee.name + "-start")) || 0; | |
var thingies = ['stuff to process', 'in an Array',,,,]; // | |
for (var i = start ; i < thingies.length; i++) { | |
if (Math.round((new Date() - startTime)/1000) > 300) { //360 seconds is Google Apps Script max run time | |
//We've hit max runtime. | |
isOverMaxRuntime = true; | |
break; | |
} | |
//do our work here | |
Logger.finest('Inside the for loop that does the xyz work. i is currently: %d', i); | |
var processingMessage = Utilities.formatString('%d of %d thingies: %s <%s>', i+1, thingies.length, thingyName, thingyId); | |
//do our work above here | |
} | |
if (isOverMaxRuntime) { | |
//save state in user/project prop if required | |
PropertiesService.getScriptProperties().setProperty(arguments.callee.name + '-start', i); | |
//create another trigger | |
ScriptApp.newTrigger('outerLoopRepeating').timeBased().everyMinutes(10).create(); | |
Logger.info('Hit max run time - last iteration completed was i=%d', i-1); | |
} else { | |
Logger.fine('Done all the work and all iterations'); | |
PropertiesService.getScriptProperties().deleteProperty(arguments.callee.name + '-start'); | |
Logger.info('Completed processing all %d things with the "%s" function', thingies.length, arguments.callee.name); | |
} | |
} catch (e) { | |
Logger.severe('%s. While processing %s', JSON.stringify(e, null, 2), processingMessage); | |
throw e; | |
} | |
} | |
//automatically invoked from outerLoop()'s creation of a new trigger if required to get work done | |
function outerLoopRepeating() { | |
outerLoop(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment