如何理解LockService并正确实现它? [英] How to understand LockService and implement it correctly?

查看:681
本文介绍了如何理解LockService并正确实现它?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

代码摘要

我有一个Google Apps脚本项目,由特定域中的大约80位用户使用,但应用程序由我执行(即 Publish > 部署为web应用程序> Me )。

该脚本的一个功能是从自定义表单中填充Google表单(使用 HTML服务)然后通知我自己和提交用户(通过使用简单的登录系统和Cookie进行标识)。

大约6个月的时间内工作正常,但在1-2次通知电子邮件已发送但Google Sheet输入尚未出现。



我想这可能是由于脚本的并发使用(因为两个通知电子邮件具有相同的时间戳)并且最近了解到锁定服务

我正在使用这篇文章,以确保我对 Lock 的正确理解,以及如何实现它由于脚本并发使用,防止Google Sheet中不显示条目。



执行

我的方案的伪代码是:



Code.gs

  var active_spreadsheet = SpreadsheetApp。 openById( BBB); 

// BEGIN - 在这里启动锁

var lock = LockService.getScriptLock();
尝试{
lock.waitLock(30000); //等待30秒让其他人使用代码段并锁定停止,然后继续
} catch(e){
Logger.log('30秒后无法获得锁定。
}

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

//做很多东西 - 例如根据以前的输入颜色应用动态背景颜色,定义目标范围和设置值,设置数据验证

SpreadsheetApp.flush() ; //应用所有待处理的电子表格变化
lock.releaseLock();

// END - 结束锁定

return;

问题

< LockService getScriptLock() waitLock() releaseLock()正确?

02)是否推荐使用 SpreadsheetApp.flush(),如果是的话,上面的实现是否正确?



术语(仅供参考)



来自 https://developers.google.com/apps-script/reference/lock



< a href =https://developers.google.com/apps-script/reference/lock/lock.html =nofollow noreferrer>锁定:

互斥锁。


LockService

防止同时发生t访问代码段。

Lock类有4个方法:

hasLock()

布尔值,返回true如果获得锁定。



releaseLock()

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



tryLock(timeoutInMillis)

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

waitLock(timeoutInMillis)

void,试图获取锁定,在提供的毫秒数之后超时并发生异常。

LockService类有3种方法:

getDocumentLock() <
Lock,获取一个锁,它可以防止当前文档的任何用户同时运行一段代码。



getScriptLock()

Lock,获取锁可以防止任何用户同时运行一段代码。



getUserLock()

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

解决方案

I在上述伪代码中,一旦脚本没有获得锁定,它仍然继续运行代码。这是预期的行为?将服务器忙消息发送给用户是一种更好的做法或选择。
像这样:

  var active_spreadsheet = SpreadsheetApp.openById(bbb); 

// BEGIN - 在这里启动锁

var lock = LockService.getScriptLock();
尝试{
lock.waitLock(30000); //等待30秒让其他人使用代码段并锁定停止,然后继续
} catch(e){
Logger.log('30秒后无法获得锁定。
返回HtmlService.createHtmlOutput(< b>服务器忙请在一段时间后尝试< p>)
//如果这是异步调用的服务器端代码,则返回错误代码并显示在客户端
返回错误:服务器忙再次尝试以后...对不起:(


//注意:如果返回运行在catch上面的块不会运行,因为函数将退出

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

//做很多东西 - 例如根据以前的输入颜色应用动态背景颜色,定义目标范围和设置值,设置数据验证

SpreadsheetApp.flush(); / /应用所有待处理的电子表格变化
lock.releaseLock();

// END - 此处结束锁定

返回;

希望有帮助!


Summary of Code

I have a Google Apps Script project that is used by around 80 users within a specific domain, however the app is executed by me (ie Publish > Deploy as web app > Execute the app as: Me).

One of the functions of the script is to populate a Google Sheet from a custom form (using HTML Service) and then notify myself and the submitting user (who is identified through the use of a simple login system and cookies).

It has been working fine for about 6 months, however on 1-2 occasions the notification email has been sent but the Google Sheet entry has not appeared.

I am thinking this might be due to concurrent use of the script (as two notification emails had the same timestamp) and have recently learned of Lock Service.

I am using this post to ensure I have the correct understanding of Lock and how to implement it in order to prevent entries not appearing in the Google Sheet due to concurrent script usage.

Implementation

The pseudo code of my scenario is:

Code.gs

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.');
 }

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; 

Questions

01) Are the implementations of LockService, getScriptLock(), waitLock() and releaseLock() correct?

02) Is it recommended to use SpreadsheetApp.flush(), and if so is the implementation above correct?

Terminology (for reference)

from: https://developers.google.com/apps-script/reference/lock

Lock:
A representation of a mutual-exclusion lock.

LockService:
Prevents concurrent access to sections of code.

The Lock class has 4 methods:

hasLock()
Boolean, Returns true if the lock was acquired.

releaseLock()
void, Releases the lock, allowing other processes waiting on the lock to continue.

tryLock(timeoutInMillis)
Boolean, Attempts to acquire the lock, timing out after the provided number of milliseconds.

waitLock(timeoutInMillis)
void, Attempts to acquire the lock, timing out with an exception after the provided number of milliseconds.

The LockService class has 3 methods:

getDocumentLock()
Lock, Gets a lock that prevents any user of the current document from concurrently running a section of code.

getScriptLock()
Lock, Gets a lock that prevents any user from concurrently running a section of code.

getUserLock()
Lock, Gets a lock that prevents the current user from concurrently running a section of code.

解决方案

In the above pseudo code, once the script doesn't get a lock it will still proceed to run the code. Is that the intended behavior? It is a better practice or option to throw a server busy message to the user. Like so:

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;

Hope that helps!

这篇关于如何理解LockService并正确实现它?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