首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将脚本部署为web应用程序时,锁定文档上的脚本执行

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

Stack Overflow用户
提问于 2016-01-19 13:32:25
回答 1查看 1.2K关注 0票数 1

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

我向脚本发送一个document ID作为查询参数,如下所示:

代码语言:javascript
复制
https://script.google.com/a/macros/s/AKfycbzCP...TnwHUbXxzDM/exec?docId=1_cMN0nuJadBw6QVjKtdEA6eXhE8ubIoxIJai1ticxnE`

Web应用程序打开文档并更改文档中的文本。

代码语言:javascript
复制
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 = PropertiesService.getDocumentProperties();为文档设置属性,但是文档属性和文档缓存在web应用程序中返回null,并且仅限于容器绑定脚本,如文档中所述。

如果在包含文档的上下文之外调用此方法(例如从独立脚本或web应用程序调用),则此方法返回null。

当Google脚本部署为web应用程序时,是否有任何方法处理文档中脚本执行的并发性。(非货柜装订)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-01-19 18:52:47

正如@azawaza所指出的,您应该使用具有适当作用域的Lock,并且脚本锁更适合您的场景。这是在此代码是否正确锁定了onFormSubmit(e)方法?中讨论的。

如果代码的关键部分足够快,那么在文档1的另一个更新继续进行时,让用户更新Document 2并不会引起真正的关注;他们不会等很久。类似于:

代码语言:javascript
复制
function doGet1(e){
  // Perform any "pre" operations on private
  // or non-critical shared resources.
  var params=e.parameters;

  // Get a script lock, because we're about to modify a shared resource.
  var lock = LockService.getScriptLock();
  // Wait for up to 10 seconds for other processes to finish.
  lock.waitLock(10000);

  ////// Critical section begins   vvvvv

  var doc = DocumentApp.openById(params['docId']);

  // change text of the document here

  doc.saveAndClose();

  ////// Critical section ends     ^^^^^
  lock.releaseLock();

  // Continue with operations on private
  // or non-critical shared resources.

  return ContentService.createTextOutput("Document updated.")
}

特定资源锁

开箱即用的Google脚本锁定服务是为了保护关键的代码部分而设计的。如果我们想控制对特定资源的访问(可能需要很长一段时间),比如Google文档,我们可以通过更改我们正在“锁定”的内容来调整它。

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

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

代码语言:javascript
复制
function doGet2(e){
  // Perform any "pre" operations on private
  // or non-critical shared resources.
  var params=e.parameters;

  // Wait for exclusive access to docId
  var ready = false;
  // Get a script lock, because we're about to modify a shared resource.
  var lock = LockService.getScriptLock();

  while (!ready) {
    // Wait for up to 1 second for other processes to finish.
    if (lock.tryLock(1000)) {
      ////// Critical section begins   vvvvv      

      var properties = PropertiesService.getScriptProperties();

      // If nobody has "locked" this document, lock it; we're ready.
      if (properties.getProperty(docId) == null) {
        // Set a property with key=docId.
        properties.setProperty(docId,"Locked"); 
        ready = true;
      }

      ////// Critical section ends     ^^^^^
      lock.releaseLock();
    }
  }

  // We have exclusive access to docId now.

  var doc = DocumentApp.openById(params['docId']);

  // change text of the document here

  doc.saveAndClose();

  // Delete the "key" for this document, so others can access it.
  properties.deleteProperty(docId); 

  return ContentService.createTextOutput("Document updated.")
}

命名锁

我们在前面的示例中使用的逻辑可以封装到一个对象中,以提供更优雅的接口。事实上,布鲁斯McPherson就是用他在桌面解放网站上描述的cNamedLock库来做的。使用该库,您可以实现如下所示的特定于文档的锁定:

代码语言:javascript
复制
function doGet3(e){
  // Perform any "pre" operations on private
  // or non-critical shared resources.
  var params=e.parameters;

  // Get a named lock.
  var namedLock = new NamedLock().setKey(docId);

  namedLock.lock();
  ////// Critical section begins   vvvvv      

  // We have exclusive access to docId now.

  var doc = DocumentApp.openById(params['docId']);

  // change text of the document here

  doc.saveAndClose();

  ////// Critical section ends     ^^^^^
  namedLock.unlock();

  return ContentService.createTextOutput("Document updated.")
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34878161

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档