fix(server): 强退设备立即离线 — online 须含活跃会话 + 撤销会话不刷 last_seen

trick bug:强退后被踢设备的下一次会话轮询会先刷 last_seen 再发现 active=false,那一刷
把它顶成「在线」直到 90s 窗口过期。修:① online = last_seen 新 且 有未撤销会话
(ActiveSessionDeviceIDs);被强退设备无活跃会话 → 立即离线。② SessionActive 仅在 active
时才 TouchLastSeen,撤销会话的轮询不再刷新。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
wangjia
2026-06-30 08:51:10 +08:00
parent 2fbaba7608
commit f0af3bcc94
3 changed files with 43 additions and 2 deletions
@@ -87,12 +87,18 @@ func TestSQLite_SessionHasActiveSession(t *testing.T) {
if ok, err := ss.HasActiveSession(ctx, uid, did); err != nil || !ok {
t.Fatalf("建会话后应活跃: ok=%v err=%v", ok, err)
}
if set, err := ss.ActiveSessionDeviceIDs(ctx, uid); err != nil || !set[did] {
t.Fatalf("活跃设备集应含 %d: set=%v err=%v", did, set, err)
}
if _, err := ss.RevokeByDevice(ctx, uid, did); err != nil {
t.Fatalf("revoke: %v", err)
}
if ok, err := ss.HasActiveSession(ctx, uid, did); err != nil || ok {
t.Fatalf("强制退出后应非活跃: ok=%v err=%v", ok, err)
}
if set, err := ss.ActiveSessionDeviceIDs(ctx, uid); err != nil || set[did] {
t.Fatalf("强退后活跃设备集不应含 %d(→立即离线): set=%v err=%v", did, set, err)
}
}
func TestSQLite_NodeAccumulateUsage(t *testing.T) {