[management] Enforce the peer activity throttle inside the update

The manager checked LastSeen on the peer it already held and then issued an
unconditional UPDATE, so concurrent requests for one peer could each pass the
check off the same stale read and write. The cutoff now travels to the store
and lands in the statement's WHERE, matching how MarkPeerConnectedIfNewerSession
fences its own write, and the local check stays as the query-free fast path.
This commit is contained in:
mlsmaycon
2026-08-09 10:39:13 +00:00
parent 25b1081933
commit 796b48e49c
6 changed files with 61 additions and 22 deletions
@@ -38,18 +38,23 @@ func (m *managerImpl) RecordUserLogin(ctx context.Context, accountID string, use
}
// RecordPeerSeen stamps LastSeen, the column a peer activates its owner
// through. The throttle reads the peer the caller already holds, so a peer seen
// inside the interval costs nothing to skip.
// through. The peer the caller already holds answers the throttle without a
// query, so a peer seen inside the interval costs nothing to skip; the same
// cutoff goes to the store, which enforces it inside the UPDATE so concurrent
// requests for one peer cannot each write off their own stale read.
func (m *managerImpl) RecordPeerSeen(ctx context.Context, accountID string, peer *peer.Peer) error {
if peer == nil || !countsTowardActivity(peer) {
return nil
}
if peer.Status != nil && time.Since(peer.Status.LastSeen) < peerSeenInterval {
staleBefore := time.Now().UTC().Add(-peerSeenInterval)
if peer.Status != nil && peer.Status.LastSeen.After(staleBefore) {
return nil
}
return m.store.RefreshPeerLastSeen(ctx, accountID, peer.ID)
_, err := m.store.RefreshPeerLastSeen(ctx, accountID, peer.ID, staleBefore)
return err
}
// countsTowardActivity reports whether the peer represents a device a person
@@ -29,8 +29,9 @@ type loginWrite struct {
}
type seenWrite struct {
accountID string
peerID string
accountID string
peerID string
staleBefore time.Time
}
func (s *recordingStore) SaveUserLastLogin(_ context.Context, accountID, userID string, lastLogin time.Time) error {
@@ -38,9 +39,9 @@ func (s *recordingStore) SaveUserLastLogin(_ context.Context, accountID, userID
return nil
}
func (s *recordingStore) RefreshPeerLastSeen(_ context.Context, accountID, peerID string) error {
s.seen = append(s.seen, seenWrite{accountID: accountID, peerID: peerID})
return nil
func (s *recordingStore) RefreshPeerLastSeen(_ context.Context, accountID, peerID string, staleBefore time.Time) (bool, error) {
s.seen = append(s.seen, seenWrite{accountID: accountID, peerID: peerID, staleBefore: staleBefore})
return true, nil
}
func TestRecordUserLogin(t *testing.T) {
@@ -140,6 +141,9 @@ func TestRecordPeerSeen(t *testing.T) {
require.Len(t, st.seen, 1, "exactly one activity write should have been recorded")
assert.Equal(t, "account1", st.seen[0].accountID, "activity must be recorded against the service account")
assert.Equal(t, tt.peer.ID, st.seen[0].peerID, "activity must be recorded against the calling peer")
assert.Equal(t, time.UTC, st.seen[0].staleBefore.Location(), "cutoffs are passed in UTC")
assert.WithinDuration(t, time.Now().UTC().Add(-peerSeenInterval), st.seen[0].staleBefore, time.Minute,
"the store must enforce the same interval the local check applies")
})
}
}