ax(database): rename db/dbMu to globalDatabase/databaseMutex
Abbreviated names `db` and `dbMu` require a comment to understand their scope and purpose, violating AX Principle 1 (Predictable Names Over Short Names). Renamed to `globalDatabase` and `databaseMutex` throughout all source and test files. Co-Authored-By: Charon <charon@lethean.io>
This commit is contained in:
parent
71292ccdc8
commit
036819e4eb
3 changed files with 55 additions and 54 deletions
|
|
@ -12,10 +12,11 @@ import (
|
|||
_ "github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
||||
// DB is the global database instance
|
||||
// globalDatabase is the global database instance
|
||||
// db := globalDatabase // check before use; nil means not initialised
|
||||
var (
|
||||
db *sql.DB
|
||||
dbMu sync.RWMutex
|
||||
globalDatabase *sql.DB
|
||||
databaseMutex sync.RWMutex
|
||||
)
|
||||
|
||||
// Config holds database configuration options
|
||||
|
|
@ -48,8 +49,8 @@ func defaultDBPath() (string, error) {
|
|||
|
||||
// Initialize opens the database connection and creates tables
|
||||
func Initialize(cfg Config) error {
|
||||
dbMu.Lock()
|
||||
defer dbMu.Unlock()
|
||||
databaseMutex.Lock()
|
||||
defer databaseMutex.Unlock()
|
||||
|
||||
if !cfg.Enabled {
|
||||
return nil
|
||||
|
|
@ -65,21 +66,21 @@ func Initialize(cfg Config) error {
|
|||
}
|
||||
|
||||
var err error
|
||||
db, err = sql.Open("sqlite3", dbPath+"?_journal=WAL&_timeout=5000")
|
||||
globalDatabase, err = sql.Open("sqlite3", dbPath+"?_journal=WAL&_timeout=5000")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open database: %w", err)
|
||||
}
|
||||
|
||||
// Set connection pool settings
|
||||
db.SetMaxOpenConns(1) // SQLite only supports one writer
|
||||
db.SetMaxIdleConns(1)
|
||||
db.SetConnMaxLifetime(time.Hour)
|
||||
globalDatabase.SetMaxOpenConns(1) // SQLite only supports one writer
|
||||
globalDatabase.SetMaxIdleConns(1)
|
||||
globalDatabase.SetConnMaxLifetime(time.Hour)
|
||||
|
||||
// Create tables
|
||||
if err := createTables(); err != nil {
|
||||
// Nil out global before closing to prevent use of closed connection
|
||||
closingDB := db
|
||||
db = nil
|
||||
closingDB := globalDatabase
|
||||
globalDatabase = nil
|
||||
closingDB.Close()
|
||||
return fmt.Errorf("failed to create tables: %w", err)
|
||||
}
|
||||
|
|
@ -89,23 +90,23 @@ func Initialize(cfg Config) error {
|
|||
|
||||
// Close closes the database connection
|
||||
func Close() error {
|
||||
dbMu.Lock()
|
||||
defer dbMu.Unlock()
|
||||
databaseMutex.Lock()
|
||||
defer databaseMutex.Unlock()
|
||||
|
||||
if db == nil {
|
||||
if globalDatabase == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
err := db.Close()
|
||||
db = nil
|
||||
err := globalDatabase.Close()
|
||||
globalDatabase = nil
|
||||
return err
|
||||
}
|
||||
|
||||
// isInitialized returns true if the database is ready
|
||||
func isInitialized() bool {
|
||||
dbMu.RLock()
|
||||
defer dbMu.RUnlock()
|
||||
return db != nil
|
||||
databaseMutex.RLock()
|
||||
defer databaseMutex.RUnlock()
|
||||
return globalDatabase != nil
|
||||
}
|
||||
|
||||
// createTables creates all required database tables
|
||||
|
|
@ -147,22 +148,22 @@ func createTables() error {
|
|||
ON miner_sessions(miner_name, started_at DESC);
|
||||
`
|
||||
|
||||
_, err := db.Exec(schema)
|
||||
_, err := globalDatabase.Exec(schema)
|
||||
return err
|
||||
}
|
||||
|
||||
// Cleanup removes old data based on retention settings
|
||||
func Cleanup(retentionDays int) error {
|
||||
dbMu.RLock()
|
||||
defer dbMu.RUnlock()
|
||||
databaseMutex.RLock()
|
||||
defer databaseMutex.RUnlock()
|
||||
|
||||
if db == nil {
|
||||
if globalDatabase == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
cutoff := time.Now().AddDate(0, 0, -retentionDays)
|
||||
|
||||
_, err := db.Exec(`
|
||||
_, err := globalDatabase.Exec(`
|
||||
DELETE FROM hashrate_history
|
||||
WHERE timestamp < ?
|
||||
`, cutoff)
|
||||
|
|
@ -172,13 +173,13 @@ func Cleanup(retentionDays int) error {
|
|||
|
||||
// vacuumDB optimizes the database file size
|
||||
func vacuumDB() error {
|
||||
dbMu.RLock()
|
||||
defer dbMu.RUnlock()
|
||||
databaseMutex.RLock()
|
||||
defer databaseMutex.RUnlock()
|
||||
|
||||
if db == nil {
|
||||
if globalDatabase == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err := db.Exec("VACUUM")
|
||||
_, err := globalDatabase.Exec("VACUUM")
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,9 +32,9 @@ func TestInitialize(t *testing.T) {
|
|||
defer cleanup()
|
||||
|
||||
// Database should be initialized
|
||||
dbMu.RLock()
|
||||
initialized := db != nil
|
||||
dbMu.RUnlock()
|
||||
databaseMutex.RLock()
|
||||
initialized := globalDatabase != nil
|
||||
databaseMutex.RUnlock()
|
||||
|
||||
if !initialized {
|
||||
t.Error("Database should be initialized")
|
||||
|
|
@ -359,30 +359,30 @@ func TestSchemaCreation(t *testing.T) {
|
|||
defer cleanup()
|
||||
|
||||
// Verify tables exist by querying sqlite_master
|
||||
dbMu.RLock()
|
||||
defer dbMu.RUnlock()
|
||||
databaseMutex.RLock()
|
||||
defer databaseMutex.RUnlock()
|
||||
|
||||
// Check hashrate_history table
|
||||
var tableName string
|
||||
err := db.QueryRow("SELECT name FROM sqlite_master WHERE type='table' AND name='hashrate_history'").Scan(&tableName)
|
||||
err := globalDatabase.QueryRow("SELECT name FROM sqlite_master WHERE type='table' AND name='hashrate_history'").Scan(&tableName)
|
||||
if err != nil {
|
||||
t.Errorf("hashrate_history table should exist: %v", err)
|
||||
}
|
||||
|
||||
// Check miner_sessions table
|
||||
err = db.QueryRow("SELECT name FROM sqlite_master WHERE type='table' AND name='miner_sessions'").Scan(&tableName)
|
||||
err = globalDatabase.QueryRow("SELECT name FROM sqlite_master WHERE type='table' AND name='miner_sessions'").Scan(&tableName)
|
||||
if err != nil {
|
||||
t.Errorf("miner_sessions table should exist: %v", err)
|
||||
}
|
||||
|
||||
// Verify indexes exist
|
||||
var indexName string
|
||||
err = db.QueryRow("SELECT name FROM sqlite_master WHERE type='index' AND name='idx_hashrate_miner_time'").Scan(&indexName)
|
||||
err = globalDatabase.QueryRow("SELECT name FROM sqlite_master WHERE type='index' AND name='idx_hashrate_miner_time'").Scan(&indexName)
|
||||
if err != nil {
|
||||
t.Errorf("idx_hashrate_miner_time index should exist: %v", err)
|
||||
}
|
||||
|
||||
err = db.QueryRow("SELECT name FROM sqlite_master WHERE type='index' AND name='idx_sessions_miner'").Scan(&indexName)
|
||||
err = globalDatabase.QueryRow("SELECT name FROM sqlite_master WHERE type='index' AND name='idx_sessions_miner'").Scan(&indexName)
|
||||
if err != nil {
|
||||
t.Errorf("idx_sessions_miner index should exist: %v", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,10 +54,10 @@ const dbInsertTimeout = 5 * time.Second
|
|||
// InsertHashratePoint stores a hashrate measurement in the database.
|
||||
// If ctx is nil, a default timeout context will be used.
|
||||
func InsertHashratePoint(ctx context.Context, minerName, minerType string, point HashratePoint, resolution Resolution) error {
|
||||
dbMu.RLock()
|
||||
defer dbMu.RUnlock()
|
||||
databaseMutex.RLock()
|
||||
defer databaseMutex.RUnlock()
|
||||
|
||||
if db == nil {
|
||||
if globalDatabase == nil {
|
||||
return nil // DB not enabled, silently skip
|
||||
}
|
||||
|
||||
|
|
@ -68,7 +68,7 @@ func InsertHashratePoint(ctx context.Context, minerName, minerType string, point
|
|||
defer cancel()
|
||||
}
|
||||
|
||||
_, err := db.ExecContext(ctx, `
|
||||
_, err := globalDatabase.ExecContext(ctx, `
|
||||
INSERT INTO hashrate_history (miner_name, miner_type, timestamp, hashrate, resolution)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
`, minerName, minerType, point.Timestamp, point.Hashrate, string(resolution))
|
||||
|
|
@ -78,14 +78,14 @@ func InsertHashratePoint(ctx context.Context, minerName, minerType string, point
|
|||
|
||||
// GetHashrateHistory retrieves hashrate history for a miner within a time range
|
||||
func GetHashrateHistory(minerName string, resolution Resolution, since, until time.Time) ([]HashratePoint, error) {
|
||||
dbMu.RLock()
|
||||
defer dbMu.RUnlock()
|
||||
databaseMutex.RLock()
|
||||
defer databaseMutex.RUnlock()
|
||||
|
||||
if db == nil {
|
||||
if globalDatabase == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
rows, err := db.Query(`
|
||||
rows, err := globalDatabase.Query(`
|
||||
SELECT timestamp, hashrate
|
||||
FROM hashrate_history
|
||||
WHERE miner_name = ?
|
||||
|
|
@ -123,16 +123,16 @@ type HashrateStats struct {
|
|||
}
|
||||
|
||||
func GetHashrateStats(minerName string) (*HashrateStats, error) {
|
||||
dbMu.RLock()
|
||||
defer dbMu.RUnlock()
|
||||
databaseMutex.RLock()
|
||||
defer databaseMutex.RUnlock()
|
||||
|
||||
if db == nil {
|
||||
if globalDatabase == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// First check if there are any rows for this miner
|
||||
var count int
|
||||
err := db.QueryRow(`SELECT COUNT(*) FROM hashrate_history WHERE miner_name = ?`, minerName).Scan(&count)
|
||||
err := globalDatabase.QueryRow(`SELECT COUNT(*) FROM hashrate_history WHERE miner_name = ?`, minerName).Scan(&count)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -148,7 +148,7 @@ func GetHashrateStats(minerName string) (*HashrateStats, error) {
|
|||
// SQLite returns timestamps as strings and AVG as float64, so scan them appropriately
|
||||
var firstSeenStr, lastSeenStr string
|
||||
var avgRate float64
|
||||
err = db.QueryRow(`
|
||||
err = globalDatabase.QueryRow(`
|
||||
SELECT
|
||||
COUNT(*),
|
||||
COALESCE(AVG(hashrate), 0),
|
||||
|
|
@ -181,14 +181,14 @@ func GetHashrateStats(minerName string) (*HashrateStats, error) {
|
|||
|
||||
// GetAllMinerStats retrieves stats for all miners
|
||||
func GetAllMinerStats() ([]HashrateStats, error) {
|
||||
dbMu.RLock()
|
||||
defer dbMu.RUnlock()
|
||||
databaseMutex.RLock()
|
||||
defer databaseMutex.RUnlock()
|
||||
|
||||
if db == nil {
|
||||
if globalDatabase == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
rows, err := db.Query(`
|
||||
rows, err := globalDatabase.Query(`
|
||||
SELECT
|
||||
miner_name,
|
||||
COUNT(*),
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue