Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
103 lines
2.8 KiB
Go
103 lines
2.8 KiB
Go
package db
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
)
|
|
|
|
type TierOutcomeStats struct {
|
|
Tier string
|
|
Total int
|
|
Successes int
|
|
Failures int
|
|
MaxHashrate float64
|
|
}
|
|
|
|
func (d *Database) InsertTierOutcome(agentID, fingerprintKey, tier string, ok bool, hashrate float64, phase string) error {
|
|
okInt := 0
|
|
if ok {
|
|
okInt = 1
|
|
}
|
|
_, err := d.Exec(
|
|
`INSERT INTO tier_outcomes (agent_id, fingerprint_key, tier, ok, hashrate, phase, created_at)
|
|
VALUES (?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)`,
|
|
agentID, fingerprintKey, tier, okInt, hashrate, phase,
|
|
)
|
|
return err
|
|
}
|
|
|
|
func (d *Database) UpsertAgentStrategyCache(agentID, fingerprintKey, strategyJSON string) error {
|
|
_, err := d.Exec(
|
|
`INSERT INTO agent_strategy_cache (agent_id, fingerprint_key, strategy_json, updated_at)
|
|
VALUES (?, ?, ?, CURRENT_TIMESTAMP)
|
|
ON CONFLICT(agent_id) DO UPDATE SET
|
|
fingerprint_key = excluded.fingerprint_key,
|
|
strategy_json = excluded.strategy_json,
|
|
updated_at = CURRENT_TIMESTAMP`,
|
|
agentID, fingerprintKey, strategyJSON,
|
|
)
|
|
return err
|
|
}
|
|
|
|
func (d *Database) ListAgentStrategyFingerprints() (map[string]string, error) {
|
|
rows, err := d.Query(`SELECT agent_id, fingerprint_key FROM agent_strategy_cache`)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
out := make(map[string]string)
|
|
for rows.Next() {
|
|
var agentID, fpKey string
|
|
if err := rows.Scan(&agentID, &fpKey); err != nil {
|
|
return nil, err
|
|
}
|
|
out[agentID] = fpKey
|
|
}
|
|
return out, rows.Err()
|
|
}
|
|
|
|
func (d *Database) AggregateTierOutcomes(fingerprintKey, goos string) ([]TierOutcomeStats, error) {
|
|
stats, err := d.aggregateTierOutcomesWhere(`fingerprint_key = ?`, fingerprintKey)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(stats) > 0 {
|
|
return stats, nil
|
|
}
|
|
if goos == "" {
|
|
return nil, nil
|
|
}
|
|
return d.aggregateTierOutcomesWhere(`fingerprint_key LIKE ?`, goos+"|%")
|
|
}
|
|
|
|
func (d *Database) aggregateTierOutcomesWhere(whereClause string, arg interface{}) ([]TierOutcomeStats, error) {
|
|
query := fmt.Sprintf(`
|
|
SELECT tier, COUNT(*) AS total,
|
|
SUM(CASE WHEN ok = 1 THEN 1 ELSE 0 END) AS successes,
|
|
SUM(CASE WHEN ok = 0 THEN 1 ELSE 0 END) AS failures,
|
|
MAX(CASE WHEN ok = 1 THEN hashrate ELSE 0 END) AS max_hashrate
|
|
FROM tier_outcomes WHERE %s GROUP BY tier`, whereClause)
|
|
rows, err := d.Query(query, arg)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var out []TierOutcomeStats
|
|
for rows.Next() {
|
|
var s TierOutcomeStats
|
|
if err := rows.Scan(&s.Tier, &s.Total, &s.Successes, &s.Failures, &s.MaxHashrate); err != nil {
|
|
return nil, err
|
|
}
|
|
out = append(out, s)
|
|
}
|
|
return out, rows.Err()
|
|
}
|
|
|
|
func (d *Database) PruneTierOutcomesOlderThan(cutoff time.Time) (int64, error) {
|
|
res, err := d.Exec(`DELETE FROM tier_outcomes WHERE created_at < ?`, cutoff)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return res.RowsAffected()
|
|
}
|