Skip to content

Commit 86f9bed

Browse files
authored
chore: fix TestCheckInactiveUsers flake (#19469)
THIS CODE WAS NOT WRITTEN BY A HUMAN. Use a fixed time interval to avoid timing flakes.
1 parent fe289e8 commit 86f9bed

File tree

2 files changed

+20
-11
lines changed

2 files changed

+20
-11
lines changed

enterprise/coderd/dormancy/dormantusersjob.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,13 @@ func CheckInactiveUsersWithOptions(ctx context.Context, logger slog.Logger, clk
3737
ctx, cancelFunc := context.WithCancel(ctx)
3838
tf := clk.TickerFunc(ctx, checkInterval, func() error {
3939
startTime := time.Now()
40-
lastSeenAfter := dbtime.Now().Add(-dormancyPeriod)
40+
now := dbtime.Time(clk.Now()).UTC()
41+
lastSeenAfter := now.Add(-dormancyPeriod)
4142
logger.Debug(ctx, "check inactive user accounts", slog.F("dormancy_period", dormancyPeriod), slog.F("last_seen_after", lastSeenAfter))
4243

4344
updatedUsers, err := db.UpdateInactiveUsersToDormant(ctx, database.UpdateInactiveUsersToDormantParams{
4445
LastSeenAfter: lastSeenAfter,
45-
UpdatedAt: dbtime.Now(),
46+
UpdatedAt: now,
4647
})
4748
if err != nil && !xerrors.Is(err, sql.ErrNoRows) {
4849
logger.Error(ctx, "can't mark inactive users as dormant", slog.Error(err))

enterprise/coderd/dormancy/dormantusersjob_test.go

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,28 @@ func TestCheckInactiveUsers(t *testing.T) {
3131
ctx, cancelFunc := context.WithCancel(context.Background())
3232
t.Cleanup(cancelFunc)
3333

34-
inactiveUser1 := setupUser(ctx, t, db, "dormant-user-1@coder.com", database.UserStatusActive, time.Now().Add(-dormancyPeriod).Add(-time.Minute))
35-
inactiveUser2 := setupUser(ctx, t, db, "dormant-user-2@coder.com", database.UserStatusActive, time.Now().Add(-dormancyPeriod).Add(-time.Hour))
36-
inactiveUser3 := setupUser(ctx, t, db, "dormant-user-3@coder.com", database.UserStatusActive, time.Now().Add(-dormancyPeriod).Add(-6*time.Hour))
34+
// Use a fixed base time to avoid timing races
35+
baseTime := time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC)
36+
dormancyThreshold := baseTime.Add(-dormancyPeriod)
3737

38-
activeUser1 := setupUser(ctx, t, db, "active-user-1@coder.com", database.UserStatusActive, time.Now().Add(-dormancyPeriod).Add(time.Minute))
39-
activeUser2 := setupUser(ctx, t, db, "active-user-2@coder.com", database.UserStatusActive, time.Now().Add(-dormancyPeriod).Add(time.Hour))
40-
activeUser3 := setupUser(ctx, t, db, "active-user-3@coder.com", database.UserStatusActive, time.Now().Add(-dormancyPeriod).Add(6*time.Hour))
38+
// Create inactive users (last seen BEFORE dormancy threshold)
39+
inactiveUser1 := setupUser(ctx, t, db, "dormant-user-1@coder.com", database.UserStatusActive, dormancyThreshold.Add(-time.Minute))
40+
inactiveUser2 := setupUser(ctx, t, db, "dormant-user-2@coder.com", database.UserStatusActive, dormancyThreshold.Add(-time.Hour))
41+
inactiveUser3 := setupUser(ctx, t, db, "dormant-user-3@coder.com", database.UserStatusActive, dormancyThreshold.Add(-6*time.Hour))
4142

42-
suspendedUser1 := setupUser(ctx, t, db, "suspended-user-1@coder.com", database.UserStatusSuspended, time.Now().Add(-dormancyPeriod).Add(-time.Minute))
43-
suspendedUser2 := setupUser(ctx, t, db, "suspended-user-2@coder.com", database.UserStatusSuspended, time.Now().Add(-dormancyPeriod).Add(-time.Hour))
44-
suspendedUser3 := setupUser(ctx, t, db, "suspended-user-3@coder.com", database.UserStatusSuspended, time.Now().Add(-dormancyPeriod).Add(-6*time.Hour))
43+
// Create active users (last seen AFTER dormancy threshold)
44+
activeUser1 := setupUser(ctx, t, db, "active-user-1@coder.com", database.UserStatusActive, baseTime.Add(-time.Minute))
45+
activeUser2 := setupUser(ctx, t, db, "active-user-2@coder.com", database.UserStatusActive, baseTime.Add(-time.Hour))
46+
activeUser3 := setupUser(ctx, t, db, "active-user-3@coder.com", database.UserStatusActive, baseTime.Add(-6*time.Hour))
47+
48+
suspendedUser1 := setupUser(ctx, t, db, "suspended-user-1@coder.com", database.UserStatusSuspended, dormancyThreshold.Add(-time.Minute))
49+
suspendedUser2 := setupUser(ctx, t, db, "suspended-user-2@coder.com", database.UserStatusSuspended, dormancyThreshold.Add(-time.Hour))
50+
suspendedUser3 := setupUser(ctx, t, db, "suspended-user-3@coder.com", database.UserStatusSuspended, dormancyThreshold.Add(-6*time.Hour))
4551

4652
mAudit := audit.NewMock()
4753
mClock := quartz.NewMock(t)
54+
// Set the mock clock to the base time to ensure consistent behavior
55+
mClock.Set(baseTime)
4856
// Run the periodic job
4957
closeFunc := dormancy.CheckInactiveUsersWithOptions(ctx, logger, mClock, db, mAudit, interval, dormancyPeriod)
5058
t.Cleanup(closeFunc)

0 commit comments

Comments
 (0)