Google apps script 如何理解LockService并正确实施它?

Google apps script 如何理解LockService并正确实施它?,google-apps-script,locking,Google Apps Script,Locking,代码摘要 我有一个Google Apps脚本项目,在一个特定的域中有大约80个用户使用,但是该应用程序是由我执行的(即PublishDeploy as web app将应用程序执行为:me) 该脚本的功能之一是从自定义表单(使用HTML服务)填充谷歌表单,然后通知我自己和提交用户(通过使用简单的登录系统和cookie识别) 它已经工作了大约6个月,但是有1-2次通知邮件已经发送,但是谷歌表单条目没有出现 我认为这可能是由于同时使用了脚本(因为两封通知电子邮件具有相同的时间戳),并且最近了解到 我

代码摘要

我有一个Google Apps脚本项目,在一个特定的域中有大约80个用户使用,但是该应用程序是由我执行的(即
Publish
Deploy as web app
将应用程序执行为
me

该脚本的功能之一是从自定义表单(使用
HTML服务
)填充谷歌表单,然后通知我自己和提交用户(通过使用简单的登录系统和cookie识别)

它已经工作了大约6个月,但是有1-2次通知邮件已经发送,但是谷歌表单条目没有出现

我认为这可能是由于同时使用了脚本(因为两封通知电子邮件具有相同的时间戳),并且最近了解到

我使用这篇文章是为了确保我对
Lock
有正确的理解,以及如何实现它,以防止由于并发脚本使用而在Google工作表中不出现条目

实施

我的场景的伪代码是:

代码.gs

问题

function myFunction() {
  var lock = LockService.getScriptLock();
  lock.tryLock(5000);
  if (!lock.hasLock()) {
    Logger.log('Could not obtain lock after 5 seconds.');
    return;
  }
  else if (lock.hasLock()) {
    Logger.log('got the lock');
    //Browser.inputBox("TESTING123");
    Utilities.sleep(10000);
  }
lock.releaseLock();
}
01)锁服务
LockService
getScriptLock()
waitLock()
releaseLock()的实现是否正确

02)是否建议使用
SpreadsheetApp.flush()
,如果是,上述实现是否正确

术语(供参考)

发件人:


互斥锁的表示


防止对代码段的并发访问

Lock类有4种方法:


布尔值,如果已获取锁,则返回true


void,释放锁,允许等待锁的其他进程继续


布尔值,尝试获取锁,在提供的毫秒数后超时


void,尝试获取锁,在提供的毫秒数之后超时,出现异常

LockService类有3种方法:


Lock,获取阻止当前文档的任何用户同时运行代码段的锁


Lock,获取阻止任何用户同时运行代码段的锁



Lock,获取阻止当前用户同时运行代码段的锁。

在上面的伪代码中,一旦脚本没有获得锁,它仍将继续运行代码。这就是我们想要的行为吗?向用户抛出服务器繁忙消息是更好的做法或选项。 像这样:

var active_spreadsheet = SpreadsheetApp.openById("bbb");

// BEGIN - start lock here

var lock = LockService.getScriptLock();
try {
    lock.waitLock(30000); // wait 30 seconds for others' use of the code section and lock to stop and then proceed
} catch (e) {
    Logger.log('Could not obtain lock after 30 seconds.');
    return HtmlService.createHtmlOutput("<b> Server Busy please try after some time <p>")
    // In case this a server side code called asynchronously you return a error code and display the appropriate message on the client side
    return "Error: Server busy try again later... Sorry :("
}

// note:  if return is run in the catch block above the following will not run as the function will be exited

var active_sheet = active_spreadsheet.getSheetByName("ENTRIES");
var new_start_row = active_sheet.getLastRow() + 1;

//  Do lots of stuff - ie apply dynamic background colors based on previous entries colors, define the target range and set values, set data validations  

SpreadsheetApp.flush(); // applies all pending spreadsheet changes
lock.releaseLock();

// END - end lock here

