2015-04-15 4 views
0

В настоящее время у нас есть форма Google, которая автоматически загружается и выгружается в рассрочку ~ 50 форм. Они входят в электронную таблицу и должны срабатывать при срабатывании триггера, который подписывается на onFormSubmit event.Предотвращение «Слишком много одновременных вызовов» на formSubmit

Проблема заключается в том, что, поскольку все они загружены одновременно, срабатывает событие быстро вернуться назад и прийти с одним из следующих предупреждений:

Слишком много одновременных вызовов: Таблицы (строка 16, файл «Код»)
К сожалению, произошла ошибка сервера. Подождите немного и повторите попытку. (строка 12, файл «Код»)

Согласно Daily Quotas Limit, существует максимум 20 сценариев триггеров в день.

Это вполне разумное число, если я могу найти способ запуска одного триггера для всех 50 обратных представлений формы в самом конце.

Было бы здорово, если бы я мог установить тайм-аут для выполнения, чтобы подождать и посмотреть, были ли какие-либо другие события запущены в ближайшие пару секунд, но мне нужно будет находиться внутри обработчика триггеров к тому моменту, когда я выполнение триггера.

Q: Есть ли способ для отправки триггеров отправки формы?

+2

Смотрите, если это может помочь: https://developers.google.com/apps-script/reference/lock /замок – ScampMichael

ответ

1

Проблема заключается в том, что вы создаете триггер для обработки каждой формы submit. Если обработчик является коротким и простым, сделайте это прямо в onFormSubmit. Если это вызовет проблемы, вместо этого будет иметься один триггер, который запускается каждые 10 минут и проверяет, есть ли работа, чтобы запомнить последнюю обработанную строку и прочитать новые строки непосредственно из электронной таблицы. Я говорю 10 минут, поэтому нет возможности совместить один экземпляр триггера со следующим. Если вы используете более короткий триггер, убедитесь, что части, которые не могут работать параллельно с блокировкой.

1

Вы можете использовать класс FormTriggerBuilder для динамического создания и уничтожения триггеров. Вы можете использовать PropertiesService сохраняться идентификатор для созданного триггера, а затем 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 
}