diff --git a/pkg/database/database.go b/pkg/database/database.go index dcdcdef..ec097d8 100644 --- a/pkg/database/database.go +++ b/pkg/database/database.go @@ -106,18 +106,6 @@ func IsInitialized() bool { return db != nil } -// GetDB returns the database connection (for advanced queries). -// -// Deprecated: This function is unsafe for concurrent use because the returned -// pointer may become invalid if Close() is called by another goroutine after -// GetDB() returns. Use the dedicated query functions (InsertHashratePoint, -// GetHashrateHistory, etc.) instead, which handle locking internally. -func GetDB() *sql.DB { - dbMu.RLock() - defer dbMu.RUnlock() - return db -} - // createTables creates all required database tables func createTables() error { schema := ` diff --git a/pkg/database/hashrate.go b/pkg/database/hashrate.go index 498a27f..c924674 100644 --- a/pkg/database/hashrate.go +++ b/pkg/database/hashrate.go @@ -2,6 +2,7 @@ package database import ( "context" + "database/sql" "fmt" "log" "time" @@ -163,7 +164,10 @@ func GetLatestHashrate(minerName string) (*HashratePoint, error) { `, minerName).Scan(&point.Timestamp, &point.Hashrate) if err != nil { - return nil, nil // Not found is not an error + if err == sql.ErrNoRows { + return nil, nil // No data found is not an error + } + return nil, fmt.Errorf("failed to get latest hashrate: %w", err) } return &point, nil diff --git a/pkg/mining/ttminer_start.go b/pkg/mining/ttminer_start.go index 20ba909..9f1a850 100644 --- a/pkg/mining/ttminer_start.go +++ b/pkg/mining/ttminer_start.go @@ -13,6 +13,17 @@ import ( // Start launches the TT-Miner with the given configuration. func (m *TTMiner) Start(config *Config) error { + // Check installation BEFORE acquiring lock (CheckInstallation takes its own locks) + m.mu.RLock() + needsInstallCheck := m.MinerBinary == "" + m.mu.RUnlock() + + if needsInstallCheck { + if _, err := m.CheckInstallation(); err != nil { + return err // Propagate the detailed error from CheckInstallation + } + } + m.mu.Lock() defer m.mu.Unlock() @@ -20,13 +31,6 @@ func (m *TTMiner) Start(config *Config) error { return errors.New("miner is already running") } - // If the binary path isn't set, run CheckInstallation to find it. - if m.MinerBinary == "" { - if _, err := m.CheckInstallation(); err != nil { - return err // Propagate the detailed error from CheckInstallation - } - } - if m.API != nil && config.HTTPPort != 0 { m.API.ListenPort = config.HTTPPort } else if m.API != nil && m.API.ListenPort == 0 { diff --git a/pkg/mining/xmrig_start.go b/pkg/mining/xmrig_start.go index 165cc10..22e48e4 100644 --- a/pkg/mining/xmrig_start.go +++ b/pkg/mining/xmrig_start.go @@ -15,6 +15,17 @@ import ( // Start launches the XMRig miner with the specified configuration. func (m *XMRigMiner) Start(config *Config) error { + // Check installation BEFORE acquiring lock (CheckInstallation takes its own locks) + m.mu.RLock() + needsInstallCheck := m.MinerBinary == "" + m.mu.RUnlock() + + if needsInstallCheck { + if _, err := m.CheckInstallation(); err != nil { + return err // Propagate the detailed error from CheckInstallation + } + } + m.mu.Lock() defer m.mu.Unlock() @@ -22,13 +33,6 @@ func (m *XMRigMiner) Start(config *Config) error { return errors.New("miner is already running") } - // If the binary path isn't set, run CheckInstallation to find it. - if m.MinerBinary == "" { - if _, err := m.CheckInstallation(); err != nil { - return err // Propagate the detailed error from CheckInstallation - } - } - if m.API != nil && config.HTTPPort != 0 { m.API.ListenPort = config.HTTPPort } else if m.API != nil && m.API.ListenPort == 0 { diff --git a/pkg/node/peer.go b/pkg/node/peer.go index 08ed927..e2616e8 100644 --- a/pkg/node/peer.go +++ b/pkg/node/peer.go @@ -91,6 +91,8 @@ func NewPeerRegistryWithPath(peersPath string) (*PeerRegistry, error) { } // AddPeer adds a new peer to the registry. +// Note: Persistence is debounced (writes batched every 5s). Call Close() to ensure +// all changes are flushed to disk before shutdown. func (r *PeerRegistry) AddPeer(peer *Peer) error { r.mu.Lock() @@ -120,6 +122,7 @@ func (r *PeerRegistry) AddPeer(peer *Peer) error { } // UpdatePeer updates an existing peer's information. +// Note: Persistence is debounced. Call Close() to flush before shutdown. func (r *PeerRegistry) UpdatePeer(peer *Peer) error { r.mu.Lock() @@ -136,6 +139,7 @@ func (r *PeerRegistry) UpdatePeer(peer *Peer) error { } // RemovePeer removes a peer from the registry. +// Note: Persistence is debounced. Call Close() to flush before shutdown. func (r *PeerRegistry) RemovePeer(id string) error { r.mu.Lock() @@ -180,6 +184,7 @@ func (r *PeerRegistry) ListPeers() []*Peer { } // UpdateMetrics updates a peer's performance metrics. +// Note: Persistence is debounced. Call Close() to flush before shutdown. func (r *PeerRegistry) UpdateMetrics(id string, pingMS, geoKM float64, hops int) error { r.mu.Lock() @@ -201,6 +206,7 @@ func (r *PeerRegistry) UpdateMetrics(id string, pingMS, geoKM float64, hops int) } // UpdateScore updates a peer's reliability score. +// Note: Persistence is debounced. Call Close() to flush before shutdown. func (r *PeerRegistry) UpdateScore(id string, score float64) error { r.mu.Lock()