@@ -3,7 +3,6 @@ package dormancy
3
3
import (
4
4
"context"
5
5
"database/sql"
6
- "encoding/json"
7
6
"net/http"
8
7
"time"
9
8
@@ -14,6 +13,7 @@ import (
14
13
"github.com/coder/coder/v2/coderd/audit"
15
14
"github.com/coder/coder/v2/coderd/database"
16
15
"github.com/coder/coder/v2/coderd/database/dbtime"
16
+ "github.com/coder/quartz"
17
17
)
18
18
19
19
const (
@@ -25,71 +25,49 @@ const (
25
25
26
26
// CheckInactiveUsers function updates status of inactive users from active to dormant
27
27
// using default parameters.
28
- func CheckInactiveUsers (ctx context.Context , logger slog.Logger , db database.Store , auditor audit.Auditor ) func () {
29
- return CheckInactiveUsersWithOptions (ctx , logger , db , auditor , jobInterval , accountDormancyPeriod )
28
+ func CheckInactiveUsers (ctx context.Context , logger slog.Logger , clk quartz. Clock , db database.Store , auditor audit.Auditor ) func () {
29
+ return CheckInactiveUsersWithOptions (ctx , logger , clk , db , auditor , jobInterval , accountDormancyPeriod )
30
30
}
31
31
32
32
// CheckInactiveUsersWithOptions function updates status of inactive users from active to dormant
33
33
// using provided parameters.
34
- func CheckInactiveUsersWithOptions (ctx context.Context , logger slog.Logger , db database.Store , auditor audit.Auditor , checkInterval , dormancyPeriod time.Duration ) func () {
34
+ func CheckInactiveUsersWithOptions (ctx context.Context , logger slog.Logger , clk quartz. Clock , db database.Store , auditor audit.Auditor , checkInterval , dormancyPeriod time.Duration ) func () {
35
35
logger = logger .Named ("dormancy" )
36
36
37
37
ctx , cancelFunc := context .WithCancel (ctx )
38
- done := make (chan struct {})
39
- ticker := time .NewTicker (checkInterval )
40
- go func () {
41
- defer close (done )
42
- defer ticker .Stop ()
43
- for {
44
- select {
45
- case <- ctx .Done ():
46
- return
47
- case <- ticker .C :
48
- }
38
+ ticker := clk .TickerFunc (ctx , checkInterval , func () error {
39
+ startTime := time .Now ()
40
+ lastSeenAfter := dbtime .Now ().Add (- dormancyPeriod )
41
+ logger .Debug (ctx , "check inactive user accounts" , slog .F ("dormancy_period" , dormancyPeriod ), slog .F ("last_seen_after" , lastSeenAfter ))
49
42
50
- startTime := time .Now ()
51
- lastSeenAfter := dbtime .Now ().Add (- dormancyPeriod )
52
- logger .Debug (ctx , "check inactive user accounts" , slog .F ("dormancy_period" , dormancyPeriod ), slog .F ("last_seen_after" , lastSeenAfter ))
43
+ updatedUsers , err := db .UpdateInactiveUsersToDormant (ctx , database.UpdateInactiveUsersToDormantParams {
44
+ LastSeenAfter : lastSeenAfter ,
45
+ UpdatedAt : dbtime .Now (),
46
+ })
47
+ if err != nil && ! xerrors .Is (err , sql .ErrNoRows ) {
48
+ logger .Error (ctx , "can't mark inactive users as dormant" , slog .Error (err ))
49
+ return nil
50
+ }
53
51
54
- updatedUsers , err := db .UpdateInactiveUsersToDormant (ctx , database.UpdateInactiveUsersToDormantParams {
55
- LastSeenAfter : lastSeenAfter ,
56
- UpdatedAt : dbtime .Now (),
52
+ for _ , u := range updatedUsers {
53
+ logger .Info (ctx , "account has been marked as dormant" , slog .F ("email" , u .Email ), slog .F ("last_seen_at" , u .LastSeenAt ))
54
+ audit .BackgroundAudit (ctx , & audit.BackgroundAuditParams [database.User ]{
55
+ Audit : auditor ,
56
+ Log : logger ,
57
+ UserID : u .ID ,
58
+ Action : database .AuditActionWrite ,
59
+ Old : database.User {ID : u .ID , Username : u .Username , Status : database .UserStatusActive },
60
+ New : database.User {ID : u .ID , Username : u .Username , Status : database .UserStatusDormant },
61
+ Status : http .StatusOK ,
62
+ AdditionalFields : audit .BackgroundTaskFields (ctx , logger , audit .BackgroundSubsystemDormancy ),
57
63
})
58
- if err != nil && ! xerrors .Is (err , sql .ErrNoRows ) {
59
- logger .Error (ctx , "can't mark inactive users as dormant" , slog .Error (err ))
60
- continue
61
- }
62
-
63
- af := map [string ]string {
64
- "automatic_actor" : "coder" ,
65
- "automatic_subsystem" : "dormancy" ,
66
- }
67
-
68
- wriBytes , err := json .Marshal (af )
69
- if err != nil {
70
- logger .Error (ctx , "marshal additional fields" , slog .Error (err ))
71
- wriBytes = []byte ("{}" )
72
- }
73
-
74
- for _ , u := range updatedUsers {
75
- logger .Info (ctx , "account has been marked as dormant" , slog .F ("email" , u .Email ), slog .F ("last_seen_at" , u .LastSeenAt ))
76
- audit .BackgroundAudit (ctx , & audit.BackgroundAuditParams [database.User ]{
77
- Audit : auditor ,
78
- Log : logger ,
79
- UserID : u .ID ,
80
- Action : database .AuditActionWrite ,
81
- Old : database.User {ID : u .ID , Username : u .Username , Status : database .UserStatusActive },
82
- New : database.User {ID : u .ID , Username : u .Username , Status : database .UserStatusDormant },
83
- Status : http .StatusOK ,
84
- AdditionalFields : wriBytes ,
85
- })
86
- }
87
- logger .Debug (ctx , "checking user accounts is done" , slog .F ("num_dormant_accounts" , len (updatedUsers )), slog .F ("execution_time" , time .Since (startTime )))
88
64
}
89
- }()
65
+ logger .Debug (ctx , "checking user accounts is done" , slog .F ("num_dormant_accounts" , len (updatedUsers )), slog .F ("execution_time" , time .Since (startTime )))
66
+ return nil
67
+ })
90
68
91
69
return func () {
92
70
cancelFunc ()
93
- <- done
71
+ ticker . Wait ()
94
72
}
95
73
}
0 commit comments