简体   繁体   English

如何增加 Google Apps 脚本中的 6 分钟执行限制?

[英]How can I increase the 6 minute execution limit in Google Apps script?

Is there any way to increase the 6 minute execution time limit for Google Apps Scripts?有什么方法可以增加 Google Apps 脚本的 6 分钟执行时间限制吗? I thought that the answer might be the Early Access program for G Business Suite.我认为答案可能是 G Business Suite 的抢先体验计划。 I might be willing to pay $10 a month for G Business Suite, if I could get into the Early Access program, in order to increase the execution limit from 6 minutes to 30 minutes.如果我能进入抢先体验计划,我可能愿意每月为 G Business Suite 支付 10 美元,以便将执行限制从 6 分钟增加到 30 分钟。 But an Advisor from the G Suite Help Forum said that Early Access is a limited program, which means that there is no guarantee that I could get that.但 G Suite 帮助论坛的一位顾问表示,Early Access 是一个有限的计划,这意味着不能保证我能得到它。

Is there any other way to increase the 6 minute execution limit?还有其他方法可以增加 6 分钟的执行限制吗?

Please note that in this question I am not asking for ideas of how to optimize my scripts to fit within the 6 minute limit.请注意,在这个问题中,我并不是要询问有关如何优化我的脚本以适应 6 分钟限制的想法。 (I may ask that in the future, if the answer to this current question is "No, there is no other way.") (将来我可能会问,如果当前这个问题的答案是“不,没有其他办法。”)

Therefore, appropriate answers to this current question are:因此,当前问题的适当答案是:

  • "No, there are no other ways to increase the 6 minute execution limit for Google App Scripts." “不,没有其他方法可以增加 Google App Scripts 的 6 分钟执行限制。”
  • "Yes, there are other ways to increase the 6 minute execution limit, and these are the ways..." “是的,还有其他方法可以增加6分钟的执行限制,这些方法……”

I have dozens of jobs that take > 6 minutes to run. 我有几十个工作需要超过6分钟才能运行。 I use an "outerloop" script (below) that I've tuned over the years. 我使用了多年来我调整过的“外环”脚本(下图)。 It runs each job to completion no matter how long it takes. 无论需要多长时间,它都会完成每项工作。

Setup (just a guide - you need to apply it to your own specific scenario): 设置(只是一个指南 - 你需要将它应用到你自己的特定场景):

  1. Change the line var thingies = to whatever you want to process. 将行var thingies =更改为您要处理的任何内容。 It should ideally be an array. 理想情况下它应该是一个数组。
  2. Add your own code after the //do our work here line //do our work here之后添加你自己的代码
  3. Set a Trigger on the function named outerLoop() to run every x hours/days. 在名为outerLoop()的函数上设置触发器,每隔x小时/天运行一次。 It's OK to rename it to something meaningful to you like doProcessWidgets() . 可以将它重命名为doProcessWidgets()等对你有意义的东西。

Code: 码:

//automatically invoked from outerLoop()'s creation of a new trigger if required to get work done
function outerLoopRepeating() {
  outerLoop();
}
// trigger this function
function outerLoop() {
  try {
    var processingMessage = 'Initialising', isOverMaxRuntime = false, startTime = new Date(), // calc elapsed time
        functionName = arguments.callee.name, repeatingFunctionName = functionName + 'Repeating'; //for logging, triggering

    // Deletes all occurrences of the Repeating trigger we don't end up with undeleted time based triggers all over the place
    //add library GASRetry MGJu3PS2ZYnANtJ9kyn2vnlLDhaBgl_dE
    GASRetry.call(function(){ScriptApp.getProjectTriggers().forEach(function(i) {
      if (i.getHandlerFunction() === repeatingFunctionName) {ScriptApp.deleteTrigger(i);}
    });});

    Logger.log('========== Starting the "%s" function ==========', functionName);

    // Handle max execution times in our outer loop
    // Get start index if we hit max execution time last run
    var start = parseInt(PropertiesService.getScriptProperties().getProperty(functionName + "-start")) || 0;

    var thingies = ['stuff to process', 'in an Array',,,,]; //
    for (var i = start ; i < thingies.length; i++) {
      if (Math.round((new Date() - startTime)/1000) > 300) { //360 seconds is Google Apps Script max run time
        //We've hit max runtime. 
        isOverMaxRuntime = true;
        break;
      }
      //do our work here
      Logger.log('Inside the for loop that does the xyz work. i is currently: %d', i);
      var processingMessage = Utilities.formatString('%d of %d thingies: %s <%s>',  i+1, thingies.length, thingyName, thingyId);

      //do our work above here
    }
    if (isOverMaxRuntime) {
      //save state in user/project prop if required
      PropertiesService.getScriptProperties().setProperty(functionName + '-start', i);
      //create another trigger
      GASRetry.call(function(){ScriptApp.newTrigger(repeatingFunctionName).timeBased().everyMinutes(10).create();});
      Logger.log('Hit max run time - last iteration completed was i=%s', i-1);
    } else {
      Logger.log('Done all the work and all iterations');
      PropertiesService.getScriptProperties().deleteProperty(functionName + '-start');
      Logger.log('Completed processing all %s things with the "%s" function', thingies.length, functionName);
    }
  } catch (e) {
    Logger.log('%s. While processing %s', JSON.stringify(e, null, 2), processingMessage);
    throw e;
  }
}

