Currently we have a Google Form that is automatically uploaded and batched in installments of ~50 forms. These come into a spreadsheet and need to be acted upon by a trigger that subscribes to the onFormSubmit event.
The problem is that since these are all uploaded simultaneously, the event fires rapidly back to back and come up with the either of the following warnings:
Too many simultaneous invocations: Spreadsheets (line 16, file "Code")
We're sorry, a server error occurred. Please wait a bit and try again. (line 12, file "Code")
According to the Daily Quotas Limit, there's a max of 20 scripted triggers per day.
That's a perfectly reasonable number, so long as I can find a way to run a single trigger for all 50 back to back form submissions at the very end.
It would be great if I could set a timeout for the execution to wait and see if any other events were fired in the next couple seconds, but I would need to be inside of a trigger handler by the time I'm executing the trigger.
Q: Is there anyway to batch Form Submission Triggers?
The problem is you seem to be creating a trigger to handle each form submit. If the handler is short and simple, do it right then onFormSubmit. If that would cause problems, instead have a single trigger that runs every 10 minutes and checks if there is work to do by remembering the last row processed and reading new rows directly from the spreadsheet. I say 10 minutes so there is no chance of overlapping one trigger instance with the next. If you use a shorter trigger make sure that parts that cannot run in parallel with a lock.
You could use the class
FormTriggerBuilder
to dynamically create and destroy triggers. You can use thePropertiesService
to persist the id for the created trigger and then programmatically delete it later like this:Alternatively, as ScampMichael pointed out, you could use the Lock Service. There's a great write up of it in this article on Concurrency and Google Apps Script. However, I'm not sure that's what I want here. The lock service will queue code waiting to be executed. Which solves the problem of concurrent executions, but not the problem of hitting daily quotas of only 20 triggers per script, depending on how the quotas are measures.
Here's an example of how a lock script could be used to prevent concurrent invocation: