1

我正在使用 LockService 来避免重复操作,但是在测试期间我不能让 tryLock 失败。

假设这段代码几乎同时运行不止一次时应该在 ScriptProperties 中写入错误,但到目前为止还没有。

第二个 App 实例应该在 tryLock 1 秒后失败,而第一个实例正在休眠 15 秒,对吧?

有什么建议么?

function doGet() {
  testingLockService(1000, 15000);
  return;
}
function testingLockService(trying, sleeping) {
  var lock = LockService.getPrivateLock();
  var hasMutex = lock.tryLock(trying);
  if (hasMutex == false) { ScriptProperties.setProperty("LockService",new Date().toString()+" tryLock failed"); return; }
  Utilities.sleep(sleeping);
  lock.releaseLock();
  return;
}
4

1 回答 1

1

有趣的问题。在玩了一会儿之后,我认为锁定正在起作用,它只是看起来不是因为 Google Apps 脚本似乎不允许并发获取请求,而是将它们排队。通过将锁定测试移动到服务器端,它就可以工作了。

如果您让 get 请求向用户返回某些内容而不是将其放入脚本属性中,这将更容易调试。

以下代码将演示排队的获取请求。测试:发出两个并发请求,并查看返回的时间戳,有趣的是,您会注意到第二个请求在第一个请求的结束时间戳之前不会有一个开始时间戳,无论它们有多接近。所以第二个请求可以完美有效地获得锁。这是代码:

function doGet() {
  var app = UiApp.createApplication();

  var tS = new Date();
  var gotLock = testingLockService(0, 5000);
  var tF = new Date();

  var label = app.createLabel(gotLock ? 'Got the lock, and slept' : "Didn't get the lock");
  app.add(label);

  var label = app.createLabel('tS ' + tS.getTime());
  app.add(label);
  var label = app.createLabel('tF ' + tF.getTime());
  app.add(label);
  var label = app.createLabel('t delta ' + (tF - tS));
  app.add(label);

  return app;
}

function testingLockService(trying, sleeping) {
  var lock = LockService.getPrivateLock();
  var hasMutex = lock.tryLock(trying);
  if (!hasMutex) { return false; }
  Utilities.sleep(sleeping);
  lock.releaseLock();
  return true;
}

现在,为了证明锁定确实有效,只需将锁​​定代码移动到服务器端。同样,为了测试,打开两个浏览器窗口并单击两个按钮。这一次你会看到第二个请求获取锁失败并立即返回。

function doGet() {
  var app = UiApp.createApplication();
  var serverHandler = app.createServerHandler('doClick');
  var button = app.createButton().setText("click me").addClickHandler(serverHandler);
  app.add(button);
  return app;
}

function doClick() {
  var app = UiApp.getActiveApplication();
  // code from here on is identical to previous example
  var tS = new Date();
  var gotLock = testingLockService(0, 5000);
  var tF = new Date();

  var label = app.createLabel(gotLock ? 'Got the lock, and slept' : "Didn't get the lock");
  app.add(label);

  var label = app.createLabel('tS ' + tS.getTime());
  app.add(label);
  var label = app.createLabel('tF ' + tF.getTime());
  app.add(label);
  var label = app.createLabel('t delta ' + (tF - tS));
  app.add(label);

  return app;
}

function testingLockService(trying, sleeping) {
  var lock = LockService.getPrivateLock();
  var hasMutex = lock.tryLock(trying);
  if (!hasMutex) { return false; }
  Utilities.sleep(sleeping);
  lock.releaseLock();
  return true;
}

Hopefully that has answered your question on the locking. Though it raises questions in my mind about the get request queueing. Is it only requests from the same user? I would love to hear from someone else if they have any more info on that, although, maybe that belongs in a question on its own.

于 2012-12-17T12:21:13.423 回答