For G Suite organizations, as I understand, it's possible to eliminate maximum execution time limit by signing in to Early Access Program . 对于G Suite组织,据我了解,可以通过登录Early Access Program来消除最长执行时间限制。 From Quotas for Google Services 来自Google服务的配额

Flexible Quotas Early Access 灵活的配额提前访问

This feature is part of the Early Access feature set. 此功能是Early Access功能集的一部分。 As such only some developers currently have access to it. 因此,只有一些开发人员目前可以访问它。

Normally, if a script execution exceeds one of the above quotas or limitations, the script execution stops and an appropriate error message is returned. 通常,如果脚本执行超出上述配额或限制之一,则脚本执行将停止并返回相应的错误消息。 This can potentially leave the script's data in an indefinite state. 这可能会使脚本的数据处于无限状态。

Under the flexible quota system, such hard quota limits are removed. 在灵活的配额制度下,这种硬配额限制被删除。 Scripts do not stop when they reach a quota limit. 脚本在达到配额限制时不会停止。 Rather, they are delayed until quota becomes available, at which point the script execution resumes. 相反,它们会延迟到配额可用,此时脚本执行将恢复。 Once quotas begin being used, they are refilled at a regular rate. 一旦开始使用配额,它们将以常规费率重新填充。 For reasonable usage, script delays are rare. 为了合理使用,脚本延迟很少见。

If you can't access EAP, there are several workarounds shared on this site. 如果您无法访问EAP,则此站点上共享了几种解决方法。 Some workarounds let the script to run until the error occurs, then restart it on the next item to be processed, other scripts just split the work on small enough to avoid the error pieces. 一些解决方法让脚本运行直到发生错误,然后在下一个要处理的项目上重新启动它,其他脚本只是将工作分成小到足以避免错误。

Related Q&A 相关问答

Below is another quite flexible approach by Inclu Cat (the author of GasTerminal ) which also supports long running functions.下面是 Inclu Cat( GasTerminal的作者)的另一种非常灵活的方法,它也支持长时间运行的函数。

The repository for the independent long-run implementation contains eg the following example.独立长期实施的存储库包含例如以下示例。 It demonstrates the separation of initializer (testInitializer), runner (testMain), and finalizer (testFinalizer) below as gas compiled version.它演示了下面作为 gas 编译版本的初始化器 (testInitializer)、运行器 (testMain) 和终结器 (testFinalizer) 的分离。

var exports = exports || {};
var module = module || { exports: exports };
Object.defineProperty(exports, "__esModule", { value: true });
//import {executeLongRun, LongRun} from "../LongRun";
var data;
function executeTest2() {
    var params = [];
    params.push("param1");
    params.push("param2");
    params.push("param3");
    // shorten the executable time for testing. (default is 240 seconds)
    LongRun.instance.setMaxExecutionSeconds(1);
    // execute the test
    // you can see the logs in Executions section
    executeLongRun("testMain", 3, params, "testInitializer", "testFinalizer");
}
function testInitializer(startIndex, params) {
    if (startIndex == 0) {
        console.log('*** executeLongRun started. ***');
    }
    console.log("testInitializer(startIndex=" + startIndex + "," + " params=[" + params.join(',') + "])");
    // demonstrate loading data
    data = ["data1", "data2", "data3", "data4", "data5", "data6", "data7", "data8", "data9", "data10"];
}
function testMain(index, params) {
    console.log("testMain(index=" + index + "," + " params=[" + params.join(',') + "])");
    // demonstrate the process
    console.log("  processing " + data[index] + "...");
    Utilities.sleep(1000);
}
function testFinalizer(isFinished, params) {
    console.log("testFinalizer(" + isFinished + ",[" + params.join(',') + "])");
    // demonstrate finalization
    if (isFinished) {
        console.log('--- executeLongRun finished. ---');
    }
}

I like that idea of separation for more complex cases.对于更复杂的案例,我喜欢这种分离的想法。

GasTerminal allows long running functions as well with a similar approach, but might be overkill for some users who are just looking for long run functionality. GasTerminal 也允许长时间运行的功能以及类似的方法,但对于一些只寻找长期运行功能的用户来说可能有点过分了。 A longer discussion of it's workaround can be seen here ).可以在此处看到对其解决方法的更长时间讨论)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM