fix(server): 设备「在线」准确反映 app 运行中 — 会话轮询刷 last_seen + 窗口缩到 90s
原 online=last_seen 在 3min 内,而 last_seen 只在连接/用量上报时刷 → app 运行≠刷新, 显示成'最近连过'而非'正在运行';关 app 后还'在线'到窗口过期。修:SessionActive(每 15s 轮询)顺便 TouchLastSeen → 运行中的 app 持续刷新;onlineWindow 3min→90s,关 app ~90s 转离线。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -83,9 +83,11 @@ type Device struct {
|
||||
LastLogin *string `json:"last_login"` // most recent session created_at; null when none
|
||||
}
|
||||
|
||||
// onlineWindow: a device is "online" if its last_seen (touched by connect +
|
||||
// periodic usage reports) is within this window.
|
||||
const onlineWindow = 3 * time.Minute
|
||||
// onlineWindow: a device is "online" if its last_seen is within this window.
|
||||
// last_seen is bumped by connect、用量上报,以及 ~15s 的会话轮询(SessionActive)——
|
||||
// 后者让「在线」准确反映 app 正在运行。窗口取 90s(覆盖几次丢失的 15s 轮询),
|
||||
// app 一关 ~90s 内转离线。
|
||||
const onlineWindow = 90 * time.Second
|
||||
|
||||
func toAPIDevice(d DeviceRow) Device {
|
||||
out := Device{UUID: d.UUID, Name: d.Name, Platform: d.Platform}
|
||||
@@ -359,6 +361,8 @@ func (svc *Service) SessionActive(ctx context.Context, userID int64, deviceUUID
|
||||
if dev == nil || dev.UserID != userID {
|
||||
return true, nil // 未知 / 非本人设备:不据此登出
|
||||
}
|
||||
// 设备在轮询 = app 正在运行:刷 last_seen,让「在线」状态准确(不再只反映上次连接)。
|
||||
_ = svc.store.TouchLastSeen(ctx, dev.ID)
|
||||
active, err := svc.sessions.HasActiveSession(ctx, userID, dev.ID)
|
||||
if err != nil {
|
||||
return false, apierr.ErrInternal
|
||||
|
||||
@@ -153,6 +153,17 @@ func (s *Store) insertDeviceTx(ctx context.Context, tx *sql.Tx, uuid string, use
|
||||
}, nil
|
||||
}
|
||||
|
||||
// TouchLastSeen bumps a device's last_seen to now (non-tx, best-effort). Called by
|
||||
// the ~15s session poll so "online" tracks an actually-running app, not just the
|
||||
// last connect/usage report.
|
||||
func (s *Store) TouchLastSeen(ctx context.Context, deviceID int64) error {
|
||||
if _, err := s.db.ExecContext(ctx,
|
||||
`UPDATE devices SET last_seen=? WHERE id=?`, time.Now().UTC(), deviceID); err != nil {
|
||||
return fmt.Errorf("store.TouchLastSeen: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// touchLastSeenTx updates a device's last_seen to now inside tx, and refreshes
|
||||
// client_version when a non-empty one is supplied (latest reported wins).
|
||||
func (s *Store) touchLastSeenTx(ctx context.Context, tx *sql.Tx, deviceID int64, clientVersion string) error {
|
||||
|
||||
Reference in New Issue
Block a user