Repository: dgraph-io/dgraph
File: worker/task.go (Go)

Code before:
				"handleUidPostings", srcFn.n, len(q.UidList.GetUids()), srcFn)
		}
	}

	// Divide the task into many goroutines.
	numGo, width := x.DivideAndRule(srcFn.n)
	x.AssertTrue(width > 0)
	span.AddEvent("Processing distribution", trace.WithAttributes(
		attribute.Int("width", width),
		attribute.Int("numGo", numGo)))

	lang := langForFunc(q.Langs)
	needFiltering := needsStringFiltering(srcFn, q.Langs, q.Attr)
	isList := schema.State().IsList(q.Attr)

	outputs := make([]*pb.Result, numGo)

	eg, egCtx := errgroup.WithContext(ctx)
	calculate := func(start, end int) error {
		x.AssertTrue(start%width == 0)
		out := &pb.Result{}
		outputs[start/width] = out

		for i := start; i < end; i++ {
			select {
			case <-egCtx.Done():
				return egCtx.Err()
			default:
			}
			if i%100 == 0 {
				select {
				case <-ctx.Done():
					return ctx.Err()
				default:
				}
			}
			var key []byte
			switch srcFn.fnType {
			case notAFunction, compareScalarFn, hasFn, uidInFn:
				if q.Reverse {
					key = x.ReverseKey(q.Attr, q.UidList.Uids[i])
				} else {
					key = x.DataKey(q.Attr, q.UidList.Uids[i])
				}
			case geoFn, regexFn, fullTextSearchFn, standardFn, customIndexFn, matchFn,
				compareAttrFn:
				key = x.IndexKey(q.Attr, srcFn.tokens[i])
			default:
				return errors.Errorf("Unhandled function in handleUidPostings: %s", srcFn.fname)
			}


Review comment (performance):
This check is redundant, no? Because egCtx is derived from ctx. If ctx is closed then the check on line 814 is never reached because the egCtx is closed too.

The check every 100 iterations was most likely for performance reasons. What do you think about the replacing the ctx.Done() check on like 814 with a check of egCtx? (and removing the 807-811)

Altho it probably doesn't have similar performance implications, I see you committed a similar change six months ago to the filterGeoFunction.

Code after:
func (qs *queryState) handleUidPostings(
	ctx context.Context, args funcArgs, opts posting.ListOptions) error {
	srcFn := args.srcFn
	q := args.q

	facetsTree, err := preprocessFilter(q.FacetsFilter)
	if err != nil {
		return err
	}

	span := trace.SpanFromContext(ctx)
	stop := x.SpanTimer(span, "handleUidPostings")
	defer stop()
	span.AddEvent("Number of uids and args.srcFn", trace.WithAttributes(
		attribute.Int64("uids_count", int64(srcFn.n)),
		attribute.String("srcFn", x.SafeUTF8(fmt.Sprintf("%+v", args.srcFn)))))
	if srcFn.n == 0 {
		return nil
	}

	// srcFn.n should be equal to len(q.UidList.Uids) for below implementation(DivideAndRule and
	// calculate) to work correctly. But we have seen some panics while forming DataKey in
	// calculate(). panic is of the form "index out of range [4] with length 1". Hence return error
	// from here when srcFn.n != len(q.UidList.Uids).
	switch srcFn.fnType {
	case notAFunction, compareScalarFn, hasFn, uidInFn:
		if srcFn.n != len(q.UidList.GetUids()) {
			return errors.Errorf("srcFn.n: %d is not equal to len(q.UidList.Uids): %d, srcFn: %+v in "+
				"handleUidPostings", srcFn.n, len(q.UidList.GetUids()), srcFn)
		}
	}

	// Divide the task into many goroutines.
	numGo, width := x.DivideAndRule(srcFn.n)
	x.AssertTrue(width > 0)
	span.AddEvent("Processing distribution", trace.WithAttributes(
		attribute.Int("width", width),
		attribute.Int("numGo", numGo)))

	lang := langForFunc(q.Langs)
	needFiltering := needsStringFiltering(srcFn, q.Langs, q.Attr)
	isList := schema.State().IsList(q.Attr)

	outputs := make([]*pb.Result, numGo)

	eg, egCtx := errgroup.WithContext(ctx)
	calculate := func(start, end int) error {
		x.AssertTrue(start%width == 0)
		out := &pb.Result{}
		outputs[start/width] = out