Функция doPost выполняется дважды (скрипт Google apps)

#javascript #google-apps-script

Вопрос:

Я надеюсь на вашу помощь, так как проблема для меня нестандартная и я не смог ее решить после многих попыток.

Проблема

У меня есть стандартная функция для приема почтовых запросов, и она стабильно работает на небольших объемах, пример кода:

 let sheet = SpreadSheet.getSheetByName("name")
let dateTime = Utilities.formatDate(new Date(), "GMT 3", "dd.MM.yyy HH:mm:ss") // Moscow time
<...>
function doPost(e) {
    sheet.insertRowBefore(2) // adds a line before the second one
    sheet.getRange(2, 1).setValue(e.parameter.par1)
    sheet.getRange(2, 2).setValue(dateTime)
    sheet.getRange(2, 3).setValue(e.parameter.par2)
    sheet.getRange(2, 4).setValue(e.parameter.par3)
    sheet.getRange(2, 5).setValue(e.parameter.par4)
}
 

В таблице это выглядит так: Пример

По сути, функция должна выполняться синхронно и работать стабильно, но когда функция получает много запросов (около 140 за 1-10 секунд), она может создать две строки сразу и дважды записать данные в одну и ту же вторую строку. В результате для 140 запросов в таблице имеется ~4 пустых строки, данные из которых были утеряны

Вот как выглядит пустая строка, добавленная по ошибке: Пример

Попытка решить

Чтобы предотвратить одновременное выполнение двух сценариев, я использовал функцию LockService из сценария Google apps, мой код стал выглядеть так:

 let sheet = SpreadSheet.getSheetByName("name")
let dateTime = Utilities.formatDate(new Date(), "GMT 3", "dd.MM.yyy HH:mm:ss") // Moscow time
var lock = LockService.getScriptLock() // LockService
<...>
function doPost(e) {
  if (lock.tryLock(30000)) { // waiting for a queue 30 seconds
    sheet.insertRowBefore(2) // adds a line before the second one
    sheet.getRange(2, 1).setValue(e.parameter.par1)
    sheet.getRange(2, 2).setValue(dateTime)
    sheet.getRange(2, 3).setValue(e.parameter.par2)
    sheet.getRange(2, 4).setValue(e.parameter.par3)
    sheet.getRange(2, 5).setValue(e.parameter.par4)
    lock.releaseLock() // unblocking
  }
}
 

Я пробовал разные времена ожидания в очереди, но это не привело к успеху. Функция продолжала оставлять пустые строки

Я прошу вашей помощи, так как я долго ломал голову над этой проблемой. Что делать? Я буду благодарен за любую информацию

Ответ №1:

Пожалуйста, попробуйте выполнить flush() до setValue

Комментарии:

1. Спасибо!! Это помогло, единственное , что я поставил flush() не только до setValue , но и после

Ответ №2:

В дополнение к flush() этому я бы рекомендовал заменить это:

 // 5 calls (get/set) to server
sheet.getRange(2, 1).setValue(e.parameter.par1)
sheet.getRange(2, 2).setValue(dateTime)
sheet.getRange(2, 3).setValue(e.parameter.par2)
sheet.getRange(2, 4).setValue(e.parameter.par3)
sheet.getRange(2, 5).setValue(e.parameter.par4)
 

с этим:

 // 1 call (get/set) to the server
sheet.getRange(2,1,2,5).setValues([ 
  e.parameter.par1,
  dateTime,
  e.parameter.par2, 
  e.parameter.par3,
  e.parameter.par4
])
 

Лучшие практики: Пакетные операции

Комментарии:

1. Спасибо за ваше редактирование, оно действительно улучшило структуру кода, а также помогло в решении проблемы