How do I call google script triggers every second? - google-apps-script

Real-life problem is that I want to call api every X seconds and can't seem to accomplish it using Google scripts.
As I know you can call trigger in every 1, 5, 10, 15 or 30 minutes.
Is there a way to run Google script every second?
function createTimeDrivenTriggers() {
ScriptApp.newTrigger('myFunction')
.timeBased()
.everyMinutes(1) //I can not write 0.01 instead of 1 here.
.create();
}
function myFunction() {
Logger.log("Logging");
}
createTimeDrivenTriggers();

Time-based triggers:
You could use the method after(durationMilliseconds) to call your function after a specified number of milliseconds, if you create the trigger at the end of your function, like this:
function myFunction() {
Logger.log("Logging");
ScriptApp.newTrigger("myFunction")
.timeBased()
.after(1000 * X) // Fire "myFunction" after X seconds
.create();
}
But it seems this method (at least currently) cannot be used for firing a function after much less than a minute, as you can see in this Issue Tracker case.
Apart from this, there is no time-based trigger that can be used for your purpose.
Workaround:
Another option, if you just want to perform some actions after X seconds, would be to use Utilities.sleep(milliseconds) and a for loop.
Of course, you would eventually reach Apps Script execution time limit, and for this reason you should:
Find out how many iterations you can make before reaching this limit.
Make each execution make this number of iterations.
Create a trigger that will fire your function after a certain amount of time, with after(durationMilliseconds).
It could be something similar to this:
function myFunction() {
var numIterations = 10; // Number of iterations before reaching time limit (change accordingly)
for (var i = 0; i < numIterations; i++) {
// Your actions
Utilities.sleep(1000 * X); // Pause execution for X seconds
}
ScriptApp.newTrigger("myFunction")
.timeBased()
.after(1000 * Y) // Fire "myFunction" after Y seconds
.create();
}
This way, you can keep your desired frecuency most of the time, and only when the execution time limit is reached (every 6 or every 30 minutes, depending on your account) this frecuency will once be lower (around 1 minute), before going back to the desired frecuency. It's not the behaviour you expect, but I think it's the closest you can get to it.
Reference:
after(durationMilliseconds)
Issue Tracker: Time based trigger could not fire after few seconds
Utilities.sleep(milliseconds)

Related

Can I use the Google App Script trigger more often than every minute?

Google app script gives you the possibility to easily trigger the script even every minute. However, I would like to trigger an event every 15 seconds ? can I do it easily ?
Or maybe other companies offer similar tools which are easy to configure?
This is not currently possible. However, you can have a parent function run a child function 4 times with a 15 second delay, for example:
// This is the function that gets triggered by your trigger every minute
function parentFunction() {
for(let i = 0; i < 4; i++) {
childFunction();
Utilities.sleep(15000); // sleep for 15 seconds
}
}
function childFunction() {
// this function does whatever you need
// 4 times per every trigger execution
// which is 4 times per minutes or every 15 seconds
}

how to make correct timing trigger in google apps script, please check my code line

I am very new to GAS. The already created script (paragraph 3) I need it to be run everyday, every 3 hours, at a specific time at 0:30 -> 3:30 -> 6:30 -> 9:30 -> 12:30-> 15:30-> 18:30-> 21:30
This is upper part of the code. Cannot "combine" below 3 codes into one
function createOpenTrigger() {
ScriptApp.newTrigger("#what should I input here or leave blank????")
.forSpreadsheet(SpreadsheetApp.getActive())
.onOpen()
.create();
}
function createTimeTriggerAtSpecificHourMinute() {
ScriptApp.newTrigger("what should I input here or leave blank????")
.timeBased(00:00)
.everyHour(3)
.nearMinute(30)
.everyDays(1)
.inTimezone("Asia/Tokyo")
.create();
}
function takeSnapShot() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const mainSheet = ss.getSheetByName('SOURCE');
const snap = mainSheet.getRange("A1:Q26").getDisplayValues();
....
If I understand your question correctly, you want to schedule your takeSnapShot() function to run every three hours beginning at 00:30.
Using the sample code you have supplied you can replace your createOpenTrigger() and createTimeTriggerAtSpecificHourMinute() functions with something like this.
function setFirstCall(){
ScriptApp.newTrigger('setRecurrence')
.timeBased()
.atHour(0)
.nearMinute(30)
.inTimezone('Asia/Tokyo')
.create();
}
This will trigger a one-off call to happen near 00:30 the next day. . After running, the trigger will delete itself but will schedule a function setRecurrence() to run. So next you need to create the recurring function.
function setRecurrence(){
ScriptApp.newTrigger('takeSnapShot')
.timeBased()
.everyHours(3)
.create();
}
GAS doesn't allow scheduling for an 'exact' minute (there's a +/- 15min accuracy) however the recurrence should be for the same minute, i.e. if the first trigger runs in the 27th minute then every iteration after should be in the 27th minute.
Hopefully that helps.
References:
TriggerBuilder.timeBased()
ClockTriggerBuilder

