github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/query/executor/request.go (about)

     1  // Copyright (c) 2018 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package executor
    22  
    23  import (
    24  	"context"
    25  	"fmt"
    26  
    27  	"github.com/m3db/m3/src/query/models"
    28  	"github.com/m3db/m3/src/query/parser"
    29  	"github.com/m3db/m3/src/query/plan"
    30  	"github.com/m3db/m3/src/query/storage"
    31  	"github.com/m3db/m3/src/query/util/logging"
    32  	"github.com/m3db/m3/src/x/instrument"
    33  	"github.com/m3db/m3/src/x/opentracing"
    34  
    35  	"go.uber.org/zap"
    36  )
    37  
    38  // State is the request state.
    39  type State int
    40  
    41  const (
    42  	compiling State = iota
    43  	planning
    44  	executing
    45  	all
    46  )
    47  
    48  func (s State) String() string {
    49  	switch s {
    50  	case compiling:
    51  		return "compiling"
    52  	case planning:
    53  		return "planning"
    54  	case executing:
    55  		return "executing"
    56  	case all:
    57  		return "all"
    58  	default:
    59  		return "unknown"
    60  	}
    61  }
    62  
    63  func (s State) durationString() string {
    64  	return fmt.Sprintf("%s_duration_seconds", s)
    65  }
    66  
    67  // Request represents a single request.
    68  type Request struct {
    69  	engine         *engine
    70  	params         models.RequestParams
    71  	fetchOpts      *storage.FetchOptions
    72  	instrumentOpts instrument.Options
    73  }
    74  
    75  func newRequest(
    76  	engine *engine,
    77  	params models.RequestParams,
    78  	fetchOpts *storage.FetchOptions,
    79  	instrumentOpts instrument.Options,
    80  ) *Request {
    81  	return &Request{
    82  		engine:         engine,
    83  		params:         params,
    84  		fetchOpts:      fetchOpts,
    85  		instrumentOpts: instrumentOpts,
    86  	}
    87  }
    88  
    89  func (r *Request) compile(ctx context.Context, parser parser.Parser) (parser.Nodes, parser.Edges, error) {
    90  	sp, ctx := opentracing.StartSpanFromContext(ctx, "compile")
    91  	defer sp.Finish()
    92  	// TODO: Change DAG interface to take in a context
    93  	nodes, edges, err := parser.DAG()
    94  	if err != nil {
    95  		return nil, nil, err
    96  	}
    97  
    98  	if r.params.Debug {
    99  		logging.WithContext(ctx, r.instrumentOpts).
   100  			Info("compiling dag", zap.Any("nodes", nodes), zap.Any("edges", edges))
   101  	}
   102  
   103  	return nodes, edges, nil
   104  }
   105  
   106  func (r *Request) plan(ctx context.Context, nodes parser.Nodes, edges parser.Edges) (plan.PhysicalPlan, error) {
   107  	sp, ctx := opentracing.StartSpanFromContext(ctx, "plan")
   108  	defer sp.Finish()
   109  
   110  	lp, err := plan.NewLogicalPlan(nodes, edges)
   111  	if err != nil {
   112  		return plan.PhysicalPlan{}, err
   113  	}
   114  
   115  	if r.params.Debug {
   116  		logging.WithContext(ctx, r.instrumentOpts).
   117  			Info("logical plan", zap.String("plan", lp.String()))
   118  	}
   119  
   120  	pp, err := plan.NewPhysicalPlan(lp, r.params)
   121  	if err != nil {
   122  		return plan.PhysicalPlan{}, err
   123  	}
   124  
   125  	if r.params.Debug {
   126  		logging.WithContext(ctx, r.instrumentOpts).
   127  			Info("physical plan", zap.String("plan", pp.String()))
   128  	}
   129  
   130  	return pp, nil
   131  }
   132  
   133  func (r *Request) generateExecutionState(ctx context.Context, pp plan.PhysicalPlan) (*ExecutionState, error) {
   134  	sp, ctx := opentracing.StartSpanFromContext(ctx,
   135  		"generate_execution_state")
   136  	defer sp.Finish()
   137  
   138  	state, err := GenerateExecutionState(pp, r.engine.opts.Store(),
   139  		r.fetchOpts, r.instrumentOpts)
   140  	// free up resources
   141  	if err != nil {
   142  		return nil, err
   143  	}
   144  
   145  	if r.params.Debug {
   146  		logging.WithContext(ctx, r.instrumentOpts).
   147  			Info("execution state", zap.String("state", state.String()))
   148  	}
   149  
   150  	return state, nil
   151  }