periodically clean sessions

This commit is contained in:
sentriz
2020-05-19 19:19:47 +01:00
parent 79ad61eeb1
commit fd96bfe6a8
5 changed files with 59 additions and 31 deletions

View File

@@ -70,6 +70,7 @@ func main() {
})
var g run.Group
g.Add(server.StartHTTP(*listenAddr))
g.Add(server.StartSessionClean(10 * time.Minute))
if *scanInterval > 0 {
tickerDur := time.Duration(*scanInterval) * time.Minute
g.Add(server.StartScanTicker(tickerDur))

View File

@@ -15,7 +15,6 @@ import (
"github.com/Masterminds/sprig"
"github.com/dustin/go-humanize"
"github.com/gorilla/securecookie"
"github.com/gorilla/sessions"
"github.com/oxtoacart/bpool"
"github.com/wader/gormstore"
@@ -85,12 +84,7 @@ type Controller struct {
sessDB *gormstore.Store
}
func New(b *ctrlbase.Controller) *Controller {
sessionKey := []byte(b.DB.GetSetting("session_key"))
if len(sessionKey) == 0 {
sessionKey = securecookie.GenerateRandomKey(32)
b.DB.SetSetting("session_key", string(sessionKey))
}
func New(b *ctrlbase.Controller, sessDB *gormstore.Store) *Controller {
tmplBase := template.
New("layout").
Funcs(sprig.FuncMap()).
@@ -100,9 +94,6 @@ func New(b *ctrlbase.Controller) *Controller {
})
tmplBase = extendFromPaths(tmplBase, prefixPartials)
tmplBase = extendFromPaths(tmplBase, prefixLayouts)
sessDB := gormstore.New(b.DB.DB, sessionKey)
sessDB.SessionOpts.HttpOnly = true
sessDB.SessionOpts.SameSite = http.SameSiteLaxMode
return &Controller{
Controller: b,
buffPool: bpool.NewBufferPool(64),

View File

@@ -6,6 +6,7 @@ import (
"net/url"
"os"
"github.com/gorilla/securecookie"
"github.com/jinzhu/gorm"
"gopkg.in/gormigrate.v1"
@@ -101,6 +102,15 @@ func (db *DB) SetSetting(key, value string) {
FirstOrCreate(&Setting{})
}
func (db *DB) GetOrCreateKey(key string) string {
value := db.GetSetting(key)
if value == "" {
value = string(securecookie.GenerateRandomKey(32))
db.SetSetting(key, value)
}
return value
}
func (db *DB) GetUserFromName(name string) *User {
user := &User{}
err := db.
@@ -113,27 +123,21 @@ func (db *DB) GetUserFromName(name string) *User {
return user
}
func (db *DB) WithTx(cb func(*gorm.DB)) {
tx := db.Begin()
defer tx.Commit()
cb(tx)
}
type ChunkFunc func(*gorm.DB, []int64) error
func (db *DB) WithTxChunked(data []int64, cb ChunkFunc) error {
func (db *DB) TransactionChunked(data []int64, cb ChunkFunc) error {
// https://sqlite.org/limits.html
const size = 999
tx := db.Begin()
defer tx.Commit()
for i := 0; i < len(data); i += size {
end := i + size
if end > len(data) {
end = len(data)
return db.Transaction(func(tx *gorm.DB) error {
for i := 0; i < len(data); i += size {
end := i + size
if end > len(data) {
end = len(data)
}
if err := cb(tx, data[i:end]); err != nil {
return err
}
}
if err := cb(tx, data[i:end]); err != nil {
return err
}
}
return nil
return nil
})
}

View File

@@ -104,7 +104,7 @@ func (s *Scanner) cleanTracks() (int, error) {
missing = append(missing, int64(prev))
}
}
err = s.db.WithTxChunked(missing, func(tx *gorm.DB, chunk []int64) error {
err = s.db.TransactionChunked(missing, func(tx *gorm.DB, chunk []int64) error {
return tx.Where(chunk).Delete(&db.Track{}).Error
})
return len(missing), err
@@ -125,7 +125,7 @@ func (s *Scanner) cleanFolders() (int, error) {
missing = append(missing, int64(prev))
}
}
err = s.db.WithTxChunked(missing, func(tx *gorm.DB, chunk []int64) error {
err = s.db.TransactionChunked(missing, func(tx *gorm.DB, chunk []int64) error {
return tx.Where(chunk).Delete(&db.Album{}).Error
})
return len(missing), err

View File

@@ -9,6 +9,7 @@ import (
"time"
"github.com/gorilla/mux"
"github.com/wader/gormstore"
"go.senan.xyz/gonic/server/assets"
"go.senan.xyz/gonic/server/ctrladmin"
@@ -30,6 +31,7 @@ type Server struct {
scanner *scanner.Scanner
jukebox *jukebox.Jukebox
router *mux.Router
sessDB *gormstore.Store
}
func New(opts Options) *Server {
@@ -51,7 +53,13 @@ func New(opts Options) *Server {
r := mux.NewRouter()
r.Use(base.WithLogging)
r.Use(base.WithCORS)
ctrlAdmin := ctrladmin.New(base)
//
sessKey := opts.DB.GetOrCreateKey("session_key")
sessDB := gormstore.New(opts.DB.DB, []byte(sessKey))
sessDB.SessionOpts.HttpOnly = true
sessDB.SessionOpts.SameSite = http.SameSiteLaxMode
//
ctrlAdmin := ctrladmin.New(base, sessDB)
ctrlSubsonic := &ctrlsubsonic.Controller{
Controller: base,
CachePath: opts.CachePath,
@@ -65,6 +73,7 @@ func New(opts Options) *Server {
scanner: scanner,
jukebox: jukebox,
router: r,
sessDB: sessDB,
}
}
@@ -234,3 +243,26 @@ func (s *Server) StartJukebox() (FuncExecute, FuncInterrupt) {
s.jukebox.Quit()
}
}
func (s *Server) StartSessionClean(dur time.Duration) (FuncExecute, FuncInterrupt) {
ticker := time.NewTicker(dur)
done := make(chan struct{})
waitFor := func() error {
for {
select {
case <-done:
return nil
case <-ticker.C:
s.sessDB.Cleanup()
}
}
}
return func() error {
log.Printf("starting job 'session clean'\n")
return waitFor()
}, func(_ error) {
// stop job
ticker.Stop()
done <- struct{}{}
}
}