ax(mining): rename mu to mutex in BaseMiner and LogBuffer (AX Principle 1)
Some checks are pending
Security Scan / security (push) Waiting to run
Test / test (push) Waiting to run

Co-Authored-By: Charon <charon@lethean.io>
This commit is contained in:
Claude 2026-04-02 13:59:06 +01:00
parent 316049d3ae
commit 7a121b7d18
No known key found for this signature in database
GPG key ID: AF404715446AEB41
7 changed files with 59 additions and 59 deletions

View file

@ -27,7 +27,7 @@ import (
type LogBuffer struct {
lines []string
maxLines int
mu sync.RWMutex
mutex sync.RWMutex
}
// buffer := NewLogBuffer(500)
@ -44,8 +44,8 @@ const maxLineLength = 2000
// cmd.Stdout = lb // satisfies io.Writer; timestamps and ring-buffers each line
func (lb *LogBuffer) Write(p []byte) (n int, err error) {
lb.mu.Lock()
defer lb.mu.Unlock()
lb.mutex.Lock()
defer lb.mutex.Unlock()
// Split input into lines
text := string(p)
@ -76,8 +76,8 @@ func (lb *LogBuffer) Write(p []byte) (n int, err error) {
// lines := lb.GetLines()
// response.Logs = lines[max(0, len(lines)-100):]
func (lb *LogBuffer) GetLines() []string {
lb.mu.RLock()
defer lb.mu.RUnlock()
lb.mutex.RLock()
defer lb.mutex.RUnlock()
result := make([]string, len(lb.lines))
copy(result, lb.lines)
return result
@ -85,8 +85,8 @@ func (lb *LogBuffer) GetLines() []string {
// lb.Clear() // called on miner Stop() to release memory
func (lb *LogBuffer) Clear() {
lb.mu.Lock()
defer lb.mu.Unlock()
lb.mutex.Lock()
defer lb.mutex.Unlock()
lb.lines = lb.lines[:0]
}
@ -102,7 +102,7 @@ type BaseMiner struct {
Running bool `json:"running"`
ConfigPath string `json:"configPath"`
API *API `json:"api"`
mu sync.RWMutex
mutex sync.RWMutex
cmd *exec.Cmd
stdinPipe io.WriteCloser `json:"-"`
HashrateHistory []HashratePoint `json:"hashrateHistory"`
@ -118,8 +118,8 @@ func (b *BaseMiner) GetType() string {
// name := miner.GetName() // e.g. "xmrig-randomx" or "tt-miner-kawpow"
func (b *BaseMiner) GetName() string {
b.mu.RLock()
defer b.mu.RUnlock()
b.mutex.RLock()
defer b.mutex.RUnlock()
return b.Name
}
@ -138,17 +138,17 @@ func (b *BaseMiner) GetPath() string {
// binary := miner.GetBinaryPath() // e.g. "/home/user/.local/share/lethean-desktop/miners/xmrig/xmrig"
func (b *BaseMiner) GetBinaryPath() string {
b.mu.RLock()
defer b.mu.RUnlock()
b.mutex.RLock()
defer b.mutex.RUnlock()
return b.MinerBinary
}
// if err := miner.Stop(); err != nil { log.Warn("stop failed", ...) }
func (b *BaseMiner) Stop() error {
b.mu.Lock()
b.mutex.Lock()
if !b.Running || b.cmd == nil {
b.mu.Unlock()
b.mutex.Unlock()
return ErrMinerNotRunning(b.Name)
}
@ -165,7 +165,7 @@ func (b *BaseMiner) Stop() error {
// Mark as not running immediately to prevent concurrent Stop() calls
b.Running = false
b.cmd = nil
b.mu.Unlock()
b.mutex.Unlock()
// Try graceful shutdown with SIGTERM first (Unix only)
if runtime.GOOS != "windows" {
@ -201,10 +201,10 @@ const stdinWriteTimeout = 5 * time.Second
// if err := miner.WriteStdin("h"); err != nil { /* miner not running */ }
func (b *BaseMiner) WriteStdin(input string) error {
b.mu.RLock()
b.mutex.RLock()
stdinPipe := b.stdinPipe
running := b.Running
b.mu.RUnlock()
b.mutex.RUnlock()
if !running || stdinPipe == nil {
return ErrMinerNotRunning(b.Name)
@ -417,8 +417,8 @@ func (b *BaseMiner) CheckInstallation() (*InstallationDetails, error) {
// points := miner.GetHashrateHistory() // low-res (24h) + high-res (5min) points in chronological order
func (b *BaseMiner) GetHashrateHistory() []HashratePoint {
b.mu.RLock()
defer b.mu.RUnlock()
b.mutex.RLock()
defer b.mutex.RUnlock()
combinedHistory := make([]HashratePoint, 0, len(b.LowResHashrateHistory)+len(b.HashrateHistory))
combinedHistory = append(combinedHistory, b.LowResHashrateHistory...)
combinedHistory = append(combinedHistory, b.HashrateHistory...)
@ -427,31 +427,31 @@ func (b *BaseMiner) GetHashrateHistory() []HashratePoint {
// miner.AddHashratePoint(HashratePoint{Timestamp: time.Now(), Hashrate: 1234.5})
func (b *BaseMiner) AddHashratePoint(point HashratePoint) {
b.mu.Lock()
defer b.mu.Unlock()
b.mutex.Lock()
defer b.mutex.Unlock()
b.HashrateHistory = append(b.HashrateHistory, point)
}
// n := miner.GetHighResHistoryLength() // 0..30 points (last 5 min at 10s resolution)
func (b *BaseMiner) GetHighResHistoryLength() int {
b.mu.RLock()
defer b.mu.RUnlock()
b.mutex.RLock()
defer b.mutex.RUnlock()
return len(b.HashrateHistory)
}
// n := miner.GetLowResHistoryLength() // 0..1440 points (last 24h at 1min resolution)
func (b *BaseMiner) GetLowResHistoryLength() int {
b.mu.RLock()
defer b.mu.RUnlock()
b.mutex.RLock()
defer b.mutex.RUnlock()
return len(b.LowResHashrateHistory)
}
// lines := miner.GetLogs()
// response.Logs = lines[max(0, len(lines)-100):]
func (b *BaseMiner) GetLogs() []string {
b.mu.RLock()
b.mutex.RLock()
logBuffer := b.LogBuffer
b.mu.RUnlock()
b.mutex.RUnlock()
if logBuffer == nil {
return []string{}
@ -461,8 +461,8 @@ func (b *BaseMiner) GetLogs() []string {
// ReduceHashrateHistory aggregates and trims hashrate data.
func (b *BaseMiner) ReduceHashrateHistory(now time.Time) {
b.mu.Lock()
defer b.mu.Unlock()
b.mutex.Lock()
defer b.mutex.Unlock()
if !b.LastLowResAggregation.IsZero() && now.Sub(b.LastLowResAggregation) < LowResolutionInterval {
return

View file

@ -173,11 +173,11 @@ func (m *TTMiner) CheckInstallation() (*InstallationDetails, error) {
}
// Update shared fields under lock
m.mu.Lock()
m.mutex.Lock()
m.MinerBinary = binaryPath
m.Path = filepath.Dir(binaryPath)
m.Version = version
m.mu.Unlock()
m.mutex.Unlock()
return &InstallationDetails{
IsInstalled: true,

View file

@ -15,9 +15,9 @@ 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()
m.mutex.RLock()
needsInstallCheck := m.MinerBinary == ""
m.mu.RUnlock()
m.mutex.RUnlock()
if needsInstallCheck {
if _, err := m.CheckInstallation(); err != nil {
@ -25,8 +25,8 @@ func (m *TTMiner) Start(config *Config) error {
}
}
m.mu.Lock()
defer m.mu.Unlock()
m.mutex.Lock()
defer m.mutex.Unlock()
if m.Running {
return errors.New("miner is already running")
@ -100,13 +100,13 @@ func (m *TTMiner) Start(config *Config) error {
}
}
m.mu.Lock()
m.mutex.Lock()
// Only clear if this is still the same command (not restarted)
if m.cmd == cmd {
m.Running = false
m.cmd = nil
}
m.mu.Unlock()
m.mutex.Unlock()
if err != nil {
logging.Debug("TT-Miner exited with error", logging.Fields{"error": err})
} else {

View file

@ -8,13 +8,13 @@ import (
// GetStats retrieves performance metrics from the TT-Miner API.
func (m *TTMiner) GetStats(ctx context.Context) (*PerformanceMetrics, error) {
// Read state under RLock, then release before HTTP call
m.mu.RLock()
m.mutex.RLock()
if !m.Running {
m.mu.RUnlock()
m.mutex.RUnlock()
return nil, errors.New("miner is not running")
}
if m.API == nil || m.API.ListenPort == 0 {
m.mu.RUnlock()
m.mutex.RUnlock()
return nil, errors.New("miner API not configured or port is zero")
}
config := HTTPStatsConfig{
@ -22,7 +22,7 @@ func (m *TTMiner) GetStats(ctx context.Context) (*PerformanceMetrics, error) {
Port: m.API.ListenPort,
Endpoint: "/summary",
}
m.mu.RUnlock()
m.mutex.RUnlock()
// Create request with context and timeout
reqCtx, cancel := context.WithTimeout(ctx, statsTimeout)
@ -35,9 +35,9 @@ func (m *TTMiner) GetStats(ctx context.Context) (*PerformanceMetrics, error) {
}
// Store the full summary in the miner struct (requires lock)
m.mu.Lock()
m.mutex.Lock()
m.FullStats = &summary
m.mu.Unlock()
m.mutex.Unlock()
// Calculate total hashrate from all GPUs
var totalHashrate float64

View file

@ -173,9 +173,9 @@ func (m *XMRigMiner) CheckInstallation() (*InstallationDetails, error) {
}
// Get the config path using the helper (use instance name if set)
m.mu.RLock()
m.mutex.RLock()
instanceName := m.Name
m.mu.RUnlock()
m.mutex.RUnlock()
configPath, err := getXMRigConfigPath(instanceName)
if err != nil {
@ -184,11 +184,11 @@ func (m *XMRigMiner) CheckInstallation() (*InstallationDetails, error) {
}
// Update shared fields under lock
m.mu.Lock()
m.mutex.Lock()
m.MinerBinary = binaryPath
m.Path = filepath.Dir(binaryPath)
m.Version = version
m.mu.Unlock()
m.mutex.Unlock()
return &InstallationDetails{
IsInstalled: true,

View file

@ -18,9 +18,9 @@ import (
// if err := miner.Start(&mining.Config{Algo: "rx/0", Pool: "pool.lthn.io:3333"}); err != nil { return err }
func (m *XMRigMiner) Start(config *Config) error {
// Check installation BEFORE acquiring lock (CheckInstallation takes its own locks)
m.mu.RLock()
m.mutex.RLock()
needsInstallCheck := m.MinerBinary == ""
m.mu.RUnlock()
m.mutex.RUnlock()
if needsInstallCheck {
if _, err := m.CheckInstallation(); err != nil {
@ -28,8 +28,8 @@ func (m *XMRigMiner) Start(config *Config) error {
}
}
m.mu.Lock()
defer m.mu.Unlock()
m.mutex.Lock()
defer m.mutex.Unlock()
if m.Running {
return errors.New("miner is already running")
@ -139,13 +139,13 @@ func (m *XMRigMiner) Start(config *Config) error {
}
}
m.mu.Lock()
m.mutex.Lock()
// Only clear if this is still the same command (not restarted)
if m.cmd == cmd {
m.Running = false
m.cmd = nil
}
m.mu.Unlock()
m.mutex.Unlock()
}()
return nil

View file

@ -12,13 +12,13 @@ const statsTimeout = 5 * time.Second
// GetStats retrieves the performance statistics from the running XMRig miner.
func (m *XMRigMiner) GetStats(ctx context.Context) (*PerformanceMetrics, error) {
// Read state under RLock, then release before HTTP call
m.mu.RLock()
m.mutex.RLock()
if !m.Running {
m.mu.RUnlock()
m.mutex.RUnlock()
return nil, errors.New("miner is not running")
}
if m.API == nil || m.API.ListenPort == 0 {
m.mu.RUnlock()
m.mutex.RUnlock()
return nil, errors.New("miner API not configured or port is zero")
}
config := HTTPStatsConfig{
@ -26,7 +26,7 @@ func (m *XMRigMiner) GetStats(ctx context.Context) (*PerformanceMetrics, error)
Port: m.API.ListenPort,
Endpoint: "/2/summary",
}
m.mu.RUnlock()
m.mutex.RUnlock()
// Create request with context and timeout
reqCtx, cancel := context.WithTimeout(ctx, statsTimeout)
@ -39,9 +39,9 @@ func (m *XMRigMiner) GetStats(ctx context.Context) (*PerformanceMetrics, error)
}
// Store the full summary in the miner struct (requires lock)
m.mu.Lock()
m.mutex.Lock()
m.FullStats = &summary
m.mu.Unlock()
m.mutex.Unlock()
var hashrate int
if len(summary.Hashrate.Total) > 0 {