ConfigProvider, PolicyExecutor, DBStatsProvider, scheduler и safety; зависимость robfig/cron/v3. Co-authored-by: Cursor <[email protected]>
63 lines
1.8 KiB
Go
63 lines
1.8 KiB
Go
package maintenance
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"evobgp/internal/pgmonitor"
|
|
)
|
|
|
|
// TableHints are PostgreSQL statistics hints for UI recommendations.
|
|
type TableHints struct {
|
|
TableName string `json:"table_name"`
|
|
DeadTuples int64 `json:"n_dead_tup"`
|
|
BloatRatio float64 `json:"bloat_ratio,omitempty"`
|
|
LastAutovacuum string `json:"last_autovacuum,omitempty"`
|
|
RecommendVacuum bool `json:"recommend_vacuum"`
|
|
Detail string `json:"detail,omitempty"`
|
|
Refs []string `json:"refs,omitempty"`
|
|
}
|
|
|
|
// DBStatsProvider wraps pgmonitor for maintenance policy hints.
|
|
type DBStatsProvider struct {
|
|
pg *pgmonitor.Service
|
|
}
|
|
|
|
// NewDBStatsProvider constructs a stats provider.
|
|
func NewDBStatsProvider(pg *pgmonitor.Service) *DBStatsProvider {
|
|
return &DBStatsProvider{pg: pg}
|
|
}
|
|
|
|
// Hints returns table-level vacuum/bloat hints.
|
|
func (d *DBStatsProvider) Hints(ctx context.Context, tableName string) (TableHints, error) {
|
|
out := TableHints{TableName: tableName}
|
|
if d == nil || d.pg == nil {
|
|
return out, fmt.Errorf("maintenance: postgres monitoring not configured")
|
|
}
|
|
if err := ValidateTableName(tableName); err != nil {
|
|
return out, err
|
|
}
|
|
tables, err := d.pg.Tables(ctx, 100)
|
|
if err != nil {
|
|
return out, err
|
|
}
|
|
for _, t := range tables {
|
|
if t.Relname != tableName {
|
|
continue
|
|
}
|
|
out.DeadTuples = t.DeadTuples
|
|
out.BloatRatio = t.BloatRatio
|
|
if t.LastAutovacuum != nil {
|
|
out.LastAutovacuum = t.LastAutovacuum.UTC().Format("2006-01-02T15:04:05Z")
|
|
}
|
|
if t.BloatRatio > 0.2 && t.DeadTuples > 5000 {
|
|
out.RecommendVacuum = true
|
|
out.Detail = "Высокая доля n_dead_tup; рекомендуется VACUUM."
|
|
out.Refs = []string{t.Relname}
|
|
}
|
|
return out, nil
|
|
}
|
|
out.Detail = "Таблица не найдена в pg_stat_user_tables (top by size)."
|
|
return out, nil
|
|
}
|