使用Y.JS+Hocuspocus+Tiptap时数据持久化遇栈溢出错误求助
我在使用Y.js搭配Hocuspocus和Tiptap编辑器实现协作编辑时,遇到数据持久化相关的栈溢出错误,错误日志如下:
sync.js:86 Caught error while handling a Yjs update RangeError: Maximum call stack size exceeded at Transaction.js:307:38 at Map.forEach (<anonymous>) at cleanupTransactions (Transaction.js:307:30) at cleanupTransactions (Transaction.js:370:9) at cleanupTransactions (Transaction.js:370:9) at cleanupTransactions (Transaction.js:370:9) at cleanupTransactions (Transaction.js:370:9) at cleanupTransactions (Transaction.js:370:9) at cleanupTransactions (Transaction.js:370:9) at cleanupTransactions (Transaction.js:370:9) readSyncStep2 @ sync.js:86 readSyncMessage @ sync.js:121 applySyncMessage @ MessageReceiver.ts:70 apply @ MessageReceiver.ts:31 onMessage @ HocuspocusProvider.ts:561
已尝试关闭多项功能,但错误仍存在,求各位帮忙排查。
可能的解决方案:
排查持久化钩子的循环触发
栈溢出大概率是持久化逻辑触发了Y.js更新的循环调用。比如在Hocuspocus的onStoreDocument或onChange钩子中,如果修改了Y.Doc或者触发了会生成Y.js update的操作,就会无限触发「钩子→更新→钩子」的循环。
解决:给持久化逻辑加个标志位,执行时暂时禁用钩子,或者判断当前更新是否来自持久化操作本身,避免重复触发。升级依赖到最新稳定版
这个错误可能是Y.js或Hocuspocus的已知bug,比如旧版本中事务清理的递归逻辑缺陷。尝试升级Y.js到13.6.x、Hocuspocus到2.10.x这类最新稳定版,很多递归栈溢出问题已经被修复。检查Tiptap扩展的过度更新
某些自定义Tiptap扩展可能会在内容变化时频繁触发Y.js更新,进而引发事务清理的递归死循环。可以逐步禁用扩展,定位是否有扩展导致的问题。规范Y.js事务使用
确保所有手动创建的Y.js事务都通过transaction.commit()正确提交,避免嵌套事务滥用。未正确闭合的事务可能会让清理逻辑进入递归循环。检查服务器端持久化的文档加载逻辑
如果用了自定义服务器端持久化(比如存数据库),确认读取文档时没有重复加载旧的update,导致客户端和服务器反复同步。从数据库读取后要正确初始化Y.Doc,不要重复应用历史更新。
内容的提问来源于stack exchange,提问作者Hoshang

