Пример #1
0
func BenchmarkQuery(b *testing.B) {
	dir1, dir2, ps, clog, err := prepare()
	if err != nil {
		b.Error(err)
		return
	}
	defer closeAll(dir1, dir2, clog)

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		gq, _, err := gql.Parse(q1)
		if err != nil {
			b.Error(err)
			return
		}
		g, err := query.ToSubGraph(gq, ps)
		if err != nil {
			b.Error(err)
			return
		}

		ch := make(chan error)
		go query.ProcessGraph(g, ch, ps)
		if err := <-ch; err != nil {
			b.Error(err)
			return
		}
		var l query.Latency
		_, err = g.ToJson(&l)
		if err != nil {
			b.Error(err)
			return
		}
	}
}
Пример #2
0
func TestQuery(t *testing.T) {
	dir1, dir2, _, err := prepare()
	require.NoError(t, err)
	defer closeAll(dir1, dir2)

	// Parse GQL into internal query representation.
	gq, _, err := gql.Parse(q0)
	require.NoError(t, err)

	ctx := context.Background()
	g, err := query.ToSubGraph(ctx, gq)
	require.NoError(t, err)

	// Test internal query representation.
	require.EqualValues(t, childAttrs(g), []string{"follows", "_xid_", "status"})
	require.EqualValues(t, childAttrs(g.Children[0]), []string{"_xid_", "status"})

	ch := make(chan error)
	go query.ProcessGraph(ctx, g, nil, ch)
	err = <-ch
	require.NoError(t, err)

	var l query.Latency
	js, err := g.ToJSON(&l)
	require.NoError(t, err)
	fmt.Println(string(js))
}
Пример #3
0
func BenchmarkQuery(b *testing.B) {
	dir1, dir2, _, err := prepare()
	if err != nil {
		b.Error(err)
		return
	}
	defer closeAll(dir1, dir2)

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		gq, _, err := gql.Parse(q1)
		if err != nil {
			b.Error(err)
			return
		}
		ctx := context.Background()
		g, err := query.ToSubGraph(ctx, gq)
		if err != nil {
			b.Error(err)
			return
		}

		ch := make(chan error)
		go query.ProcessGraph(ctx, g, nil, ch)
		if err := <-ch; err != nil {
			b.Error(err)
			return
		}
		var l query.Latency
		_, err = g.ToJSON(&l)
		if err != nil {
			b.Error(err)
			return
		}
	}
}
Пример #4
0
func TestQuery(t *testing.T) {
	dir1, dir2, ps, clog, err := prepare()
	if err != nil {
		t.Error(err)
		return
	}
	defer closeAll(dir1, dir2, clog)

	// Parse GQL into internal query representation.
	gq, _, err := gql.Parse(q0)
	if err != nil {
		t.Error(err)
		return
	}
	g, err := query.ToSubGraph(gq, ps)
	if err != nil {
		t.Error(err)
		return
	}

	// Test internal query representation.
	if len(g.Children) != 3 {
		t.Errorf("Expected 3 children. Got: %v", len(g.Children))
	}

	{
		child := g.Children[0]
		if child.Attr != "follows" {
			t.Errorf("Expected follows. Got: %q", child.Attr)
		}
		if len(child.Children) != 2 {
			t.Errorf("Expected 2 child. Got: %v", len(child.Children))
		}
		gc := child.Children[0]
		if gc.Attr != "_xid_" {
			t.Errorf("Expected _xid_. Got: %q", gc.Attr)
		}
		gc = child.Children[1]
		if gc.Attr != "status" {
			t.Errorf("Expected status. Got: %q", gc.Attr)
		}
	}

	{
		child := g.Children[1]
		if child.Attr != "_xid_" {
			t.Errorf("Expected _xid_. Got: %q", child.Attr)
		}
	}

	{
		child := g.Children[2]
		if child.Attr != "status" {
			t.Errorf("Expected status. Got: %q", child.Attr)
		}
	}

	ch := make(chan error)
	go query.ProcessGraph(g, ch, ps)
	if err := <-ch; err != nil {
		t.Error(err)
		return
	}
	var l query.Latency
	js, err := g.ToJson(&l)
	if err != nil {
		t.Error(err)
		return
	}
	fmt.Println(string(js))
}
Пример #5
0
// 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
}
Пример #6
0
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)
}
Пример #7
0
func queryHandler(ps *store.Store) http.HandlerFunc {
	return func(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.")
		gq, _, 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
		}
		sg, err := query.ToSubGraph(gq, ps)
		if err != nil {
			x.Err(glog, err).Error("While conversion to internal format")
			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, ps)
		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))
	}
}