Reputation: 5811
Is it possible to see if a particular project's triggers have any active/running executions?
I have a one-time migration script/project to update thousands of our Google Sheets files to a new template format. The script will take, by my calculations, hours to run. Our G-Suite Enterprise environment has a 30 minute limit for execution.
My code is written such that if the script fails, for whatever reason, I can just re-run it and it'll continue from where it stopped.
Sometimes the script fails for other reasons -- like memory error or because of network connectivity issues.
So I want to set up a 15 minute trigger to run the script. And I want it to check if another execution is still running. If it is, then it'll stop. If it isn't, then it'll continue.
I know how to use ScriptApp.getProjectTriggers()
to see the triggers linked to a project but from that I don't know how to find running executions.
Upvotes: 6
Views: 5840
Reputation: 49
Here is the cleanest (and at the same time easiest) way to do it:
Google provides a built-in tool for Apps Script called Lock Service. You can use it to avoid running any section of the code again while it's still already running (by you manually or by a trigger).
Just structure your function that you'll call from the trigger as such:
function functionName() {
let lock = LockService.getUserLock().tryLock(0);
if (lock.hasLock()) {
// Your code goes here.
};
};
Now whenever your trigger fires, it will first check if there is a lock or not. If there is, it will skip that run. If there is not, it will create a lock and start executing your code.
Upvotes: 4
Reputation: 201338
If my understanding is correct, how about this answer? Please think of this as just one of several answers.
I think that your goal can be achieved using the method of processes.list in Google Apps Script API. When the method of processes.list in Google Apps Script API is request during the script is run by the time-driven trigger, the following value can be retrieved.
{
"processes": [
{
"projectName": "sampleProject",
"functionName": "myFunction",
"processType": "TIME_DRIVEN",
"processStatus": "RUNNING", // <--- here
"userAccessLevel": "OWNER",
"startTime": "2019-10-07T00:00:00.000Z",
"duration": "36.145s"
}
]
}
In this case, processStatus
is RUNNING
. When the script is finished, processStatus
is changed to COMPLETED
.
The sample script for retrieving the information when processStatus
is RUNNING
is as follows.
In this case, it is required to link Cloud Platform Project to Google Apps Script Project. About how to link it, you can see it at here.
As the second step, please enable Google Apps Script API at API console. About how to enable it, you can see it at this thread.
function sample() {
var scriptId = "###"; // Please set the script ID here.
var functionName = "###"; // Please set the function name here.
var url = "https://script.googleapis.com/v1/processes?userProcessFilter.functionName=" + functionName + "&userProcessFilter.scriptId=" + scriptId;
var res = UrlFetchApp.fetch(url, {headers: {Authorization: 'Bearer ' + ScriptApp.getOAuthToken()}});
var obj = JSON.parse(res);
var runningScript = obj.processes.filter(function(p) {return p.processType == "TIME_DRIVEN" && p.processStatus == "RUNNING"});
Logger.log(runningScript)
}
https://www.googleapis.com/auth/script.external_request
and https://www.googleapis.com/auth/script.processes
. So please add them to the manifest file (appsscript.json
).scriptId
and functionName
which are run when the time-driven trigger is fired.[]
is returned.p.processType == "TIME_DRIVEN"
.processStatus
sometimes became UNKNOWN
. But in this case, it indicates that the script is finished.If I misunderstood your question and this was not the direction you want, I apologize.
I think that the method using Apps Script API is one solution. In order to achieve your goal without linking Cloud Platform Project to GAS Project, here, I would like to propose a workaround.
In this workaround, I used the property of Drive API. When the property of Drive API is used, the property can be retrieved other project. So here, I used the property of Drive API. Please think of this as just one of several workarounds.
At first, please enable Drive API at Advanced Google services.
Please copy and paste the following script. It supposes that the function of runByTrigger
is run by the time-driven trigger.
function runByTrigger(e) {
var fileId = "###"; // Please set the file ID.
if (e && "triggerUid" in e && e.triggerUid != "") {
Drive.Files.update({properties: [
{key: "processStatus", value: "RUNNING", visibility: "PUBLIC"},
{key: "processStartTime", value: new Date().toISOString(), visibility: "PUBLIC"},
]}, fileId);
}
// do something
// Here, please put your script.
if (e && "triggerUid" in e && e.triggerUid != "") {
Drive.Files.update({properties: [
{key: "processStatus", value: "COMPLETED", visibility: "PUBLIC"},
{key: "processStartTime", value: "", visibility: "PUBLIC"},
]}, fileId);
}
}
This script is used for checking whether the script is run by the time-driven trigger. Please run this script for checking it. You can also use this script which is not the same project including runByTrigger
.
function myFunction() {
var fileId = "###"; // Please set the file ID.
var runningScript = Drive.Properties.get(fileId, "processStatus", {visibility: "PUBLIC"}).value;
if (runningScript == "RUNNING") {
var startTime = Drive.Properties.get(fileId, "processStartTime", {visibility: "PUBLIC"}).value;
Logger.log("Script is currently running. Start time is %s", startTime)
} else {
Logger.log("Script was finished.")
}
}
fileId
of script 1 and 2 is the same ID. As a test case, if the script is the standalone script, please set the script ID of the standalone script. If the script is the container-bound script, please set the file ID of Google Docs.runByTrigger
is run by the time-driven trigger, processStatus
and processStartTime
are put to the property of the file.
myFunction
is run, Script is currently running. Start time is {startTime}
is shown at the log.Script was finished.
is shown at the log.Upvotes: 7