309 lines
12 KiB
JavaScript
309 lines
12 KiB
JavaScript
// Compiled using ts2gas 3.6.5 (TypeScript 4.3.2)
|
|
var exports = exports || {};
|
|
var module = module || { exports: exports };
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.executeLongRun = exports.LongRun = void 0;
|
|
//import Properties = GoogleAppsScript.Properties.Properties;
|
|
/**
|
|
* Long-Running Support
|
|
*/
|
|
var LongRun = /** @class */ (function () {
|
|
/**
|
|
* Private constructor
|
|
* @private
|
|
*/
|
|
function LongRun() {
|
|
/** start time map */
|
|
this.startTimeMap = {};
|
|
}
|
|
Object.defineProperty(LongRun, "instance", {
|
|
/**
|
|
* Returns singleton instance.
|
|
*/
|
|
get: function () {
|
|
if (!this._instance) {
|
|
this._instance = new LongRun();
|
|
}
|
|
return this._instance;
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
/**
|
|
* Returns if function is running now.
|
|
* @param funcName
|
|
*/
|
|
LongRun.prototype.isRunning = function (funcName) {
|
|
// get spreadsheet properties
|
|
var properties = PropertiesService.getScriptProperties();
|
|
var running = properties.getProperty(LongRun.PREFIX_RUNNING + funcName);
|
|
return !(running == null || running === '');
|
|
};
|
|
/**
|
|
* Sets the function is running
|
|
* @param funcName
|
|
* @param running
|
|
*/
|
|
LongRun.prototype.setRunning = function (funcName, running) {
|
|
var properties = PropertiesService.getScriptProperties();
|
|
var key = LongRun.PREFIX_RUNNING + funcName;
|
|
if (running) {
|
|
properties.setProperty(key, "running");
|
|
}
|
|
else {
|
|
properties.deleteProperty(key);
|
|
}
|
|
};
|
|
/**
|
|
* Sets max execution seconds
|
|
* @param seconds
|
|
*/
|
|
LongRun.prototype.setMaxExecutionSeconds = function (seconds) {
|
|
LongRun.RUNNING_MAX_SECONDS = seconds;
|
|
};
|
|
/**
|
|
* Sets the trigger's delay minutes
|
|
* @param minutes
|
|
*/
|
|
LongRun.prototype.setTriggerDelayMinutes = function (minutes) {
|
|
LongRun.RUNNING_DELAY_MINUTES = minutes;
|
|
};
|
|
/**
|
|
* Returns the function parameters
|
|
* @param funcName
|
|
*/
|
|
LongRun.prototype.getParameters = function (funcName) {
|
|
var properties = PropertiesService.getScriptProperties();
|
|
var parameters = properties.getProperty(LongRun.PREFIX_OPTION + funcName);
|
|
if (parameters != null) {
|
|
return parameters.split(',');
|
|
}
|
|
else {
|
|
return [];
|
|
}
|
|
};
|
|
/**
|
|
* Sets the function parameters.
|
|
* @param funcName
|
|
* @param parameters
|
|
*/
|
|
LongRun.prototype.setParameters = function (funcName, parameters) {
|
|
var properties = PropertiesService.getScriptProperties();
|
|
if (parameters != null) {
|
|
properties.setProperty(LongRun.PREFIX_OPTION + funcName, parameters.join(','));
|
|
}
|
|
else {
|
|
properties.deleteProperty(LongRun.PREFIX_OPTION + funcName);
|
|
}
|
|
};
|
|
/**
|
|
* Starts or Resumes Long-Run process.
|
|
* @param funcName
|
|
* @returns start index ( 0 for the first time )
|
|
*/
|
|
LongRun.prototype.startOrResume = function (funcName) {
|
|
// save start time
|
|
this.startTimeMap[funcName] = new Date().getTime();
|
|
// get properties of spreadsheet
|
|
var properties = PropertiesService.getScriptProperties();
|
|
// set running-flag
|
|
this.setRunning(funcName, true);
|
|
// if the trigger exists, delete it.
|
|
this.deleteTrigger(LongRun.PREFIX_TRIGGER_KEY + funcName);
|
|
// get start index
|
|
var startPos = parseInt(properties.getProperty(LongRun.PREFIX_START_POS + funcName));
|
|
if (!startPos) {
|
|
return 0;
|
|
}
|
|
else {
|
|
return startPos;
|
|
}
|
|
};
|
|
/**
|
|
* Determines whether the process should be suspended.
|
|
* If it should be suspended, the next trigger will be registered.
|
|
* @param funcName
|
|
* @param nextIndex - start position when resuming
|
|
* @return true - it should be suspended
|
|
*/
|
|
LongRun.prototype.checkShouldSuspend = function (funcName, nextIndex) {
|
|
var startTime = this.startTimeMap[funcName];
|
|
var diff = (new Date().getTime() - startTime) / 1000;
|
|
// If it's past the specified time, suspend the process
|
|
if (diff >= LongRun.RUNNING_MAX_SECONDS) {
|
|
// register the next trigger and set running-flag off
|
|
this.registerNextTrigger(funcName, nextIndex);
|
|
return true;
|
|
}
|
|
else {
|
|
return false;
|
|
}
|
|
};
|
|
/**
|
|
* Resets Long-Running variables
|
|
* @param funcName
|
|
*/
|
|
LongRun.prototype.reset = function (funcName) {
|
|
// delete trigger
|
|
this.deleteTrigger(LongRun.PREFIX_TRIGGER_KEY + funcName);
|
|
// delete spreadsheet properties
|
|
var properties = PropertiesService.getScriptProperties();
|
|
properties.deleteProperty(LongRun.PREFIX_START_POS + funcName);
|
|
properties.deleteProperty(LongRun.PREFIX_OPTION + funcName);
|
|
properties.deleteProperty(LongRun.PREFIX_RUNNING + funcName);
|
|
properties.deleteProperty(LongRun.PREFIX_TRIGGER_KEY + funcName);
|
|
};
|
|
/**
|
|
* Resets Long-Running variables if there is no next trigger.
|
|
* Returns whether the command has finished or not.
|
|
* @param funcName
|
|
*/
|
|
LongRun.prototype.end = function (funcName) {
|
|
var ret = false;
|
|
if (!this.existsNextTrigger(funcName)) {
|
|
this.reset(funcName);
|
|
ret = true;
|
|
}
|
|
return ret;
|
|
};
|
|
/**
|
|
* Returns if there is next trigger.
|
|
* @param funcName
|
|
*/
|
|
LongRun.prototype.existsNextTrigger = function (funcName) {
|
|
var triggerId = PropertiesService.getScriptProperties().getProperty(LongRun.PREFIX_TRIGGER_KEY + funcName);
|
|
return triggerId != null;
|
|
};
|
|
/**
|
|
* register the next trigger and set running-flag off
|
|
* @param funcName
|
|
* @param nextIndex - start position when resuming
|
|
*/
|
|
LongRun.prototype.registerNextTrigger = function (funcName, nextIndex) {
|
|
// get spreadsheet properties
|
|
var properties = PropertiesService.getScriptProperties();
|
|
properties.setProperty(LongRun.PREFIX_START_POS + funcName, String(nextIndex)); // save next start position
|
|
this.setTrigger(LongRun.PREFIX_TRIGGER_KEY + funcName, funcName); // set trigger
|
|
// turn off running-flag
|
|
properties.deleteProperty(LongRun.PREFIX_RUNNING + funcName);
|
|
};
|
|
/**
|
|
* Deletes the trigger
|
|
* @param triggerKey
|
|
*/
|
|
LongRun.prototype.deleteTrigger = function (triggerKey) {
|
|
var triggerId = PropertiesService.getScriptProperties().getProperty(triggerKey);
|
|
if (!triggerId)
|
|
return;
|
|
ScriptApp.getProjectTriggers().filter(function (trigger) {
|
|
return trigger.getUniqueId() == triggerId;
|
|
})
|
|
.forEach(function (trigger) {
|
|
ScriptApp.deleteTrigger(trigger);
|
|
});
|
|
PropertiesService.getScriptProperties().deleteProperty(triggerKey);
|
|
};
|
|
/**
|
|
* Sets a trigger
|
|
* @param triggerKey
|
|
* @param funcName
|
|
*/
|
|
LongRun.prototype.setTrigger = function (triggerKey, funcName) {
|
|
this.deleteTrigger(triggerKey); // delete if exists.
|
|
var dt = new Date();
|
|
dt.setMinutes(dt.getMinutes() + LongRun.RUNNING_DELAY_MINUTES); // will execute after the specified time
|
|
var triggerId = ScriptApp.newTrigger(funcName).timeBased().at(dt).create().getUniqueId();
|
|
// save the trigger id to delete the trigger later.
|
|
PropertiesService.getScriptProperties().setProperty(triggerKey, triggerId);
|
|
};
|
|
// constants
|
|
LongRun.PREFIX_RUNNING = "running_";
|
|
LongRun.PREFIX_TRIGGER_KEY = "trigger_";
|
|
LongRun.PREFIX_START_POS = "start_";
|
|
LongRun.PREFIX_OPTION = "option_";
|
|
LongRun.RUNNING_MAX_SECONDS = 4 * 60;
|
|
LongRun.RUNNING_DELAY_MINUTES = 1;
|
|
LongRun.EXECUTE_LONGRUN_FUNCNAME = "_executeLongRun";
|
|
return LongRun;
|
|
}());
|
|
exports.LongRun = LongRun;
|
|
/**
|
|
* A function allows you to easily execute long-run task using the LongRun class.
|
|
*
|
|
* @param mainFuncName - Name of the function to be executed each time.
|
|
* @param loopCount - Number of times to execute the main function.
|
|
* @param params - Parameters passed to each function (string[]). (optional)
|
|
* @param initializerName - Name of the first function to be executed on first or restart. (optional)
|
|
* @param finalizerName - Name of the function to be called on interruption or when all processing is complete. (optional)
|
|
*
|
|
* The definition of each function to be passed should be as follows.
|
|
* - Main function: function [function name](index: number, params: string[]) {...}
|
|
* - Initializer: function [function name](startIndex: number, params: string[]) {...}
|
|
* - Finalizer: function [function name](isFinished: boolean, params: string[]) {...}
|
|
*
|
|
* Note that it is not possible to use executeLongRun() to execute different long-time processes simultaneously.
|
|
*/
|
|
function executeLongRun(mainFuncName, loopCount, params, initializerName, finalizerName) {
|
|
if (params === void 0) { params = null; }
|
|
if (initializerName === void 0) { initializerName = null; }
|
|
if (finalizerName === void 0) { finalizerName = null; }
|
|
var longRunParams = [];
|
|
longRunParams.push(mainFuncName);
|
|
longRunParams.push(String(loopCount));
|
|
longRunParams.push(initializerName === null ? '' : initializerName);
|
|
longRunParams.push(finalizerName === null ? '' : finalizerName);
|
|
if (params != null && params.length > 0) {
|
|
longRunParams.push(params.join(','));
|
|
}
|
|
LongRun.instance.setParameters(LongRun.EXECUTE_LONGRUN_FUNCNAME, longRunParams);
|
|
_executeLongRun();
|
|
}
|
|
exports.executeLongRun = executeLongRun;
|
|
/**
|
|
* The main body of executeLongRun
|
|
*/
|
|
function _executeLongRun() {
|
|
var longRun = LongRun.instance;
|
|
// get parameters
|
|
var longRunParams = longRun.getParameters(LongRun.EXECUTE_LONGRUN_FUNCNAME);
|
|
var mainFuncName = longRunParams[0];
|
|
var loopCount = parseInt(longRunParams[1]);
|
|
var initializerName = longRunParams[2];
|
|
var finalizerName = longRunParams[3];
|
|
var params = [];
|
|
for (var i = 4; i < longRunParams.length; i++) {
|
|
params.push('"' + longRunParams[i] + '"');
|
|
}
|
|
var paramsLiteral = '[' + params.join(',') + ']';
|
|
var startIndex = longRun.startOrResume(LongRun.EXECUTE_LONGRUN_FUNCNAME);
|
|
try {
|
|
// *** call initializer ***
|
|
if (initializerName != null && initializerName.length > 0) {
|
|
eval(initializerName + '(' + startIndex + ',' + paramsLiteral + ')');
|
|
}
|
|
// execute the iterative process.
|
|
for (var i = startIndex; i < loopCount; i++) {
|
|
// Each time before executing a process, you need to check if it should be stopped or not.
|
|
if (longRun.checkShouldSuspend(LongRun.EXECUTE_LONGRUN_FUNCNAME, i)) {
|
|
// if checkShouldSuspend() returns true, the next trigger has been set
|
|
// and you should get out of the loop.
|
|
console.log('*** The process has been suspended. ***');
|
|
break;
|
|
}
|
|
// *** call main process ***
|
|
eval(mainFuncName + '(' + i + ',' + paramsLiteral + ')');
|
|
}
|
|
}
|
|
catch (e) {
|
|
console.log(e.message);
|
|
}
|
|
finally {
|
|
// you must always call end() to reset the long-running variables if there is no next trigger.
|
|
var finished = longRun.end(LongRun.EXECUTE_LONGRUN_FUNCNAME);
|
|
// *** call finalizer ***
|
|
if (finalizerName != null && finalizerName.length > 0) {
|
|
eval(finalizerName + '(' + finished + ',' + paramsLiteral + ')');
|
|
}
|
|
}
|
|
}
|