return;
var active_电子表格=电子表格app.openById(“bbb”);
//开始-开始锁定在这里
var lock=LockService.getScriptLock();
试一试{
lock.waitLock(30000);//等待30秒,等待其他人使用代码段并锁定停止,然后继续
}捕获(e){
Logger.log('30秒后无法获得锁');
返回HtmlService.createHtmlOutput(“服务器忙,请稍后再试”)
//如果这是一个异步调用的服务器端代码,则返回一个错误代码并在客户端显示相应的消息
return“错误:服务器正忙,请稍后再试…抱歉:(”
}
//注意:如果在上面的catch块中运行return,则以下操作将不会运行,因为函数将退出
var active_sheet=active_电子表格.getSheetByName(“条目”);
var new_start_row=活动的_sheet.getLastRow()+1;
//做很多事情-例如根据以前的条目应用动态背景颜色颜色,定义目标范围和设置值,设置数据验证
SpreadsheetApp.flush();//应用所有挂起的电子表格更改
锁。释放锁();
//这里是端锁
返回;

希望有帮助!

所以我想我发现了锁定系统的一个问题。也就是说,当你触发一个弹出框(显示在工作表中)时在脚本中,它会删除锁…或者类似的东西,因为它肯定不会保留锁。我有一段代码,我正在尝试运行,基本上没有弹出框,锁定系统可以工作。没有问题,当第一个用户拥有锁时,haslock确实会返回false…但随后您引入了一个弹出框和锁定系统不能像它应该的那样工作,即使弹出框和那一行代码,或者它后面的任何一行代码没有被执行,也会给第二个用户一个锁。我在弹出框之后延迟了一下尝试,因为我最初认为它可能没有等待输入回来,所以它只是有点跳过在弹出框被推到工作表上之后…但是即使在代码的弹出框部分之后有很长的延迟(脚本仍然在我面前运行)第二个用户仍然被授予一个锁。也许我做得不对,但是弹出框是唯一会抛出我的代码的东西。我尝试了try、catch和if、if-else…但没有运气,我甚至尝试了if、else…我知道这不是因为trylock/waitlock太长或太短。我尝试了一系列值,我也知道它不是sleep bc我在代码中尝试了一系列的值,以及不同的位置。在不同的google用户帐户上进行了大量测试,在公元前几天的不同日子里,我原本以为这是我在装傻什么的。但实际上,似乎弹出框是唯一将其发送出预订的东西。。 锁定系统何时工作的示例

function myFunction() {
  var lock = LockService.getScriptLock();
  lock.tryLock(5000);
  if (!lock.hasLock()) {
    Logger.log('Could not obtain lock after 5 seconds.');
    return;
  }
  else if (lock.hasLock()) {
    Logger.log('got the lock');
    //Browser.inputBox("TESTING123");
    Utilities.sleep(10000);
  }
lock.releaseLock();
}
二,

使用建议的try,catch语句

function myFunction() {
  var lock = LockService.getScriptLock();
  try {
    lock.waitLock(5000); // wait 5 seconds try to get lock
  } catch (e) {
    Logger.log('Could not obtain lock after 5 seconds.');
  }
  Utilities.sleep(10000);
  //Browser.inputBox("TESTING123");
  lock.releaseLock();
}
function myFunction() {
  var lock = LockService.getScriptLock();
  try {
    lock.waitLock(5000); // wait 5 seconds try to get lock
  } catch (e) {
    Logger.log('Could not obtain lock after 5 seconds.');
  }
  Utilities.sleep(10000);
  Browser.inputBox("TESTING123");
  lock.releaseLock();
}
它确实捕获了错误,并显示弹出窗口,表示无法获取错误

不起作用的示例

function myFunction() {
  var lock = LockService.getScriptLock();
  lock.tryLock(5000);
  if (!lock.hasLock()) {
    Logger.log('Could not obtain lock after 5 seconds.');
    return;
  }
  else if (lock.hasLock()) {
    Logger.log('got the lock');
    Browser.inputBox("TESTING123");
    Utilities.sleep(10000);
  }
 lock.releaseLock();
}
二,

使用建议的try-catch语句

function myFunction() {
  var lock = LockService.getScriptLock();
  try {
    lock.waitLock(5000); // wait 5 seconds try to get lock
  } catch (e) {
    Logger.log('Could not obtain lock after 5 seconds.');
  }
  Utilities.sleep(10000);
  //Browser.inputBox("TESTING123");
  lock.releaseLock();
}
function myFunction() {
  var lock = LockService.getScriptLock();
  try {
    lock.waitLock(5000); // wait 5 seconds try to get lock
  } catch (e) {
    Logger.log('Could not obtain lock after 5 seconds.');
  }
  Utilities.sleep(10000);
  Browser.inputBox("TESTING123");
  lock.releaseLock();
}
弹出框在所有情况下都会出现。它不应该出现,因为弹出框没有显示