resp→response, db→database pattern across mining, logging packages. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
57 lines
1.7 KiB
Go
57 lines
1.7 KiB
Go
package mining
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
"net/http"
|
|
"strconv"
|
|
)
|
|
|
|
// var collector StatsCollector = &XMRigStatsCollector{...}
|
|
// metrics, err := collector.CollectStats(ctx)
|
|
type StatsCollector interface {
|
|
CollectStats(ctx context.Context) (*PerformanceMetrics, error)
|
|
}
|
|
|
|
// HTTPStatsConfig{Host: "127.0.0.1", Port: 8080, Endpoint: "/2/summary"}
|
|
type HTTPStatsConfig struct {
|
|
Host string
|
|
Port int
|
|
Endpoint string // e.g., "/2/summary" for XMRig, "/summary" for TT-Miner
|
|
}
|
|
|
|
// var summary XMRigSummary
|
|
// if err := FetchJSONStats(ctx, HTTPStatsConfig{Host: "127.0.0.1", Port: 8080, Endpoint: "/2/summary"}, &summary); err != nil { return err }
|
|
func FetchJSONStats[T any](ctx context.Context, config HTTPStatsConfig, target *T) error {
|
|
if config.Port == 0 {
|
|
return ErrInternal("API port is zero")
|
|
}
|
|
|
|
requestURL := "http://" + config.Host + ":" + strconv.Itoa(config.Port) + config.Endpoint
|
|
|
|
httpRequest, err := http.NewRequestWithContext(ctx, "GET", requestURL, nil)
|
|
if err != nil {
|
|
return ErrInternal("failed to create request").WithCause(err)
|
|
}
|
|
|
|
response, err := getHTTPClient().Do(httpRequest)
|
|
if err != nil {
|
|
return ErrInternal("HTTP request failed").WithCause(err)
|
|
}
|
|
defer response.Body.Close()
|
|
|
|
if response.StatusCode != http.StatusOK {
|
|
io.Copy(io.Discard, response.Body) // Drain body to allow connection reuse
|
|
return ErrInternal("unexpected status code: " + strconv.Itoa(response.StatusCode))
|
|
}
|
|
|
|
body, err := io.ReadAll(response.Body)
|
|
if err != nil {
|
|
return ErrInternal("failed to read response body").WithCause(err)
|
|
}
|
|
if err := UnmarshalJSON(body, target); err != nil {
|
|
return ErrInternal("failed to decode response").WithCause(err)
|
|
}
|
|
|
|
return nil
|
|
}
|