Foundation: config, schema/migrations, auth, stable IDs, metadata probing
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
)
|
||||
|
||||
// GetSetting reads a key from the settings table, returning def if unset.
|
||||
func GetSetting(db *sql.DB, key, def string) string {
|
||||
var v string
|
||||
err := db.QueryRow(`SELECT value FROM settings WHERE key = ?`, key).Scan(&v)
|
||||
if err != nil {
|
||||
return def
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func SetSetting(db *sql.DB, key, value string) error {
|
||||
_, err := db.Exec(`INSERT INTO settings (key, value, updated_at) VALUES (?, ?, strftime('%Y-%m-%dT%H:%M:%fZ','now'))
|
||||
ON CONFLICT (key) DO UPDATE SET value=excluded.value, updated_at=excluded.updated_at`, key, value)
|
||||
return err
|
||||
}
|
||||
|
||||
// --- Scan state ---
|
||||
|
||||
type ScanState struct {
|
||||
ID string
|
||||
MusicFolderID string
|
||||
Status string
|
||||
StartedAt sql.NullString
|
||||
FinishedAt sql.NullString
|
||||
FilesSeen int
|
||||
FilesTotalEstimate int
|
||||
FilesAdded int
|
||||
FilesUpdated int
|
||||
FilesRemoved int
|
||||
ErrorMessage string
|
||||
LastFullScanAt sql.NullString
|
||||
}
|
||||
|
||||
const scanStateSelect = `SELECT id, music_folder_id, status, started_at, finished_at, files_seen, files_total_estimate, files_added, files_updated, files_removed, error_message, last_full_scan_at FROM scan_state`
|
||||
|
||||
func GetScanState(db *sql.DB, folderID string) (*ScanState, error) {
|
||||
var s ScanState
|
||||
err := db.QueryRow(scanStateSelect+` WHERE music_folder_id = ?`, folderID).Scan(
|
||||
&s.ID, &s.MusicFolderID, &s.Status, &s.StartedAt, &s.FinishedAt, &s.FilesSeen, &s.FilesTotalEstimate,
|
||||
&s.FilesAdded, &s.FilesUpdated, &s.FilesRemoved, &s.ErrorMessage, &s.LastFullScanAt)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &s, nil
|
||||
}
|
||||
|
||||
func ListScanStates(db *sql.DB) ([]*ScanState, error) {
|
||||
rows, err := db.Query(scanStateSelect)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var out []*ScanState
|
||||
for rows.Next() {
|
||||
var s ScanState
|
||||
if err := rows.Scan(&s.ID, &s.MusicFolderID, &s.Status, &s.StartedAt, &s.FinishedAt, &s.FilesSeen, &s.FilesTotalEstimate,
|
||||
&s.FilesAdded, &s.FilesUpdated, &s.FilesRemoved, &s.ErrorMessage, &s.LastFullScanAt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, &s)
|
||||
}
|
||||
return out, rows.Err()
|
||||
}
|
||||
|
||||
func StartScan(db *sql.DB, folderID string) error {
|
||||
_, err := db.Exec(`UPDATE scan_state SET status='scanning', started_at=strftime('%Y-%m-%dT%H:%M:%fZ','now'), finished_at=NULL,
|
||||
files_seen=0, files_added=0, files_updated=0, files_removed=0, error_message='' WHERE music_folder_id=?`, folderID)
|
||||
return err
|
||||
}
|
||||
|
||||
func UpdateScanProgress(db *sql.DB, folderID string, filesSeen, filesAdded, filesUpdated int) error {
|
||||
_, err := db.Exec(`UPDATE scan_state SET files_seen=?, files_added=?, files_updated=? WHERE music_folder_id=?`,
|
||||
filesSeen, filesAdded, filesUpdated, folderID)
|
||||
return err
|
||||
}
|
||||
|
||||
func FinishScan(db *sql.DB, folderID string, filesRemoved int, errMsg string) error {
|
||||
status := "idle"
|
||||
if errMsg != "" {
|
||||
status = "error"
|
||||
}
|
||||
_, err := db.Exec(`UPDATE scan_state SET status=?, finished_at=strftime('%Y-%m-%dT%H:%M:%fZ','now'), files_removed=?, error_message=?,
|
||||
last_full_scan_at=strftime('%Y-%m-%dT%H:%M:%fZ','now') WHERE music_folder_id=?`, status, filesRemoved, errMsg, folderID)
|
||||
return err
|
||||
}
|
||||
Reference in New Issue
Block a user