// Record the stream for a duration func (s *Service) doRecordStream(id string, dataSource DataSource, stop time.Time, dbrps []kapacitor.DBRP, measurements []string) error { e, err := s.TaskMaster.NewFork(id, dbrps, measurements) if err != nil { return err } sw, err := dataSource.StreamWriter() if err != nil { return err } defer sw.Close() done := make(chan struct{}) go func() { closed := false for p, ok := e.NextPoint(); ok; p, ok = e.NextPoint() { if closed { continue } if p.Time.After(stop) { closed = true close(done) //continue to read any data already on the edge, but just drop it. continue } kapacitor.WritePointForRecording(sw, p, precision) } }() <-done e.Abort() s.TaskMaster.DelFork(id) return nil }
func (s *Service) saveStreamQuery(dataSource DataSource, points <-chan models.Point, precision string) error { sw, err := dataSource.StreamWriter() if err != nil { return err } for point := range points { err := kapacitor.WritePointForRecording(sw, point, precision) if err != nil { return err } } return sw.Close() }
// Record the stream for a duration func (r *Service) doRecordStream(rid uuid.UUID, dur time.Duration, dbrps []kapacitor.DBRP, started chan struct{}) error { e, err := r.TaskMaster.NewFork(rid.String(), dbrps) if err != nil { return err } sw, err := r.newStreamWriter(rid) if err != nil { return err } defer sw.Close() done := make(chan struct{}) go func() { close(started) start := time.Time{} closed := false for p, ok := e.NextPoint(); ok; p, ok = e.NextPoint() { if closed { continue } if start.IsZero() { start = p.Time } if p.Time.Sub(start) > dur { closed = true close(done) //continue to read any data already on the edge, but just drop it. continue } kapacitor.WritePointForRecording(sw, p, precision) } }() <-done e.Abort() r.TaskMaster.DelFork(rid.String()) return nil }
func (r *Service) doRecordQuery(rid uuid.UUID, q string, tt kapacitor.TaskType) error { // Parse query to determine dbrp var db, rp string s, err := influxql.ParseStatement(q) if err != nil { return err } if slct, ok := s.(*influxql.SelectStatement); ok && len(slct.Sources) == 1 { if m, ok := slct.Sources[0].(*influxql.Measurement); ok { db = m.Database rp = m.RetentionPolicy } } if db == "" || rp == "" { return errors.New("could not determine database and retention policy. Is the query fully qualified?") } // Query InfluxDB con, err := r.InfluxDBService.NewClient() if err != nil { return err } query := client.Query{ Command: q, } resp, err := con.Query(query) if err != nil { return err } if resp.Err != nil { return resp.Err } // Open appropriate writer var w io.Writer var c io.Closer switch tt { case kapacitor.StreamTask: sw, err := r.newStreamWriter(rid) if err != nil { return err } w = sw c = sw case kapacitor.BatchTask: archive, err := r.newBatchArchive(rid) if err != nil { return err } w, err = archive.Create(0) if err != nil { return err } c = archive } // Write results to writer for _, res := range resp.Results { batches, err := models.ResultToBatches(res) if err != nil { c.Close() return err } for _, batch := range batches { switch tt { case kapacitor.StreamTask: for _, bp := range batch.Points { p := models.Point{ Name: batch.Name, Database: db, RetentionPolicy: rp, Tags: bp.Tags, Fields: bp.Fields, Time: bp.Time, } kapacitor.WritePointForRecording(w, p, precision) } case kapacitor.BatchTask: kapacitor.WriteBatchForRecording(w, batch) } } } return c.Close() }