【问题标题】:Prevent "Too many simultaneous invocations" on formSubmit防止 formSubmit 上的“太多同时调用”
【发布时间】:2015-04-15 18:45:49
【问题描述】:

目前,我们有一个 Google 表单,它会自动上传并分批分批,大约 50 个表单。这些进入电子表格,需要通过订阅onFormSubmit event 的触发器来执行。

问题在于,由于这些都是同时上传的,因此事件会迅速背靠背触发并出现以下警告之一:

同时调用太多:电子表格(第 16 行,文件“代码”)
很抱歉,发生服务器错误。请稍等,然后重试。 (第 12 行,文件“代码”)

根据Daily Quotas Limit,每天最多有 20 个脚本触发器。

这是一个完全合理的数字,只要我能找到一种方法,在最后为所有 50 个背靠背表单提交运行单个触发器。

如果我可以设置执行超时以等待并查看在接下来的几秒钟内是否触发了任何其他事件,那就太好了,但是在我执行时我需要在触发器处理程序中触发器。

:是否可以批量处理表单提交触发器?

【问题讨论】:

标签: google-apps-script google-sheets google-forms


【解决方案1】:

问题是您似乎正在创建一个触发器来处理每个表单提交。如果处理程序简短而简单,请立即执行 onFormSubmit。如果这会导致问题,请改为使用一个触发器,该触发器每 10 分钟运行一次,并通过记住已处理的最后一行并直接从电子表格中读取新行来检查是否有工作要做。我说 10 分钟,所以没有机会与下一个触发实例重叠。如果您使用较短的触发器,请确保无法与锁并行运行的部分。

【讨论】:

    【解决方案2】:

    您可以使用FormTriggerBuilder 类来动态创建和销毁触发器。您可以使用 PropertiesService 来持久化创建的触发器的 id,然后使用 programmatically delete it later 像这样:

    var formID = 'XXXXXXX';
    var properties = PropertiesService.getScriptProperties()
    
    function onInstall() {
      createSubmitHandler()
    }
    
    function createSubmitHandler() {
     var form = FormApp.openById(formID);
     var trigger = ScriptApp.newTrigger('onSubmit')
         .forForm(form)
         .onFormSubmit()
         .create();
    
      properties.setProperty('triggerID', trigger.getUniqueId())
    }
    
    function destroySubmitHandler() {
       var triggerID = properties.getProperty('triggerID')
       var form = FormApp.openById(formID);
       var allTriggers = ScriptApp.getUserTriggers(form)
       for (var i = 0; i < allTriggers.length; i++) {
         if (allTriggers[i].getUniqueId() == triggerID) {
           ScriptApp.deleteTrigger(allTriggers[i]);
           break;
         }
       }
    }
    
    function onSubmit() {
      // we've been called, remove trigger, set timeout, re-enable, and then run function
      destroySubmitHandler();
      Utilities.sleep(5 * 1000)
      createSubmitHandler();
      myFunction()
    }
    
    function myFunction() {
      // do stuff here
    }
    

    或者,正如 ScampMichael 指出的那样,您可以使用 Lock Service。在Concurrency and Google Apps Script 上的这篇文章中有一篇很棒的文章。但是,我不确定这就是我想要的。锁服务将等待执行的代码排队。这解决了并发执行的问题,但没有解决每个脚本每天只能触发 20 个触发器的问题,具体取决于配额的衡量方式。

    这是一个如何使用锁定脚本来防止并发调用的示例:

    function onSubmit() {
      // we've been called, get a public lock, wait for other job to finish, run the function, and release the cracken
      var lock = LockService.getScriptLock();
      lock.tryLock(30 * 1000);
      myFunction();
      lock.releaseLock();
    }
    
    function myFunction() {
      // do stuff here
    }
    

    【讨论】:

      猜你喜欢
      • 2021-12-27
      • 1970-01-01
      • 1970-01-01
      • 2022-01-08
      • 2012-01-30
      • 1970-01-01
      • 1970-01-01
      • 2015-10-31
      • 1970-01-01
      相关资源
      最近更新 更多