func queryHandler(w http.ResponseWriter, r *http.Request) { addCorsHeaders(w) if r.Method == "OPTIONS" { return } if r.Method != "POST" { x.SetStatus(w, x.E_INVALID_METHOD, "Invalid method") return } var l query.Latency l.Start = time.Now() defer r.Body.Close() q, err := ioutil.ReadAll(r.Body) if err != nil || len(q) == 0 { x.Err(glog, err).Error("While reading query") x.SetStatus(w, x.E_INVALID_REQUEST, "Invalid request encountered.") return } glog.WithField("q", string(q)).Debug("Query received.") sg, err := gql.Parse(string(q)) if err != nil { x.Err(glog, err).Error("While parsing query") x.SetStatus(w, x.E_INVALID_REQUEST, err.Error()) return } l.Parsing = time.Since(l.Start) glog.WithField("q", string(q)).Debug("Query parsed.") rch := make(chan error) go query.ProcessGraph(sg, rch) err = <-rch if err != nil { x.Err(glog, err).Error("While executing query") x.SetStatus(w, x.E_ERROR, err.Error()) return } l.Processing = time.Since(l.Start) - l.Parsing glog.WithField("q", string(q)).Debug("Graph processed.") js, err := sg.ToJson(&l) if err != nil { x.Err(glog, err).Error("While converting to Json.") x.SetStatus(w, x.E_ERROR, err.Error()) return } glog.WithFields(logrus.Fields{ "total": time.Since(l.Start), "parsing": l.Parsing, "process": l.Processing, "json": l.Json, }).Info("Query Latencies") w.Header().Set("Content-Type", "application/json") fmt.Fprint(w, string(js)) }
// This method is used to execute the query and return the response to the // client as a protocol buffer message. func (s *grpcServer) Query(ctx context.Context, req *graph.Request) (*graph.Response, error) { var allocIds map[string]uint64 if rand.Float64() < *tracing { tr := trace.New("Dgraph", "GrpcQuery") defer tr.Finish() ctx = trace.NewContext(ctx, tr) } resp := new(graph.Response) if len(req.Query) == 0 && req.Mutation == nil { x.TraceError(ctx, x.Errorf("Empty query and mutation.")) return resp, fmt.Errorf("Empty query and mutation.") } var l query.Latency l.Start = time.Now() x.Trace(ctx, "Query received: %v", req.Query) gq, mu, err := gql.Parse(req.Query) if err != nil { x.TraceError(ctx, x.Wrapf(err, "Error while parsing query")) return resp, err } // If mutations are part of the query, we run them through the mutation handler // same as the http client. if mu != nil && (len(mu.Set) > 0 || len(mu.Del) > 0) { if allocIds, err = mutationHandler(ctx, mu); err != nil { x.TraceError(ctx, x.Wrapf(err, "Error while handling mutations")) return resp, err } } // If mutations are sent as part of the mutation object in the request we run // them here. if req.Mutation != nil && (len(req.Mutation.Set) > 0 || len(req.Mutation.Del) > 0) { if allocIds, err = runMutations(ctx, req.Mutation); err != nil { x.TraceError(ctx, x.Wrapf(err, "Error while handling mutations")) return resp, err } } resp.AssignedUids = allocIds if gq == nil || (gq.UID == 0 && len(gq.XID) == 0) { return resp, err } sg, err := query.ToSubGraph(ctx, gq) if err != nil { x.TraceError(ctx, x.Wrapf(err, "Error while conversion to internal format")) return resp, err } l.Parsing = time.Since(l.Start) x.Trace(ctx, "Query parsed") rch := make(chan error) go query.ProcessGraph(ctx, sg, nil, rch) err = <-rch if err != nil { x.TraceError(ctx, x.Wrapf(err, "Error while executing query")) return resp, err } l.Processing = time.Since(l.Start) - l.Parsing x.Trace(ctx, "Graph processed") node, err := sg.ToProtocolBuffer(&l) if err != nil { x.TraceError(ctx, x.Wrapf(err, "Error while converting to ProtocolBuffer")) return resp, err } resp.N = node gl := new(graph.Latency) gl.Parsing, gl.Processing, gl.Pb = l.Parsing.String(), l.Processing.String(), l.ProtocolBuffer.String() resp.L = gl return resp, err }
func queryHandler(w http.ResponseWriter, r *http.Request) { // Add a limit on how many pending queries can be run in the system. pendingQueries <- struct{}{} defer func() { <-pendingQueries }() addCorsHeaders(w) if r.Method == "OPTIONS" { return } if r.Method != "POST" { x.SetStatus(w, x.ErrorInvalidMethod, "Invalid method") return } ctx, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() if rand.Float64() < *tracing { tr := trace.New("Dgraph", "Query") defer tr.Finish() ctx = trace.NewContext(ctx, tr) } var l query.Latency l.Start = time.Now() defer r.Body.Close() req, err := ioutil.ReadAll(r.Body) q := string(req) if err != nil || len(q) == 0 { x.TraceError(ctx, x.Wrapf(err, "Error while reading query")) x.SetStatus(w, x.ErrorInvalidRequest, "Invalid request encountered.") return } x.Trace(ctx, "Query received: %v", q) gq, mu, err := gql.Parse(q) if err != nil { x.TraceError(ctx, x.Wrapf(err, "Error while parsing query")) x.SetStatus(w, x.ErrorInvalidRequest, err.Error()) return } var allocIds map[string]uint64 var allocIdsStr map[string]string // If we have mutations, run them first. if mu != nil && (len(mu.Set) > 0 || len(mu.Del) > 0) { if allocIds, err = mutationHandler(ctx, mu); err != nil { x.TraceError(ctx, x.Wrapf(err, "Error while handling mutations")) x.SetStatus(w, x.Error, err.Error()) return } // convert the new UIDs to hex string. allocIdsStr = make(map[string]string) for k, v := range allocIds { allocIdsStr[k] = fmt.Sprintf("%#x", v) } } if gq == nil || (gq.UID == 0 && gq.Func == nil && len(gq.XID) == 0) { mp := map[string]interface{}{ "code": x.ErrorOk, "message": "Done", "uids": allocIdsStr, } if js, err := json.Marshal(mp); err == nil { w.Write(js) } else { x.SetStatus(w, "Error", "Unable to marshal map") } return } sg, err := query.ToSubGraph(ctx, gq) if err != nil { x.TraceError(ctx, x.Wrapf(err, "Error while conversion o internal format")) x.SetStatus(w, x.ErrorInvalidRequest, err.Error()) return } l.Parsing = time.Since(l.Start) x.Trace(ctx, "Query parsed") rch := make(chan error) go query.ProcessGraph(ctx, sg, nil, rch) err = <-rch if err != nil { x.TraceError(ctx, x.Wrapf(err, "Error while executing query")) x.SetStatus(w, x.Error, err.Error()) return } l.Processing = time.Since(l.Start) - l.Parsing x.Trace(ctx, "Graph processed") if len(*dumpSubgraph) > 0 { x.Checkf(os.MkdirAll(*dumpSubgraph, 0700), *dumpSubgraph) s := time.Now().Format("20060102.150405.000000.gob") filename := path.Join(*dumpSubgraph, s) f, err := os.Create(filename) x.Checkf(err, filename) enc := gob.NewEncoder(f) x.Check(enc.Encode(sg)) x.Checkf(f.Close(), filename) } js, err := sg.ToJSON(&l) if err != nil { x.TraceError(ctx, x.Wrapf(err, "Error while converting to Json")) x.SetStatus(w, x.Error, err.Error()) return } x.Trace(ctx, "Latencies: Total: %v Parsing: %v Process: %v Json: %v", time.Since(l.Start), l.Parsing, l.Processing, l.Json) w.Header().Set("Content-Type", "application/json") w.Write(js) }