v1.27.0-a #10
@ -35,6 +35,8 @@ type actorInfo struct {
|
||||
|
||||
ActorBalance, ActorAvailable, WorkerBalance string
|
||||
|
||||
Win1, Win7, Win30 int64
|
||||
|
||||
Deadlines []actorDeadline
|
||||
}
|
||||
|
||||
|
@ -70,6 +70,11 @@ func (a *app) updateActor(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
wins, err := a.spWins(ctx)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting sp wins: %w", err)
|
||||
}
|
||||
|
||||
for addr, cnames := range confNameToAddr {
|
||||
p, err := api.StateMinerPower(ctx, addr, types.EmptyTSK)
|
||||
if err != nil {
|
||||
@ -167,6 +172,10 @@ func (a *app) updateActor(ctx context.Context) error {
|
||||
ActorBalance: types.FIL(mact.Balance).Short(),
|
||||
ActorAvailable: types.FIL(avail).Short(),
|
||||
WorkerBalance: types.FIL(wbal).Short(),
|
||||
|
||||
Win1: wins[addr].Win1, // note: zero values are fine here
|
||||
Win7: wins[addr].Win7,
|
||||
Win30: wins[addr].Win30,
|
||||
})
|
||||
}
|
||||
|
||||
@ -199,6 +208,57 @@ func (a *app) loadConfigs(ctx context.Context) (map[string]string, error) {
|
||||
return configs, nil
|
||||
}
|
||||
|
||||
type wins struct {
|
||||
SpID int64 `db:"sp_id"`
|
||||
Win1 int64 `db:"win1"`
|
||||
Win7 int64 `db:"win7"`
|
||||
Win30 int64 `db:"win30"`
|
||||
}
|
||||
|
||||
func (a *app) spWins(ctx context.Context) (map[address.Address]wins, error) {
|
||||
var w []wins
|
||||
|
||||
// note: this query uses mining_tasks_won_sp_id_base_compute_time_index
|
||||
err := a.db.Select(ctx, &w, `WITH wins AS (
|
||||
SELECT
|
||||
sp_id,
|
||||
base_compute_time,
|
||||
won
|
||||
FROM
|
||||
mining_tasks
|
||||
WHERE
|
||||
won = true
|
||||
AND base_compute_time > NOW() - INTERVAL '30 days'
|
||||
)
|
||||
|
||||
SELECT
|
||||
sp_id,
|
||||
COUNT(*) FILTER (WHERE base_compute_time > NOW() - INTERVAL '1 day') AS "win1",
|
||||
COUNT(*) FILTER (WHERE base_compute_time > NOW() - INTERVAL '7 days') AS "win7",
|
||||
COUNT(*) FILTER (WHERE base_compute_time > NOW() - INTERVAL '30 days') AS "win30"
|
||||
FROM
|
||||
wins
|
||||
GROUP BY
|
||||
sp_id
|
||||
ORDER BY
|
||||
sp_id`)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("query win counts: %w", err)
|
||||
}
|
||||
|
||||
wm := make(map[address.Address]wins)
|
||||
for _, wi := range w {
|
||||
ma, err := address.NewIDAddress(uint64(wi.SpID))
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("parsing miner address: %w", err)
|
||||
}
|
||||
|
||||
wm[ma] = wi
|
||||
}
|
||||
|
||||
return wm, nil
|
||||
}
|
||||
|
||||
func forEachConfig[T any](a *app, cb func(name string, v T) error) error {
|
||||
confs, err := a.loadConfigs(context.Background())
|
||||
if err != nil {
|
||||
|
@ -18,6 +18,13 @@
|
||||
<td>{{.ActorBalance}}</td>
|
||||
<td>{{.ActorAvailable}}</td>
|
||||
<td>{{.WorkerBalance}}</td>
|
||||
<td>
|
||||
<table>
|
||||
<tr><td>1day: {{.Win1}}</td></tr>
|
||||
<tr><td>7day: {{.Win7}}</td></tr>
|
||||
<tr><td>30day: {{.Win30}}</td></tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
{{end}}
|
@ -60,6 +60,7 @@
|
||||
<th>Host</th>
|
||||
<th>ID</th>
|
||||
<th>Last Contact</th>
|
||||
<th>Tasks (24h)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody hx-get="/hapi/simpleinfo/machines" hx-trigger="load,every 5s">
|
||||
@ -100,6 +101,7 @@
|
||||
<th>Balance</th>
|
||||
<th>Available</th>
|
||||
<th>Worker</th>
|
||||
<th>Wins</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody hx-get="/hapi/simpleinfo/actorsummary" hx-trigger="load,every 5s">
|
||||
|
@ -1,3 +1,7 @@
|
||||
/* Used for webui clusterMachineSummary */
|
||||
CREATE INDEX harmony_task_history_work_index
|
||||
ON harmony_task_history (completed_by_host_and_port ASC, name ASC, result ASC, work_end DESC);
|
||||
|
||||
/* Used for webui actorSummary sp wins */
|
||||
create index mining_tasks_won_sp_id_base_compute_time_index
|
||||
on mining_tasks (won asc, sp_id asc, base_compute_time desc);
|
Loading…
Reference in New Issue
Block a user