2017-08-15 19:24:22 +00:00
|
|
|
package query
|
2016-03-28 14:55:50 +00:00
|
|
|
|
2018-03-02 16:59:40 +00:00
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
// MonitorFunc is a function that will be called to check if a query
|
|
|
|
// is currently healthy. If the query needs to be interrupted for some reason,
|
|
|
|
// the error should be returned by this function.
|
|
|
|
type MonitorFunc func(<-chan struct{}) error
|
|
|
|
|
|
|
|
// Monitor monitors the status of a query and returns whether the query should
|
|
|
|
// be aborted with an error.
|
|
|
|
type Monitor interface {
|
|
|
|
// Monitor starts a new goroutine that will monitor a query. The function
|
|
|
|
// will be passed in a channel to signal when the query has been finished
|
|
|
|
// normally. If the function returns with an error and the query is still
|
|
|
|
// running, the query will be terminated.
|
|
|
|
Monitor(fn MonitorFunc)
|
|
|
|
}
|
|
|
|
|
|
|
|
// MonitorFromContext returns a Monitor embedded within the Context
|
|
|
|
// if one exists.
|
|
|
|
func MonitorFromContext(ctx context.Context) Monitor {
|
|
|
|
v, _ := ctx.Value(monitorContextKey).(Monitor)
|
|
|
|
return v
|
|
|
|
}
|
2016-03-28 14:55:50 +00:00
|
|
|
|
|
|
|
// PointLimitMonitor is a query monitor that exits when the number of points
|
|
|
|
// emitted exceeds a threshold.
|
Refactor the math engine to compile the query and use eval
This change makes it so that we simplify the math engine so it doesn't
use a complicated set of nested iterators. That way, we have to change
math in one fewer place.
It also greatly simplifies the query engine as now we can create the
necessary iterators, join them by time, name, and tags, and then use the
cursor interface to read them and use eval to compute the result. It
makes it so the auxiliary iterators and all of their complexity can be
removed.
This also makes use of the new eval functionality that was recently
added to the influxql package.
No math functions have been added, but the scaffolding has been included
so things like trigonometry functions are just a single commit away.
This also introduces a small breaking change. Because of the call
optimization, it is now possible to use the same selector multiple times
as a selector. So if you do this:
SELECT max(value) * 2, max(value) / 2 FROM cpu
This will now return the timestamp of the max value rather than zero
since this query is considered to have only a single selector rather
than multiple separate selectors. If any aspect of the selector is
different, such as different selector functions or different arguments,
it will consider the selectors to be aggregates like the old behavior.
2018-03-19 17:05:55 +00:00
|
|
|
func PointLimitMonitor(cur Cursor, interval time.Duration, limit int) MonitorFunc {
|
2016-03-28 14:55:50 +00:00
|
|
|
return func(closing <-chan struct{}) error {
|
|
|
|
ticker := time.NewTicker(interval)
|
|
|
|
defer ticker.Stop()
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-ticker.C:
|
Refactor the math engine to compile the query and use eval
This change makes it so that we simplify the math engine so it doesn't
use a complicated set of nested iterators. That way, we have to change
math in one fewer place.
It also greatly simplifies the query engine as now we can create the
necessary iterators, join them by time, name, and tags, and then use the
cursor interface to read them and use eval to compute the result. It
makes it so the auxiliary iterators and all of their complexity can be
removed.
This also makes use of the new eval functionality that was recently
added to the influxql package.
No math functions have been added, but the scaffolding has been included
so things like trigonometry functions are just a single commit away.
This also introduces a small breaking change. Because of the call
optimization, it is now possible to use the same selector multiple times
as a selector. So if you do this:
SELECT max(value) * 2, max(value) / 2 FROM cpu
This will now return the timestamp of the max value rather than zero
since this query is considered to have only a single selector rather
than multiple separate selectors. If any aspect of the selector is
different, such as different selector functions or different arguments,
it will consider the selectors to be aggregates like the old behavior.
2018-03-19 17:05:55 +00:00
|
|
|
stats := cur.Stats()
|
2016-03-28 14:55:50 +00:00
|
|
|
if stats.PointN >= limit {
|
2016-10-28 20:44:33 +00:00
|
|
|
return ErrMaxSelectPointsLimitExceeded(stats.PointN, limit)
|
2016-03-28 14:55:50 +00:00
|
|
|
}
|
|
|
|
case <-closing:
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|