Home > other >  What am I doing wrong when triggering a Gmail script to run again after the timeout?
What am I doing wrong when triggering a Gmail script to run again after the timeout?

Time:05-23

I'm trying to clear an account of emails on Gmail. Doing it on the Gmail UI leads to errors probably because there are over 500k emails.

So I've started doing it with the Apps Script website https://script.google.com/ based on some scripts I have found and it works fine until around five or six minutes when it times out.

Right now the way I have it setup (code below), it runs fine but when it hits isTimeUp it just exits. The newTrigger is never running.

function myFunction() {
  console.log("myFunction")
  var batchSize = 100
  var today = new Date();
  while (true) {

    var threads = GmailApp.search('before:2020/05/20');
    for (j = 0; j < threads.length; j  = batchSize) {
      console.log("Batch "   j)
      GmailApp.moveThreadsToTrash(threads.slice(j, j   batchSize));

    }
    if (isTimeUp(today)) {
      console.log("time up")
      var triggers = ScriptApp.getProjectTriggers();
      try {
        ScriptApp.deleteTrigger(triggers[0]);
      } catch (e) {

      }
      ScriptApp.newTrigger("myFunction")
        .timeBased()
        .after(1000)
        .create();
      break;
    }
  }
}


function isTimeUp(today) {
  var now = new Date();
  return now.getTime() - today.getTime() > 300000;

}

This is the log I see:

4:46:05 PM  Notice  Execution started
4:46:05 PM  Info    myFunction
4:46:06 PM  Info    Batch 0
4:46:19 PM  Info    Batch 100
4:46:32 PM  Info    Batch 200
4:46:45 PM  Info    Batch 300
4:46:58 PM  Info    Batch 400
4:47:11 PM  Info    Batch 0
4:47:23 PM  Info    Batch 100
4:47:37 PM  Info    Batch 200
4:47:49 PM  Info    Batch 300
4:48:01 PM  Info    Batch 400
4:48:14 PM  Info    Batch 0
4:48:28 PM  Info    Batch 100
4:48:40 PM  Info    Batch 200
4:48:53 PM  Info    Batch 300
4:49:05 PM  Info    Batch 400
4:49:18 PM  Info    Batch 0
4:49:31 PM  Info    Batch 100
4:49:43 PM  Info    Batch 200
4:49:58 PM  Info    Batch 300
4:50:18 PM  Info    Batch 400
4:50:33 PM  Info    Batch 0
4:50:46 PM  Info    Batch 100
4:50:59 PM  Info    Batch 200
4:51:12 PM  Info    Batch 300
4:51:26 PM  Info    Batch 400
4:51:39 PM  Info    time up
4:51:39 PM  Notice  Execution completed

What am I doing wrong?

CodePudding user response:

Issue and workaround:

About The newTrigger is never running., if you are using V8 runtime at the script editor and the installed trigger doesn't work, I'm worried that this might be the bug. Ref1 Ref2

But, fortunately, in the current stage, there is a workaround for removing this bug. It's to use Web Apps. Ref I had had the same situation before. The flow of this workaround is as follows.

  1. Run the script you want to run.
  2. When the time-driven trigger is installed, that is installed using the Web Apps.
    • This is the important point.

In this case, the time-driven trigger installed by the script is run. When your script is modified, it becomes as follows.

Usage:

1. Modified script.

Please modify your script as follows.

const functionName = "myFunction";

// When v8 runtime is used, when the trigger is set from the function executing by a trigger, the trigger is disabled. This is the recognized bug. But unfortunately, this has still not been resolved. (September 21, 2021)
// https://issuetracker.google.com/issues/150756612
// https://issuetracker.google.com/issues/142405165
const doGet = _ => {
  ScriptApp.newTrigger(functionName).timeBased().after(1000).create();
  return ContentService.createTextOutput();

  // DriveApp.createFile() // This is used for automatically detecting the scopes for requesting to Web Apps. Please don't remove this comment line.
};

function myFunction() {
  console.log(functionName)
  var batchSize = 100
  var today = new Date();
  while (true) {

    var threads = GmailApp.search('before:2020/05/20');
    for (j = 0; j < threads.length; j  = batchSize) {
      console.log("Batch "   j)
      GmailApp.moveThreadsToTrash(threads.slice(j, j   batchSize));
    }

    if (isTimeUp(today)) {
      console.log("time up")
      var triggers = ScriptApp.getProjectTriggers();
      var trigger = triggers.find(t => t.getHandlerFunction() == functionName);
      if (trigger) {
        ScriptApp.deleteTrigger(trigger);
      }
      UrlFetchApp.fetch(ScriptApp.getService().getUrl(), { headers: { authorization: "Bearer "   ScriptApp.getOAuthToken() } });
      break;
    }
  }
}

function isTimeUp(today) {
  var now = new Date();
  return now.getTime() - today.getTime() > 3000;
}

2. Deploy Web Apps.

  1. On the script editor, at the top right of the script editor, please click "click Deploy" -> "New deployment".
  2. Please click "Select type" -> "Web App".
  3. Please input the information about the Web App in the fields under "Deployment configuration".
  4. Please select "Me" for "Execute as".
    • This is the important of this workaround.
  5. Please select "Only myself" for "Who has access".
  6. Please click "Deploy" button.

The detail information can be seen at the official document and my report.

3. Testing.

In the modified script, as the 1st run, please run myFunction() with the script editor. By this, your script is run. And, the time-driven trigger is installed by the Web Apps. And, the installed trigger is run automatically by the time-driven trigger.

Note:

  • If you disable the V8 runtime, I thought that the script might be worked without the above modification. But in that case, the process cost of the loop will become high. Ref

Reference:

CodePudding user response:

Based on my own experience using after method of the Google Apps Script trigger builder, I think that 1000 milliseconds is a too small value. Try using something equal or greater than 60000 milliseconds (1 minute).

  • Related