You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Google Apps Script LockService不生效 无法限制多用户同时打开侧边栏

问题描述

在绑定至Google Sheets的Apps Script脚本中实现侧边栏功能时,期望通过锁机制控制同一时间仅允许单个用户打开侧边栏,初始实现代码如下:

function loadM1DocsSideBar() {
  var lock = LockService.getScriptLock();
  lock.tryLock(0);
  if (!lock.hasLock()) {
    SpreadsheetApp.getUi().alert("WARNING! Function currently in use by another user. Please try again later.");
    return;
  }

  Logger.log(lock);
 
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sh = ss.getSheetByName("Metadata");
  var dataRange = sh.getRange("metadataRecord").clearContent();
  
  var form = HtmlService.createHtmlOutputFromFile('M1DocsConfiguratorSidebar').setTitle('Verification Project Library Creator');
  SpreadsheetApp.getUi().showSidebar(form);

  lock.releaseLock();
}

测试过程中发现两名用户仍然可以同时成功启动侧边栏,需要定位代码中的逻辑错误。

代码核心问题
  • 锁的生命周期完全不匹配业务需求:这是并发控制失效的根本原因。LockService的锁仅在当前服务端函数执行的上下文中生效,你在调用showSidebar()完成侧边栏渲染触发后,立刻执行了lock.releaseLock()释放锁——整个加锁的时间窗口只覆盖了函数执行的几十到几百毫秒,根本没有覆盖用户打开侧边栏后的整个使用周期。第一个用户触发函数执行完锁就已经释放,第二个用户后续触发时自然可以正常拿到锁、打开侧边栏。
  • 锁机制本身的能力边界没有匹配场景:ScriptLock是服务端单次代码执行的互斥工具,无法跟踪浏览器端侧边栏的打开状态。侧边栏渲染完成后,后续交互是前端和服务端的异步通信,服务端函数执行结束后上下文就销毁了,不可能靠单次函数里加的锁持续阻止其他用户访问。
  • tryLock(0)的参数设置仅会让锁不等待重试,不是导致并发失效的核心原因。
可行修正方案
  • 放弃「单次函数加锁、函数结束释放」的思路,改用持久化状态标记锁状态:可以用文档属性、隐藏工作表单元格存储当前持锁用户ID、加锁时间、锁过期时间。
  • 打开侧边栏前先检查持久化的锁状态:如果存在未过期、且不属于当前用户的锁,直接弹出提示阻止打开。
  • 侧边栏前端增加心跳逻辑:每隔固定间隔(比如1分钟)调用服务端接口续期锁,更新过期时间,证明当前用户仍在使用侧边栏。
  • 侧边栏关闭、用户提交完操作时,前端主动调用服务端接口清除锁标记。
  • 给锁设置兜底过期时间(比如30分钟),避免用户异常关闭侧边栏导致锁永远不释放。

内容的提问来源于stack exchange,提问作者Mike Eburne

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 12:30:48