时钟触发生成器不调用函数时安排-谷歌表应用程序脚本



我正在使用谷歌提供的应用程序脚本,通过表格访问他们的预测API。我试图一次预测数千行,然而,6分钟后,在代码停止时达到了最大执行时间。

我实现了一个解决方案,我发现使用时钟触发生成器。一旦我运行这个函数,它就会运行5分钟,然后它会停止,并在2分钟内设置一个触发器来召回这个函数。

主要问题是该函数在调度时没有被调用。我在当前触发器列表中看到它,但它不会再被调用。你能解释一下为什么会这样吗?

我的意图是在5分钟内预测尽可能多的行,然后停止,设置一个触发器,在几分钟内再次调用预测函数,从它离开的地方开始,并继续,直到每个元素都被预测。

我还需要知道如何将这些值存储在缓存中,以便在再次调用函数时知道所需的所有信息。

//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);
  }
}

为什么你的代码没有按预期运行:

1)既然你提到,"我在当前触发器列表中看到它,但它永远不会再次被调用",看看你的代码,我不确定你是否打算在它的执行完成后再次调用该函数。如果您这样做,这是因为您的for循环运行了一段时间,直到获得instances的长度。脚本中没有任何内容表明该函数在完成对instances的迭代后需要再次运行。请参阅此链接,了解如何以编程方式管理触发器。

2) var builder = ScriptApp.newTrigger('predict').timeBased().after(REASONABLE_TIME_TO_WAIT);

这行代码属于if条件,停止执行1分钟(值为60000)。因此,在执行开始后的时间上增加1分钟。您没有将startTime计数器重置为等待时间之后的时间,因为一旦currTime - startTime的值超过MAX_RUNNING_TIME,该函数将在此后的for循环的所有迭代中继续调用if循环。简单地说,如果startTime是9:35,currTime是9:40,等待1分钟后,currTime是9:41,仍然比MAX_RUNNING_TIME(5分钟)多,因为startTime的值仍然是9:35。此时将其重置为9:41应该可以解决您的问题。

3)在if循环中丢失break可能也有助于解决这个问题。

编辑:

添加一个函数,如下面的链接所示:

function callTrigger(){
  ScriptApp.newTrigger('predict')
      .timeBased()
      .everyMinutes(30)
      .create();
}

在编辑器中运行一次callTrigger函数,应该就可以了。请记住,对于几分钟,您只能传递值1、5、15或30。

相关内容

最新更新