服务调用太多次一天:gmail阅读

时间:2012-12-18 14:49:26

标签: google-apps-script

我正在使用gmail运行各种速率限制,我不知道我能做些什么来解决它们。我想要完成的是搜索gmail中有任何“过期”标签的消息(以几分钟的不同时间)。我的目的是让邮件规则将这些标签应用于在一定时间后变得无关紧要的邮件。我希望这些邮件保留在我的收件箱中,直到它们过期,然后自动存档。我根据我在http://googleappsdeveloper.blogspot.com/2011/07/gmail-snooze-with-apps-script.html

看到的帖子提出了一般技巧

我有一个触发器,每五分钟运行一次“过期”功能。

因此,每五分钟,它会对GmailApp.getUserLabelByName进行10次调用,并对getThreads()进行一次调用。然后根据它找到的匹配线程数量,对于每个线程:

1 x getFirstMessageSubject 1 x getLastMessageDate 1 x addLabel 1 x moveToArchive 1 x removeLabel

每个帖子有5个电话。

所以,我想,我正在拨打10个电话/ 5分钟,或者每天拨打2880个电话来寻找消息。然后,假设我在一天中发现了1,000条消息,另外还有5,000条呼叫。结合7,880个电话,这是我认为的配额限制,但我有点不清楚。根据Quota Limits下的https://docs.google.com/a/macros/latinschool.org/dashboard,对于像我这样的Google Apps for Edu帐户,我应该能够每天执行10,000次GMail读取和10,000次GMail写入操作。我想我的所有电话都属于这两个电话中的一个。

我可以减少我正在使用的标签/次数,而不是主题(我用于调试),但除此之外,我不确定如何使这个脚本更有效率。而且我完全不清楚我是如何达到配额的(见上面的数学)。

这是我的代码:

/**
 * Expire mail after set time by archiving based on labels
 * based on http://googleappsdeveloper.blogspot.com/2011/07/gmail-snooze-with-apps-script.html
 * For more information on interacting with GMail labels, see
 * https://developers.google.com/apps-script/class_gmaillabel
 */

var expiretimes = [5,15,30,60,120,180,240,480,720];  // times in minutes to expire messages


function getLabelName(i) {
  return "expire/expire " + i;
}

function setup() {
  // Create the labels we’ll need for expiring
  GmailApp.createLabel("expire");
  for (var expt = 0; expt < expiretimes.length; expt++) {
    GmailApp.createLabel(getLabelName(expt));
  }
    GmailApp.createLabel("expired");
}


function expiremsgs(expiremin) {
  // get current date
  var nowdate = new Date();
  Logger.log(nowdate);

  // get the label for given name
  var label = GmailApp.getUserLabelByName(getLabelName(expiremin));
  var expiredlabel = GmailApp.getUserLabelByName("expired");
  var threads = label.getThreads();
  Utilities.sleep(1000);
  for (var i = 0; i < threads.length; i++) {
    Logger.log("i: " + i);
    Logger.log(threads[i].getFirstMessageSubject());
    var lastmsgdate = threads[i].getLastMessageDate();
    Logger.log(lastmsgdate);
    var minold = (nowdate-lastmsgdate)/60000; // convert from ms to minutes
    Logger.log(minold);
    if (minold > expiremin) {
      threads[i].addLabel(expiredlabel);
      threads[i].moveToArchive();
      threads[i].removeLabel(label);
      Logger.log("Archived");
    }
  Utilities.sleep(1500);
  }
};

function expire() {
  for (var expt = 0; expt < expiretimes.length; expt++) {
    expiremsgs(expt);
  }
}

1 个答案:

答案 0 :(得分:1)

我仔细研究了你在做什么,看起来你的数学是正确的。但是,我知道使用批处理操作是使用电子表格时的最佳做法。所以,我做了一些查看参考资料,我发现了一些关键功能:

GmailApp.moveThreadsToArchive(GmailThreads[]);
label.removeFromThreads(GmailThreads[]);
label.addToThreads(GmailThreads[]);

我认为,这些函数将减少您使用API​​进行的读/写调用次数。 (谷歌OP如果我错了请纠正我。)

尽管如此,当我在玩你的代码时,我发现这些函数一次只能处理100个线程,所以如果有更多,那么必须对该操作进行批处理。我还检查了GmailApp服务调用的速度和可扩展性,发现大多数呼叫的延迟与所涉及的项目数量无关。批量存档6个线程需要(在一秒或两秒内)与100相同的时间,至少在我的测试中。在外出Gmail之前,我还努力在脚本中尽可能多地做。最后,我修改了与超时交互的方式。我无法弄清楚你是如何获得数组中的值的,所以我修改了它以及标签。他们现在将读取“过期/在15分钟内”等。该脚本大约需要30秒来处理300条左右实际上有标签的消息。

另一种方法可能是一次性运行单个搜索查找所有标签,然后检查标签。但是,当您检查每个帖子的属性时,这可能仍然会调用太多回拨给Gmail。

完成所有这些后,这是我的代码迭代:

var expiretimes = [5,15,30,60,120,180,240,480,720];

function getLabelName(i) {
  return "expire/in " + expiretimes[i]  + " min";
}

function setup() {
  GmailApp.createLabel("expired");
  GmailApp.createLabel("expire");
  for (var expt = 0; expt < expiretimes.length; expt++) {
    GmailApp.createLabel(getLabelName(expt));
  }
}

function expire() {
  var allExpThreads = [];
  for (var expt = 0; expt < expiretimes.length; expt++) allExpThreads = allExpThreads.concat(expiremsgs(expt));
  if(allExpThreads.length > 100) batchExpire(allExpThreads);
  else GmailApp.moveThreadsToArchive(allExpThreads).getUserLabelByName("expired").addToThreads(allExpThreads);
}

function expiremsgs(expiremin) {
  var label = GmailApp.getUserLabelByName(getLabelName(expiremin));   
  var threads = label.getThreads();
  if(threads.length > 0){   
    var threadsToExpire = threads.filter(msgExpired, {date: new Date(), min: expiretimes[expiremin]});
    if(threadsToExpire.length > 100) batchRemoveLabel(threadsToExpire,label);
    else if(threadsToExpire.length > 0) label.removeFromThreads(threadsToExpire);
    return threadsToExpire;
  }
  return [];
}

function msgExpired(thread) {
  return this.date - thread.getLastMessageDate() / 6000 > this.min;
}

function batchRemoveLabel(threads,label) {
  var start = 0, end = 100;
  do {
    label.removeFromThreads(threads.slice(start,end));
    start = end;
    end = end > threads.length - 100 ? threads.length : end + 100;
  } while (start < threads.length);
}

function batchExpire(threads) {
  var start = 0, end = 100;
  var expLabel = GmailApp.getUserLabelByName("expired");
  do {
    GmailApp.moveThreadsToArchive(threads.slice(start,end));
    expLabel.addToThreads(threads.slice(start,end));
    start = end;
    end = end > threads.length - 100 ? threads.length : end + 100;
  } while (start < threads.length);
}