Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-apps-script/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Concurrency 将脚本部署为web应用程序时锁定文档上的脚本执行_Concurrency_Google Apps Script_Google Docs - Fatal编程技术网

Concurrency 将脚本部署为web应用程序时锁定文档上的脚本执行

Concurrency 将脚本部署为web应用程序时锁定文档上的脚本执行,concurrency,google-apps-script,google-docs,Concurrency,Google Apps Script,Google Docs,我的谷歌应用程序脚本部署为web应用程序,任何用户都可以访问。其功能是打开和更改该文档中的文本 function doGet(e){ var params=e.parameters; var doc = DocumentApp.openById(params['docId']); ... /* change text of the document */ } 我将脚本a文档ID作为查询参数发送,如下所示: https://script.google.com/a/macros/s

我的谷歌应用程序脚本部署为web应用程序,任何用户都可以访问。其功能是打开和更改该文档中的文本

function doGet(e){
  var params=e.parameters;
  var doc = DocumentApp.openById(params['docId']);
  ...
  /* change text of the document */
}
我将脚本a
文档ID
作为查询参数发送,如下所示:

https://script.google.com/a/macros/s/AKfycbzCP...TnwHUbXxzDM/exec?docId=1_cMN0nuJadBw6QVjKtdEA6eXhE8ubIoxIJai1ticxnE`
Web app打开文档并更改文档中的文本

function doGet(e){
  var params=e.parameters;
  var doc = DocumentApp.openById(params['docId']);
  ...
  /* change text of the document */
}
问题

现在,当多个用户试图在同一文档上同时运行应用程序脚本时,web应用程序无法处理并发性和功能中断

我研究了锁服务,但它只适用于容器绑定脚本,不适用于web应用

然后我尝试使用
var cache=CacheService.getDocumentCache()设置属性
var documentProperties=propertiesseservice.getDocumentProperties(),但文档属性和文档缓存在web应用程序中返回
null
,并且仅限于绑定到容器的脚本,如中所述:

如果在包含 文档(例如来自独立脚本或web应用程序),此方法 返回null


当GoogleApps脚本部署为web应用时,是否有任何方法可以处理文档中脚本执行的并发性。(不受容器限制)

正如@azawaza所指出的,您应该使用具有适当范围的锁,而脚本锁更适合您的场景。这将在中讨论

如果代码的关键部分足够快,那么在对文档1进行另一次更新时,让用户等待文档2的更新就不存在真正的问题;他们不会等太久的。比如:

函数doGet1(e){
//在专用计算机上执行任何“预”操作
//或非关键共享资源。
var params=e.参数;
//获取脚本锁,因为我们将要修改共享资源。
var lock=LockService.getScriptLock();
//等待10秒钟,等待其他进程完成。
lock.waitLock(10000);
//////临界段开始VVV
var doc=DocumentApp.openById(params['docId']);
//在此处更改文档的文本
doc.saveAndClose();
//////临界截面端部^^^^^
锁。释放锁();
//继续对私有网络进行操作
//或非关键共享资源。
返回ContentService.createTextOutput(“文档已更新”)
}
特定资源锁 开箱即用的Google Apps脚本锁定服务旨在保护代码的关键部分。如果我们想要控制对特定资源的访问(可能是很长一段时间),比如谷歌文档,我们可以通过改变我们“锁定”的内容来调整它

在本例中,锁定服务保护一个关键部分,在该部分中检查和更新脚本属性。这些属性具有与我们的
docId
参数匹配的“键”;值并不重要,因为我们可以使用键的简单存在性作为测试

注意:当前,如果另一个脚本无法删除保护用户使用共享文档的属性,此脚本可能会“永远”阻止用户(直到脚本超时)。您可能希望在生产代码中更加小心

函数doGet2(e){
//在专用计算机上执行任何“预”操作
//或非关键共享资源。
var params=e.参数;
//等待对docId的独占访问
var ready=false;
//获取脚本锁,因为我们将要修改共享资源。
var lock=LockService.getScriptLock();
当(!准备就绪){
//等待最长1秒,等待其他进程完成。
如果(锁定tryLock(1000)){
//////临界段开始VVV
var properties=PropertiesService.getScriptProperties();
//如果没有人“锁定”此文档,请锁定它;我们已准备就绪。
if(properties.getProperty(docId)==null){
//设置key=docId的属性。
设置属性(docId,“锁定”);
就绪=正确;
}
//////临界截面端部^^^^^
锁。释放锁();
}
}
//我们现在可以独家访问docId。
var doc=DocumentApp.openById(params['docId']);
//在此处更改文档的文本
doc.saveAndClose();
//删除此文档的“密钥”,以便其他人可以访问它。
属性。删除属性(docId);
返回ContentService.createTextOutput(“文档已更新”)
}
命名锁 我们在前面的示例中使用的逻辑可以封装到对象中,以提供更优雅的接口。事实上,Bruce McPherson就是用他的,在他的。使用该库,您可以实现特定于文档的锁定,如下所示:

函数doGet3(e){
//在专用计算机上执行任何“预”操作
//或非关键共享资源。
var params=e.参数;
//获取一个命名锁。
var namedLock=new namedLock().setKey(docId);
namedLock.lock();
//////临界段开始VVV
//我们现在可以独家访问docId。
var doc=DocumentApp.openById(params['docId']);
//在此处更改文档的文本
doc.saveAndClose();
//////临界截面端部^^^^^
namedLock.unlock();
返回ContentService.createTextOutput(“文档已更新”)
}

您使用锁定服务的方向是正确的-您只需要使用。但是如果我使用脚本锁定,将发生的情况是,如果两个不同的用户独立处理两个不同的文档,并且他们都将调用相同的web应用,一个用户将锁定脚本,另一个用户将无需等待,因为我的核心流程每个周期大约需要2到3秒,因此即使有10人同时访问web应用程序,队列中最后一个用户的等待时间也将高达20到30秒。因为“特定资源锁”似乎很有希望,我将在脚本属性中添加
doc Id
,并且只允许那些用户在其
doc Id