package influx import ( "context" "encoding/json" "fmt" "time" _ "github.com/influxdata/influxdb1-client" "github.com/influxdata/influxdb1-client/models" client "github.com/influxdata/influxdb1-client/v2" "github.com/filecoin-project/lotus/build" ) type PointList struct { points []models.Point } func NewPointList() *PointList { return &PointList{} } func (pl *PointList) AddPoint(p models.Point) { pl.points = append(pl.points, p) } func (pl *PointList) Points() []models.Point { return pl.points } type WriteQueue struct { ch chan client.BatchPoints } func NewWriteQueue(ctx context.Context, influx client.Client) *WriteQueue { ch := make(chan client.BatchPoints, 128) maxRetries := 10 go func() { main: for { select { case <-ctx.Done(): return case batch := <-ch: for i := 0; i < maxRetries; i++ { if err := influx.Write(batch); err != nil { log.Warnw("Failed to write batch", "error", err) build.Clock.Sleep(3 * time.Second) continue } continue main } log.Error("dropping batch due to failure to write") } } }() return &WriteQueue{ ch: ch, } } func (i *WriteQueue) AddBatch(bp client.BatchPoints) { i.ch <- bp } func (i *WriteQueue) Close() { close(i.ch) } func NewClient(addr, user, pass string) (client.Client, error) { return client.NewHTTPClient(client.HTTPConfig{ Addr: addr, Username: user, Password: pass, }) } func NewBatch() (client.BatchPoints, error) { return client.NewBatchPoints(client.BatchPointsConfig{}) } func NewPoint(name string, value interface{}) models.Point { pt, _ := models.NewPoint(name, models.Tags{}, map[string]interface{}{"value": value}, build.Clock.Now().UTC()) return pt } func NewPointFrom(p models.Point) *client.Point { return client.NewPointFrom(p) } func ResetDatabase(influx client.Client, database string) error { log.Debug("resetting database") q := client.NewQuery(fmt.Sprintf(`DROP DATABASE "%s"; CREATE DATABASE "%s";`, database, database), "", "") _, err := influx.Query(q) if err != nil { return err } log.Infow("database reset", "database", database) return nil } func GetLastRecordedHeight(influx client.Client, database string) (int64, error) { log.Debug("retrieving last record height") q := client.NewQuery(`SELECT "value" FROM "chain.height" ORDER BY time DESC LIMIT 1`, database, "") res, err := influx.Query(q) if err != nil { return 0, err } if len(res.Results) == 0 { return 0, fmt.Errorf("No results found for last recorded height") } if len(res.Results[0].Series) == 0 { return 0, fmt.Errorf("No results found for last recorded height") } height, err := (res.Results[0].Series[0].Values[0][1].(json.Number)).Int64() if err != nil { return 0, err } log.Infow("last record height", "height", height) return height, nil }