瀏覽代碼

:bug: 短时间内多次修改文档定义块标题后动态锚文本没有跟随 Fix https://github.com/siyuan-note/siyuan/issues/6330

Liang Ding 2 年之前
父節點
當前提交
055a8b5981
共有 2 個文件被更改,包括 39 次插入22 次删除
  1. 10 19
      kernel/model/file.go
  2. 29 3
      kernel/model/transaction.go

+ 10 - 19
kernel/model/file.go

@@ -1282,6 +1282,15 @@ func RenameDoc(boxID, p, title string) (err error) {
 		title = "Untitled"
 		title = "Untitled"
 	}
 	}
 
 
+	oldHPath := tree.HPath
+	tree.HPath = path.Join(path.Dir(tree.HPath), title)
+	tree.Root.SetIALAttr("title", title)
+	tree.Root.SetIALAttr("updated", util.CurrentTimeSecondsStr())
+
+	if err = renameWriteJSONQueue(tree, oldHPath); nil != err {
+		return
+	}
+
 	refText := getNodeRefText(tree.Root)
 	refText := getNodeRefText(tree.Root)
 	evt := util.NewCmdResult("rename", 0, util.PushModeBroadcast, util.PushModeNone)
 	evt := util.NewCmdResult("rename", 0, util.PushModeBroadcast, util.PushModeNone)
 	evt.Data = map[string]interface{}{
 	evt.Data = map[string]interface{}{
@@ -1293,26 +1302,8 @@ func RenameDoc(boxID, p, title string) (err error) {
 	}
 	}
 	util.PushEvent(evt)
 	util.PushEvent(evt)
 
 
-	oldHPath := tree.HPath
-	tree.HPath = path.Join(path.Dir(tree.HPath), title)
-	tree.Root.SetIALAttr("title", title)
-	tree.Root.SetIALAttr("updated", util.CurrentTimeSecondsStr())
-
-	if err = renameWriteJSONQueue(tree, oldHPath); nil != err {
-		return
-	}
-
 	box.renameSubTrees(tree)
 	box.renameSubTrees(tree)
-	changedDefs := map[string]*ast.Node{tree.ID: tree.Root}
-	changedTrees := map[string]*parse.Tree{tree.ID: tree}
-
-	// 引用文档时锚文本没有跟随文档重命名 https://github.com/siyuan-note/siyuan/issues/4193
-	// 详见 refreshDynamicRefText 函数实现
-	go func() {
-		sql.WaitForWritingDatabase()
-		refreshDynamicRefText(changedDefs, changedTrees)
-	}()
-
+	go updateRefTextRenameDoc(tree)
 	IncSync()
 	IncSync()
 	return
 	return
 }
 }

+ 29 - 3
kernel/model/transaction.go

@@ -100,6 +100,7 @@ func isWritingFiles() bool {
 }
 }
 
 
 func AutoFlushTx() {
 func AutoFlushTx() {
+	go autoFlushUpdateRefTextRenameDoc()
 	for {
 	for {
 		flushTx()
 		flushTx()
 		time.Sleep(time.Duration(txDelay) * time.Millisecond)
 		time.Sleep(time.Duration(txDelay) * time.Millisecond)
@@ -1060,9 +1061,6 @@ func (tx *Transaction) writeTree(tree *parse.Tree) (err error) {
 
 
 func refreshDynamicRefText(updatedDefNodes map[string]*ast.Node, updatedTrees map[string]*parse.Tree) {
 func refreshDynamicRefText(updatedDefNodes map[string]*ast.Node, updatedTrees map[string]*parse.Tree) {
 	// 这个实现依赖了数据库缓存,导致外部调用时可能需要阻塞等待数据库写入后才能获取到 refs
 	// 这个实现依赖了数据库缓存,导致外部调用时可能需要阻塞等待数据库写入后才能获取到 refs
-	// 比如通过块引创建文档后立即重命名文档,这时引用关系还没有入库,所以重命名查询不到引用关系,最终导致动态锚文本设置失败
-	// 引用文档时锚文本没有跟随文档重命名 https://github.com/siyuan-note/siyuan/issues/4193
-	// 解决方案是将重命名通过协程异步调用,详见 RenameDoc 函数
 
 
 	treeRefNodeIDs := map[string]*hashset.Set{}
 	treeRefNodeIDs := map[string]*hashset.Set{}
 	for _, updateNode := range updatedDefNodes {
 	for _, updateNode := range updatedDefNodes {
@@ -1126,6 +1124,34 @@ func refreshDynamicRefText(updatedDefNodes map[string]*ast.Node, updatedTrees ma
 	}
 	}
 }
 }
 
 
+var updateRefTextRenameDocs = map[string]*parse.Tree{}
+var updateRefTextRenameDocLock = sync.Mutex{}
+
+func updateRefTextRenameDoc(renamedTree *parse.Tree) {
+	updateRefTextRenameDocLock.Lock()
+	updateRefTextRenameDocs[renamedTree.ID] = renamedTree
+	updateRefTextRenameDocLock.Unlock()
+}
+
+func autoFlushUpdateRefTextRenameDoc() {
+	for {
+		sql.WaitForWritingDatabase()
+		flushUpdateRefTextRenameDoc()
+	}
+}
+
+func flushUpdateRefTextRenameDoc() {
+	updateRefTextRenameDocLock.Lock()
+	defer updateRefTextRenameDocLock.Unlock()
+
+	for _, tree := range updateRefTextRenameDocs {
+		changedDefs := map[string]*ast.Node{tree.ID: tree.Root}
+		changedTrees := map[string]*parse.Tree{tree.ID: tree}
+		refreshDynamicRefText(changedDefs, changedTrees)
+	}
+	updateRefTextRenameDocs = map[string]*parse.Tree{}
+}
+
 func updateRefText(refNode *ast.Node, changedDefNodes map[string]*ast.Node) (changed bool) {
 func updateRefText(refNode *ast.Node, changedDefNodes map[string]*ast.Node) (changed bool) {
 	ast.Walk(refNode, func(n *ast.Node, entering bool) ast.WalkStatus {
 	ast.Walk(refNode, func(n *ast.Node, entering bool) ast.WalkStatus {
 		if !entering {
 		if !entering {