create installable trigger (GAS) to run at 'f' frequency starting from 't' time

i have created six getData functions that each make an API call to differing services (four RESTful JSON, two SOAP XML). for each getData function, i have created a setTrigger function, that looks a little like this...
function setGenerationTrigger() {
ScriptApp.newTrigger('generationControl')
.timeBased()
.everyMinutes(30)
.create();
}
i have created a separate createSchedule function, which deletes all existing triggers and executes each of the setTrigger functions. of the six triggers, i need three of them to run .everyMinutes(30), two to run .everyHours(2), and the last to run .everyHours(6). this executes as i'd expect and the triggers run at the desired intervals starting from when the createSchedule runs.
the problem that i want to solve is that i want these setTrigger functions to be staggered, for example:
one .everyMinutes(30) to start at 12:00 (12:30, 13:00, 13:30, etc)
one .everyMinutes(30) to start at 12:10 (12:40, 13:10, 13:40, etc)
one .everyMinutes(30) to start at 12:20 (12:50, 13:20, 13:50, etc)
one .everyHours(2) to start at 12:00 (14:00, 16:00, 18:00, etc)
one .everyHours(2) to start at 13:00 (15:00, 17:00, 19:00, etc)
i hoped it would be as easy as adding:
using .atHour(12) but this will only run daily during that hour
using .atMinute(10) but this errors as this is not a valid method
can this be done from Google Apps Script using a single function to execute? or do i just have to manually schedule each trigger from the desired point in time?
or alternatively is there another/better way of achieving this same result?
you could try something like
ScriptApp.newTrigger("everydayCreate")
.timeBased()
.at(dStart)
.create();
ScriptApp.newTrigger("everyDayDelete")
.timeBased()
.at(dStop)
.create();
function everydayCreate(){
ScriptApp.newTrigger("everyMinutes")
.timeBased()
.everyMinutes(30)
.create();
}
function everyDayDelete()
{
//filter everyMinutes Trigger(s) then
ScriptApp.deleteTrigger(trigger);
}
function everyMinutes(){
//main process
}
NOTE
at(Date) has a 15 minutes rounding error.
Specifies when the trigger will run (plus or minus 15 minutes).
REFERENCE
at(Date)
everyMinutes(Integer)
so this is what i've settled on... first up there is the function that deletes all existing triggers and kicks off a staggered schedule.
function startTriggers() {
deleteTriggers();
var d = new Date();
ScriptApp.newTrigger("startNow")
.timeBased()
.at(d) // using .at() as GAS doesn't accept .after(0) / .after(0 * 60 * 1000)
.create();
ScriptApp.newTrigger("startIn10")
.timeBased()
.after(10 * 60 * 1000)
.create();
ScriptApp.newTrigger("startIn60")
.timeBased()
.after(60 * 60 * 1000)
.create();
}
then for each of these triggers, i created a separate function which nests triggers for each of the API calls, like so.
function startNow() {
ScriptApp.newTrigger('huntlyControl')
.timeBased()
.everyHours(2)
.create();
ScriptApp.newTrigger('generationControl')
.timeBased()
.everyMinutes(30)
.create();
}
function startIn10() {
ScriptApp.newTrigger('hvdcControl')
.timeBased()
.everyMinutes(30)
.create();
}
function startIn60() {
ScriptApp.newTrigger('huntlyControl2')
.timeBased()
.everyHours(2)
.create();
}
the outcome is a schedule of triggers that looks like this...
the Disabled triggers are the 'staggered schedule' i create at the start and will disappear after midnight, so there's no concerns of them recreating/retriggering each day. in fact my trigger schedule now looks like the following, without me having to do any manual tidy ups.
thanks very much #JSmith for your answer, whilst i didn't use it in full i gave it a vote up for providing the inspiration here.

