0

Do google apps scripts have a built in mechanism for preventing long loops that it suspects may be programming error? The reason I'm asking is that I have a google app script I'm creating for my gmail to keep it under control. To avoid the maximum execution time error, I'm only cleaning up 100 emails at a time and then starting the function over using a time based trigger, which will continue until there are no more emails to clean up. I have a lot of mail to clean up, and the script runs about 7 times or so, and then it just stops. I have the code set up to email me at every possible fail or end point but I don't get an email, it just stops. When I look at the triggers for the script, they go every minute or so as expected until about the 7th - 9th one and then they just stop. Here is my code, but I don't think it is a code issue.

function runcleanup() {
  var unreadthreads = 'label:all label:unread -has:red-star older_than:7d',
    archivethreads = 'label:inbox -has:red-star older_than:14d',
    threads,
    execute;

  try {
    threads = GmailApp.search(unreadthreads, 0, 100);
    Logger.log(threads.length);
    if (threads.length) {
      execute = markasread(threads);
      ScriptApp.newTrigger("runcleanup")
        .timeBased()
        .at(new Date((new Date()).getTime() + 1000 * 15))
        .create();
    } else {
      GmailApp.sendEmail(Session.getActiveUser().getEmail(),
        "troubleshooting script",
        "threads = " + threads.length);
    }
  } catch (e) {
    GmailApp.sendEmail(Session.getActiveUser().getEmail(),
      "troubleshooting script ERROR",
      "error = " + e);
  }
}

function markasread(threads) {
  if (!threads) {
    return false;
  }

  for (var i = 0; i < threads.length; i++) {
    threads[i].markRead();
  }

  return true;
}

function archive(threads, maxDate, delayread) {
  if (!threads) {
    return false;
  }

  for (var i = 0; i < threads.length; i++) {
    threads[i].moveToArchive();
  }

  return true;
}
Mogsdad
  • 44,709
  • 21
  • 151
  • 275
richbai90
  • 4,994
  • 4
  • 50
  • 85

2 Answers2

3

I don't agree with your own answer, the issue - I think - is different.

Your script is creating time based triggers that runs the function 15 seconds later, that means that after a short while you have multiple instances of the same function that run concurrently ... and that's not a good idea.

You'll be facing issues with properties and some other limitations on computing request on the same account.

The usual (and working ) way to proceed when using timer trigger to prevent maximum execution time error is simply to allow for execution every 5 minutes when the mean execution time is shorter than 5 minutes.

Personally I setup the trigger to once every 10 minutes and use a tmie measure routine to check I never exceed 5 minutes so I'm sure the first run has ended before I start the next one.

an example is viewable in this post for example but I published a lot of other working examples...

Community
  • 1
  • 1
Serge insas
  • 45,904
  • 7
  • 105
  • 131
0

The answer, for anyone who is curious, appears to be yes. After adding this to the top of my function, the script works

triggers = ScriptApp.getProjectTriggers();
if(triggers.length) {
    ScriptApp.deleteTrigger(triggers[0])
}

It should go without saying of course that this has the potential for creating an infinite loop, so be careful.

richbai90
  • 4,994
  • 4
  • 50
  • 85
  • 2
    It's working because you're stopping a previous 'thread'... but it's not getting the work done any faster. There's also no infinite loop... nor enough room to explain in this comment. – Mogsdad Oct 09 '14 at 22:37