49 lines
1.4 KiB
Go
49 lines
1.4 KiB
Go
package query
|
|
|
|
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
|
|
}
|
|
|
|
// PointLimitMonitor is a query monitor that exits when the number of points
|
|
// emitted exceeds a threshold.
|
|
func PointLimitMonitor(cur Cursor, interval time.Duration, limit int) MonitorFunc {
|
|
return func(closing <-chan struct{}) error {
|
|
ticker := time.NewTicker(interval)
|
|
defer ticker.Stop()
|
|
for {
|
|
select {
|
|
case <-ticker.C:
|
|
stats := cur.Stats()
|
|
if stats.PointN >= limit {
|
|
return ErrMaxSelectPointsLimitExceeded(stats.PointN, limit)
|
|
}
|
|
case <-closing:
|
|
return nil
|
|
}
|
|
}
|
|
}
|
|
}
|