2023-07-03 18:24:25 +08:00
|
|
|
package tasks
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"strconv"
|
|
|
|
|
|
|
|
"github.com/milvus-io/milvus-proto/go-api/v2/commonpb"
|
|
|
|
"github.com/milvus-io/milvus/internal/proto/internalpb"
|
|
|
|
"github.com/milvus-io/milvus/internal/proto/querypb"
|
|
|
|
"github.com/milvus-io/milvus/internal/proto/segcorepb"
|
|
|
|
"github.com/milvus-io/milvus/internal/querynodev2/collector"
|
|
|
|
"github.com/milvus-io/milvus/internal/querynodev2/segments"
|
|
|
|
"github.com/milvus-io/milvus/pkg/metrics"
|
|
|
|
"github.com/milvus-io/milvus/pkg/util/metricsinfo"
|
|
|
|
"github.com/milvus-io/milvus/pkg/util/paramtable"
|
|
|
|
"github.com/milvus-io/milvus/pkg/util/timerecord"
|
|
|
|
)
|
|
|
|
|
|
|
|
var _ Task = &QueryTask{}
|
|
|
|
|
|
|
|
func NewQueryTask(ctx context.Context,
|
|
|
|
collection *segments.Collection,
|
|
|
|
manager *segments.Manager,
|
|
|
|
req *querypb.QueryRequest,
|
|
|
|
) *QueryTask {
|
|
|
|
return &QueryTask{
|
|
|
|
ctx: ctx,
|
|
|
|
collection: collection,
|
|
|
|
segmentManager: manager,
|
|
|
|
req: req,
|
|
|
|
notifier: make(chan error, 1),
|
|
|
|
tr: timerecord.NewTimeRecorderWithTrace(ctx, "queryTask"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type QueryTask struct {
|
|
|
|
ctx context.Context
|
|
|
|
collection *segments.Collection
|
|
|
|
segmentManager *segments.Manager
|
|
|
|
req *querypb.QueryRequest
|
|
|
|
result *internalpb.RetrieveResults
|
|
|
|
notifier chan error
|
|
|
|
tr *timerecord.TimeRecorder
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return the username which task is belong to.
|
|
|
|
// Return "" if the task do not contain any user info.
|
|
|
|
func (t *QueryTask) Username() string {
|
|
|
|
return t.req.Req.GetUsername()
|
|
|
|
}
|
|
|
|
|
|
|
|
// PreExecute the task, only call once.
|
|
|
|
func (t *QueryTask) PreExecute() error {
|
|
|
|
// Update task wait time metric before execute
|
|
|
|
nodeID := strconv.FormatInt(paramtable.GetNodeID(), 10)
|
|
|
|
inQueueDuration := t.tr.ElapseSpan()
|
|
|
|
|
|
|
|
// Update in queue metric for prometheus.
|
|
|
|
metrics.QueryNodeSQLatencyInQueue.WithLabelValues(
|
|
|
|
nodeID,
|
|
|
|
metrics.QueryLabel).
|
|
|
|
Observe(float64(inQueueDuration.Milliseconds()))
|
|
|
|
|
|
|
|
username := t.Username()
|
|
|
|
metrics.QueryNodeSQPerUserLatencyInQueue.WithLabelValues(
|
|
|
|
nodeID,
|
|
|
|
metrics.QueryLabel,
|
|
|
|
username).
|
|
|
|
Observe(float64(inQueueDuration.Milliseconds()))
|
|
|
|
|
|
|
|
// Update collector for query node quota.
|
|
|
|
collector.Average.Add(metricsinfo.QueryQueueMetric, float64(inQueueDuration.Microseconds()))
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Execute the task, only call once.
|
|
|
|
func (t *QueryTask) Execute() error {
|
2023-07-25 18:51:01 +08:00
|
|
|
tr := timerecord.NewTimeRecorderWithTrace(t.ctx, "QueryTask")
|
|
|
|
|
2023-07-03 18:24:25 +08:00
|
|
|
retrievePlan, err := segments.NewRetrievePlan(
|
|
|
|
t.collection,
|
|
|
|
t.req.Req.GetSerializedExprPlan(),
|
2023-08-10 18:53:17 +08:00
|
|
|
t.req.Req.GetMvccTimestamp(),
|
2023-07-03 18:24:25 +08:00
|
|
|
t.req.Req.Base.GetMsgID(),
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer retrievePlan.Delete()
|
|
|
|
|
|
|
|
var results []*segcorepb.RetrieveResults
|
|
|
|
if t.req.GetScope() == querypb.DataScope_Historical {
|
|
|
|
results, _, _, err = segments.RetrieveHistorical(
|
|
|
|
t.ctx,
|
|
|
|
t.segmentManager,
|
|
|
|
retrievePlan,
|
|
|
|
t.req.Req.CollectionID,
|
|
|
|
nil,
|
|
|
|
t.req.GetSegmentIDs(),
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
results, _, _, err = segments.RetrieveStreaming(
|
|
|
|
t.ctx,
|
|
|
|
t.segmentManager,
|
|
|
|
retrievePlan,
|
|
|
|
t.req.Req.CollectionID,
|
|
|
|
nil,
|
|
|
|
t.req.GetSegmentIDs(),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
reducer := segments.CreateSegCoreReducer(
|
|
|
|
t.req,
|
|
|
|
t.collection.Schema(),
|
|
|
|
)
|
|
|
|
|
|
|
|
reducedResult, err := reducer.Reduce(t.ctx, results)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
t.result = &internalpb.RetrieveResults{
|
2023-08-09 11:37:15 +08:00
|
|
|
Base: &commonpb.MsgBase{
|
|
|
|
SourceID: paramtable.GetNodeID(),
|
|
|
|
},
|
2023-07-03 18:24:25 +08:00
|
|
|
Status: &commonpb.Status{ErrorCode: commonpb.ErrorCode_Success},
|
|
|
|
Ids: reducedResult.Ids,
|
|
|
|
FieldsData: reducedResult.FieldsData,
|
2023-07-25 18:51:01 +08:00
|
|
|
CostAggregation: &internalpb.CostAggregation{
|
|
|
|
ServiceTime: tr.ElapseSpan().Milliseconds(),
|
|
|
|
},
|
2023-07-03 18:24:25 +08:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *QueryTask) Done(err error) {
|
|
|
|
t.notifier <- err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *QueryTask) Canceled() error {
|
|
|
|
return t.ctx.Err()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *QueryTask) Wait() error {
|
|
|
|
return <-t.notifier
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *QueryTask) Result() *internalpb.RetrieveResults {
|
|
|
|
return t.result
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *QueryTask) NQ() int64 {
|
|
|
|
return 1
|
|
|
|
}
|