diff --git a/storage/sql/config.go b/storage/sql/config.go index bf56d017..4bff016b 100644 --- a/storage/sql/config.go +++ b/storage/sql/config.go @@ -5,6 +5,7 @@ import ( "fmt" "net/url" "strconv" + "time" "github.com/coreos/dex/storage" ) @@ -17,7 +18,11 @@ type SQLite3 struct { // Open creates a new storage implementation backed by SQLite3 func (s *SQLite3) Open() (storage.Storage, error) { - return s.open() + conn, err := s.open() + if err != nil { + return nil, err + } + return withGC(conn, time.Now), nil } func (s *SQLite3) open() (*conn, error) { @@ -67,7 +72,11 @@ type Postgres struct { // Open creates a new storage implementation backed by Postgres. func (p *Postgres) Open() (storage.Storage, error) { - return p.open() + conn, err := p.open() + if err != nil { + return nil, err + } + return withGC(conn, time.Now), nil } func (p *Postgres) open() (*conn, error) { diff --git a/storage/sql/gc.go b/storage/sql/gc.go index 11e70f95..1636c087 100644 --- a/storage/sql/gc.go +++ b/storage/sql/gc.go @@ -1,8 +1,12 @@ package sql import ( + "context" "fmt" + "log" "time" + + "github.com/coreos/dex/storage" ) type gc struct { @@ -10,10 +14,8 @@ type gc struct { conn *conn } -var tablesWithGC = []string{"auth_request", "auth_code"} - func (gc gc) run() error { - for _, table := range tablesWithGC { + for _, table := range []string{"auth_request", "auth_code"} { _, err := gc.conn.Exec(`delete from `+table+` where expiry < $1`, gc.now()) if err != nil { return fmt.Errorf("gc %s: %v", table, err) @@ -22,3 +24,30 @@ func (gc gc) run() error { } return nil } + +type withCancel struct { + storage.Storage + cancel context.CancelFunc +} + +func (w withCancel) Close() error { + w.cancel() + return w.Storage.Close() +} + +func withGC(conn *conn, now func() time.Time) storage.Storage { + ctx, cancel := context.WithCancel(context.Background()) + run := (gc{now, conn}).run + go func() { + for { + select { + case <-time.After(time.Second * 30): + if err := run(); err != nil { + log.Printf("gc failed: %v", err) + } + case <-ctx.Done(): + } + } + }() + return withCancel{conn, cancel} +}