// package session manages Yggdrasil session lifecycle. package session import ( "context" "log" "time" "github.com/jackc/pgx/v5/pgxpool" "gitea.mrixs.me/Mrixs/MrixsCraft-server/internal/database" ) // StartCleanupWorker launches a background goroutine that deletes expired // yggdrasil_sessions every interval. It stops when the context is cancelled. func StartCleanupWorker(db *database.DB, interval time.Duration) context.CancelFunc { ctx, cancel := context.WithCancel(context.Background()) go func() { log.Printf("Session cleanup worker started (interval: %v)", interval) ticker := time.NewTicker(interval) defer ticker.Stop() // Run once on start. cleanup(db) for { select { case <-ticker.C: cleanup(db) case <-ctx.Done(): log.Println("Session cleanup worker stopped") return } } }() return cancel } func cleanup(db *database.DB) { if db == nil { return } pool := db.Pool() if pool == nil { return } tag, err := pool.Exec(context.Background(), `DELETE FROM yggdrasil_sessions WHERE expires_at < NOW()`) if err != nil { log.Printf("Session cleanup error: %v", err) return } if tag.RowsAffected() > 0 { log.Printf("Session cleanup: removed %d expired sessions", tag.RowsAffected()) } } // CountActive returns the number of non-expired sessions. func CountActive(pool *pgxpool.Pool) (int, error) { var count int err := pool.QueryRow(context.Background(), `SELECT COUNT(*) FROM yggdrasil_sessions WHERE expires_at > NOW()`, ).Scan(&count) return count, err }