Clock Trigger Builder Not calling function when scheduled - Google sheets app Script

I am using the app script provided by Google to access their prediction API through sheets. I am trying to predict thousands of rows at once, however, after 6 minutes the maximum execution time is reached at the code stops.
I implemented a solution that I found using clock trigger builder. Once I run the function it goes for 5 mins, then it stops sets a trigger to recall the function within 2 mins.
The major problem is that the function is not called when scheduled. I see it in the current triggers list, but it never gets called again. Can you please explain why this is occurring.
My intention is to predict as many lines as possible in 5 min then stop set a trigger to call the predict function again within a few minutes start where it left off and continue until ever element has been predicted.
I also need to know how would I store then values in cache so that it would know all the information that it needs when the function is called again.
//This is the function that is used to predict a selection of data
function predict() {
try {
clearOutput();
var startTime= (new Date()).getTime();
var sheet = SpreadsheetApp.getActiveSheet();
var selection = sheet.getActiveSelection();
var instances = selection.getValues();
var project_number = getProjectNumber();
var model_name = getModelName();
var startRow = stRow;
var MAX_RUNNING_TIME = 300000;
var REASONABLE_TIME_TO_WAIT = 60000;
for (var i = startRow; i < instances.length; ++i) {
var currTime = (new Date()).getTime();
if(currTime - startTime >= MAX_RUNNING_TIME) {
var builder = ScriptApp.newTrigger('predict').timeBased().after(REASONABLE_TIME_TO_WAIT);
builder.create();
break;
} else {
var result = predictSingleRow(project_number, model_name, instances[i]);
selection.getCell(i + 1, 1).setValue(result);
}
}
} catch(e) {
Browser.msgBox('ERROR:' + e, Browser.Buttons.OK);
}
}
Few things as to why your code is not functioning as intended:
1) Since you mentioned,"I see it in the current triggers list, but it never gets called again" and looking at your code, I am unsure whether you intended to call the function again after it's execution has completed. If you do, this is because your for loop runs for a while until the length of the instances is obtained. Nothing in the script suggests that the function needs to be run again once it has finished iterating through instances. Refer to this link to see how to Manage Trigger Programmatically.
2) var builder = ScriptApp.newTrigger('predict').timeBased().after(REASONABLE_TIME_TO_WAIT);
This line of your code falls under an if condition which stops the execution for 1 minute (value is 60000). Hence, adding 1 minute to the time since execution started. Nowhere are you resetting the startTime counter to the time after the waiting time since once the value of currTime - startTime has exceeded MAX_RUNNING_TIME, the function will keep calling the if loop for all iterations of the for loop after that. Simply put, if startTime was 9:35 and currTime was 9:40, after waiting for 1 minute the currTime is 9:41 which is still more than the MAX_RUNNING_TIME(5 minutes) because value of startTime still remains 9:35. Resetting it to 9:41 at this point should resolve your problem.
3) Loosing the break in the if loop would probably help fix that as well.
EDIT:
Add a function as shown in the link I mentioned above:
function callTrigger(){
ScriptApp.newTrigger('predict')
.timeBased()
.everyMinutes(30)
.create();
}
Run the function callTrigger once from your editor and you should be good to go. Remember, for minutes you can only pass values 1,5,15 or 30.

GAS - Execution time-out

I have a spreadsheet that needs to 'setValue' to about 2000 rows.
The problem is, after awhile, I get time-out.
So I'm looking for a solution to split up the job.
I'm thinking of creating a time-based trigger, possibly to start off where the last row or timeout ended. But I can't figure how to get trigger unique ID.
function triggerList() {
ScriptApp.newTrigger('populateList')
.timeBased()
.after(5 * 60 * 1000) // run every 5 mins. Script will time-out.
.create();
}
function deleteTrigger() {
// delete the above trigger
var triggers = ScriptApp.getProjectTriggers();
for (var i = 0; i < triggers.length; i++) {
Logger.log(triggers[i]);
}
}
There is a similar topic on this but i don't quite understand.What happens when I "sleep" in GAS ? (execution time limit workaround)
Anyone has suggestions, workarounds?
Put all of your data into a two dimensional array first, then set all the values at once. Each inner array is a row, each element of each inner array is a cell in a new column.
Set Values Documentation