Repository navigation
Conversation
入站流程先读 route 的活跃会话指针,没有时再新建会话并改写指针,三步之间 没有互斥。渠道首次接入带积压、或一次转发多条消息时,同一个新聊天的消息会 各自建一个会话,指针只留下最后写入的那个,其余会话里的消息之后不再进入 上下文,每个会话还各自调用模型。 新增 CreateIfAbsent:同一进程内按 route 合并并发的创建;跨进程时指针只从 读取时的值改写,没抢到的一方删掉自己建的会话,改用已选中的会话。入站在 没有活跃会话时改用它;/new 仍然无条件新建。
两个 fake 合成一个,测试并入 thread_test.go;并发用例改用 channel 控制先后, 不再依赖计时;「指针指向已删除会话」并入跨进程用例,去掉逻辑直接的 「已有会话直接返回」用例。
条件写入失败后会重新读取 route:选中的会话已不存在时,改为从新的值再写一次, 最多 3 次,不再沿用指针没有指向的会话;条件写入报错时返回错误并删掉刚建的会话。 只有选中的会话不存在时才新建,其他读取错误直接返回,避免把仍在用的会话换掉。 共享的创建改用 DoChan:调用方 context 结束时立即返回,共享的那次最多 30 秒。 删除没有调用方的 EnsureActive 和 EnsureActiveSession。补充 inbound 走 CreateSessionIfAbsent 的断言,以及加入别人建的 discuss 会话时拒绝 skill 的用例。
共享的创建会执行 SessionStart hook,工作区冷启动时可能超过 30 秒, 超时后条件写入和删除都会失败。改为不设总时长上限,等待的调用方仍按 自己的 ctx 返回。 条件写入报错时可能已经提交。报错后重新读取 route:已指向新建的会话 就返回它;读取失败时保留会话,只返回错误。
CompareAndSetRouteActiveSession 沿用 SetRouteActiveSession 的加锁写法。 锁顺序测试的 helper 改为传入切换函数,新增删除 bot 与条件写入并发的用例; 去掉条件写入中目标会话的 FOR KEY SHARE 后该用例报死锁。
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Author
Type
Summary
一个新聊天同时收到多条消息时,会被拆成多个会话。入站流程先读 route 的活跃会话指针,没有时再新建会话并改写指针,三步之间没有互斥,中间还隔着 ACL 和命令检查。渠道首次接入带积压、bot 刚进一个活跃的群、一次转发多条消息时,这些消息会各自建一个会话,指针只留下最后写入的那个。其余会话里的消息之后不再进入上下文;discuss 模式下每个会话还各自起一个 worker、各自判断是否发言。
新增
ThreadCoordinator.CreateIfAbsent:有可用的活跃会话就直接返回,没有才新建。同一进程内按 route 用 singleflight 合并并发的创建;跨进程时用新增的CompareAndSetRouteActiveSession只从读取时的值改写指针,条件写入失败的一方删除自己创建的会话,改用已选中的会话。条件写入失败后重新读取 route,最多 3 轮:新选中的会话存在就用它,已不存在就再写一次。读取已选中的会话出错时不替换,直接返回错误。条件写入报错时可能已经提交,因此先重新读取 route,已指向新会话就返回它,读取失败则保留新会话。调用方放弃等待时立即返回,创建在后台继续;创建会执行 SessionStart hook,所以不设总时长上限。入站在没有活跃会话时改用它,拿到别人建的会话时重新检查 skill 支持。/new仍然无条件新建;原来的EnsureActive不再有调用方,已删除。修复不会合并已经被拆开的旧会话。跨进程竞争中被删除的会话在创建时已经发布了
session_created、执行过 SessionStart hook;删除不发布事件,Web 侧边栏刷新前会多显示一个会话。Related Issues
Validation
internal/channel/route新增 6 个用例:20 个调用方同时进来只建 1 个;跨进程条件写入失败时改用对方的会话并删除自己创建的;对方选中的会话随即被删时重试;已选中的会话读取出错时不替换;条件写入已提交但返回错误时返回并保留新会话;调用方放弃等待时立即返回。依次去掉 singleflight、忽略条件写入结果、只尝试 1 次、把读取错误当作会话不存在、条件写入报错后不重新读取、忽略调用方的 ctx,对应用例失败。用例在-race下连续 20 次通过。internal/channel/inbound新增用例:私聊里的/alpha拿到别人建的 discuss 会话时,回复不支持且不启动 turn;去掉重新检查后用例失败。TestPostgresRouteCompareAndSetMovesOnlyFromExpectedSession,覆盖期望值匹配、不匹配、空指针、空指针已被他人写入四种情况;route 锁顺序测试新增删除 bot 与条件写入并发的用例,去掉条件写入里目标会话的FOR KEY SHARE后该用例报死锁。均在临时库上通过。internal/chat/message(含 route 锁顺序测试)、internal/arch、internal/channel/inbound、cmd/internal/channel、internal/handlers测试和 golangci-lint 通过。Screenshots / Recordings
改动没有可见界面,验证方式见 Validation。
Human QA