Time based GAS trigger disabled for internal error - google-apps-script

I'm trying to create a trigger to launch a function in GAS every 15 minutes starting from a precise time (every day). So the trigger has to run the script at (for example) 10:02 and then every 15 minutes: 10:17, 10:32, 10:47, 11:02, etc.
So I've found a great source to run a script in a certain time (without using atHour and nearminute(0) because they have a confidential interval of +/- 15 minutes), here is the source (big up for the guy David Weiss): https://github.com/davidtheweiss/Apps-Script-Season-3-Script-Service/blob/master/Episode%201.1.gs
And there you can find the adapted code of the trigger for my purpouse:
function copyPicked(){
// code of the function I want to run
}
////////////////// TRIGGER
function immutableTrigger() {
ScriptApp.newTrigger('mutableTrigger')
.timeBased()
.everyMinutes(15)
.create();
}
function mutableTrigger() {
const today = new Date();
const year = today.getFullYear();
const month = today.getMonth();
const day = today.getDate();
const functionName = 'copyPicked';
ScriptApp.getProjectTriggers().forEach(trigger => {
trigger.getHandlerFunction() === functionName ? ScriptApp.deleteTrigger(trigger) : 0;
});
ScriptApp.newTrigger(functionName)
.timeBased()
.at(new Date(year, month, day, 10, 02))
.create();
}
The problem is that when I run the functions mutableTrigger and immutableTrigger they run perfectly and smoothly but then a time trigger is created with the name of the function I want to run (copyPicked) with a precise time (10:02) and at 10:02 the function is automatically disabled for internal error! Why?
I found this could be a problem related to the runtime: V8 runtime has an issue with this type of time triggers -> https://issuetracker.google.com/issues/150756612
So I tried to enable the old runtime: DEPRECATED_ES5 as described in the above issue but it gives me a generic error at this point of the code related to the trigger:
ScriptApp.getProjectTriggers().forEach(trigger => {
I don't know this old runtime!

I have tried it myself but I have no problem with running copyPicked.
Have you provided enough permission for copyPicked?
Arrow function (trigger => {) is not available in ES5

Related

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

How do I call google script triggers every second?

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)

How do I set a time controlled trigger starting at a certain time whitout user interaction?

I would like to have a code (see below) executed daily at 22:00:00. I have already tried to solve this via the G Suite Developer Hub by setting an hour interval trigger. Unfortunately I could not set a time there (in this case 22:00:00). Next I discovered the function "ScriptApp.newTrigger" and created the following code, but I'm not sure if this is the right solution. What do you think? Can it work like this?
The following is important to me.
The code must be reliably executed daily at 22:00:00.
One execution per day is sufficient
At best, even if no user has opened the table.
OnEdit or OnOpen are less suitable for this, since it is not guaranteed that the table a.) will be opened at the right time and b.) If users are online, it is not certain that they will edit it.
function TimeTrigger() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Tickerprüfung');
sheet.getRange('C2').setValue(new Date());
var date = new Date();
date.setHours(22);
date.setMinutes(0);
date.setSeconds(0);
date.setMilliseconds(0);
sheet.getRange('C3').setValue(date);
}
function createDayTrigger() {
ScriptApp.newTrigger("TimeTrigger")
.timeBased().everyHours(24).atHour(22).create();
}
You want to run the function of TimeTrigger() only at 22:00:00 every day.
The time zone uses your time zone.
If my understanding is correct, how about this modification? Please think of this as just one of several answers.
Modification points:
When you run the script only at 22:00, how about the following
ScriptApp.newTrigger('TimeTrigger').timeBased().at(setTime).create()
After the trigger was fired, it removes the finished trigger. Because the finished trigger is left.
The flow of this modified script is as follows.
Flow:
At first, please run the function of startScript(). By this, the trigger for running createDayTrigger() is set.
This trigger is run near 21:00 every day.
This function is required to run only one time.
By the trigger set with startScript(), createDayTrigger() is run at 21:00 (Specifies the hour the trigger will run (plus or minus 15 minutes). Ref).
createDayTrigger() set the trigger for running TimeTrigger() at 22:00.
At 22:00, TimeTrigger() is run. At this time, the trigger set by createDayTrigger() is cleared by deleteTrigger().
Because the trigger set with startScript() is existing, createDayTrigger() is run at 21:00. By this cycle, TimeTrigger() can be run at 22:00 every day.
Modified script:
Please copy and paste the following script to the script editor. And please run the function of startScript(). Please run this function only one time. By this, the base trigger is set.
// Your script.
function TimeTrigger() {
deleteTrigger();
// Below script is your script.
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Tickerprüfung');
sheet.getRange('C2').setValue(new Date());
var date = new Date();
date.setHours(22);
date.setMinutes(0);
date.setSeconds(0);
date.setMilliseconds(0);
sheet.getRange('C3').setValue(date);
}
// Delete finished trigger.
function deleteTrigger() {
var triggers = ScriptApp.getProjectTriggers();
triggers.forEach(function(t) {
if (t.getHandlerFunction() == "TimeTrigger") ScriptApp.deleteTrigger(t);
});
}
function createDayTrigger() {
var d = new Date();
d.setHours(22);
d.setMinutes(0);
d.setSeconds(0);
ScriptApp.newTrigger('TimeTrigger').timeBased().at(d).create();
}
// Please run this function.
function startScript() {
ScriptApp.newTrigger('createDayTrigger').timeBased().everyDays(1).atHour(21).create();
}
References:
Class ClockTriggerBuilder
atHour(hour)
If I misunderstood your question and this was not the direction you want, I apologize.

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.

Timed script not working

I have a google script that I would like to run automatically every weekday at 8:11 am. I have set my time zones to make sure that everything is correct, but it never seems to work correctly. I am still weak at scripting. Does anyone see where I might have error in this script?
function myFunction(){
try {
var d = new Date();
if (d.getDay() == 6 || d.getDay() == 0) return;
if (d.getHours() != 08 && d.getMinutes() != 11) return; // This will stop the script from running unless it is 8:11am
} catch (e) {
MailApp.sendEmail("pthompson#ucc.on.ca", "Error report", e.message);
}
}
Thank you,
Paul
To run a function based on time, setup a project trigger (under Resources tab) with the Event "Time-driven". You can even setup a notification.
If you wanted to manage this trigger programmatically you could do something like this:
function createTimeTrigger() {
// Once a day at 8AM, near minute 11 for function 'writeSomething()'
var dailyHourNearMinute = ScriptApp.newTrigger("writeSomething")
.timeBased()
.everyDays(1)
.atHour(8)
.nearMinute(11)
.create();
}
You will notice that this creates a trigger for you that can be viewed under 'Current project's triggers'. It will say between 8AM-9AM. As far as google time events, they work well at getting it within the hour but not on the exact minute. The load in the system can also throw this off. So, the best you can really plan for is, between 8AM - 9AM.