...
1 package store
2
3 import (
4 "context"
5 "fmt"
6 "time"
7
8 "github.com/gorilla/sessions"
9 )
10
11 var defaultInterval = time.Minute * 5
12
13
14
15 func (db *PGStore) Cleanup(interval time.Duration) (chan<- struct{}, <-chan struct{}) {
16 if interval <= 0 {
17 interval = defaultInterval
18 }
19
20 quit, done := make(chan struct{}), make(chan struct{})
21 go db.cleanup(interval, quit, done)
22 return quit, done
23 }
24
25
26 func (db *PGStore) StopCleanup(quit chan<- struct{}, done <-chan struct{}) {
27 quit <- struct{}{}
28 <-done
29 }
30
31
32 func (db *PGStore) cleanup(interval time.Duration, quit <-chan struct{}, done chan<- struct{}) {
33 ticker := time.NewTicker(interval)
34
35 defer func() {
36 ticker.Stop()
37 }()
38
39 for {
40 select {
41 case <-quit:
42
43 done <- struct{}{}
44 return
45 case <-ticker.C:
46
47 var count int
48 rows, err := db.DbPool.QueryContext(context.Background(), "SELECT key FROM http_sessions WHERE expires_on < now()")
49 if err != nil {
50 db.log.Error(err, "pgstore: unable to get expired sessions")
51 done <- struct{}{}
52 return
53 }
54 for rows.Next() {
55 var id string
56 if err := rows.Scan(&id); err != nil {
57 db.log.Error(err, "an error occurred scanning expired session")
58 continue
59 }
60 sess := sessions.NewSession(db, SessionIdentifier)
61 sess.ID = id
62 if err := db.load(sess); err != nil {
63 db.log.Error(err, "failed to load session", "operation_name", CleanupExpiredSessionOp)
64 continue
65 }
66 db.log.Info("deleting expired session", enrichLogWithSession(CleanupExpiredSessionOp, sess)...)
67 count++
68 }
69 err = db.deleteExpired()
70 if err != nil {
71 db.log.Error(err, "pgstore: unable to delete expired sessions")
72 } else {
73 db.log.Info(fmt.Sprintf("deleted %v expired sessions", count), "operation_name", CleanupExpiredSessionOp)
74 }
75 }
76 }
77 }
78
79
80 func (db *PGStore) deleteExpired() error {
81 _, err := db.DbPool.Exec("DELETE FROM http_sessions WHERE expires_on < now()")
82 return err
83 }
84
View as plain text