我的Google脚本部署为web应用程序,任何用户都可以访问。它的功能是打开和更改该文档中的文本。
我向脚本发送一个document ID作为查询参数,如下所示:
https://script.google.com/a/macros/s/AKfycbzCP...TnwHUbXxzDM/exec?docId=1_cMN0nuJadBw6QVjKtdEA6eXhE8ubIoxIJai1ticxnE`Web应用程序打开文档并更改文档中的文本。
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应用程序时,是否有任何方法处理文档中脚本执行的并发性。(非货柜装订)
发布于 2016-01-19 18:52:47
正如@azawaza所指出的,您应该使用具有适当作用域的Lock,并且脚本锁更适合您的场景。这是在此代码是否正确锁定了onFormSubmit(e)方法?中讨论的。
如果代码的关键部分足够快,那么在文档1的另一个更新继续进行时,让用户更新Document 2并不会引起真正的关注;他们不会等很久。类似于:
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参数匹配的“键”;值并不重要,因为我们可以使用键的简单存在作为我们的测试。
注意:当前,如果另一个脚本无法删除保护用户使用共享文档的属性,则该脚本可能会“永远”阻止用户(直到脚本超时)。您会希望在生产代码中更加小心。
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库来做的。使用该库,您可以实现如下所示的特定于文档的锁定:
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.")
}https://stackoverflow.com/questions/34878161
复制相似问题