fix: 重启后用户分组丢失 - #10
Merged
Merged
Conversation
UserGroup was added to AppState, and saveStateLocked wrote it correctly, but neither loadState nor loadPostgresState ever read it back. Every restart therefore came up with an empty group list, so a deploy silently discarded every group an operator had created and forced them to be recreated by hand. The first save after a restart then overwrote the persisted copy, making the loss permanent. Also hardening around the same area: - normalizeStateCollections now materialises the default registration group, so the console never shows an unexplained empty list - a user whose groupId no longer resolves is reset to ungrouped rather than left dangling: a dangling id silently confines the user to unrestricted channels, which is harder to notice than a missing group Tests, both of which fail without the load fix: - TestUserGroupsSurviveRestart round-trips groups, user assignment and channel scoping through a real file-backed restart - TestEveryAppStateCollectionRoundTrips asserts a seeded entry from every collection survives a load. It checks for the specific entry rather than a non-empty collection, because normalization creates entries of its own and would otherwise mask a collection that was never loaded. Co-Authored-By: Claude Code <noreply@anthropic.com>
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.
问题
UserGroup加进了AppState,saveStateLocked也正确写入了,但loadState(文件)和loadPostgresState(Postgres)都没有读回来。后果:每次重启/部署分组列表都归零,管理员手动建的分组全部消失,只能重建。更糟的是重启后的第一次保存会把空列表写回覆盖持久化的数据,所以丢失是不可逆的。
修复
stored.Groups恢复normalizeStateCollections现在会确保默认注册分组存在,控制台不会再出现无解释的空列表groupId会被重置为未分组,而不是留着悬空 —— 悬空引用会让用户静默地只能用未限制分组的渠道,比分组缺失更难发现验证
新增两个测试,都已在移除修复后确认会失败:
TestUserGroupsSurviveRestart—— 走真实的文件持久化重启,验证分组、用户归属、渠道范围限定三者都保留TestEveryAppStateCollectionRoundTrips—— 断言每一条集合里的样本记录都能在加载后存活第二个测试刻意检查「具体记录存在」而不是「集合非空」:归一化会自己补出默认分组,只查非空会掩盖从未被加载的集合。这一点是我第一版测试写错后发现的 —— 当时的写法在这个 bug 下依然通过。
实测(文件持久化,真实重启):
go test ./...全绿。关于已有数据
已经被清掉的分组无法从当前数据库恢复(覆盖已经发生)。需要重建一次,之后就会正常保留了。如果你有导出的备份 JSON,可以用「设置 → 恢复」找回来。