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 } } } }