Skip to content

Commit

Permalink
don't execute any further resolvers after context got cancelled
Browse files Browse the repository at this point in the history
  • Loading branch information
neelance committed Feb 20, 2017
1 parent 644435c commit e8590a1
Showing 1 changed file with 23 additions and 5 deletions.
28 changes: 23 additions & 5 deletions internal/exec/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,10 @@ func ExecuteRequest(ctx context.Context, e *Exec, document *query.Document, oper
return opExec.exec(ctx, r, op.SelSet, e.resolver, serially)
}()

if err := ctx.Err(); err != nil {
return nil, []*errors.QueryError{errors.Errorf("%s", err)}
}

return data, r.errs
}

Expand Down Expand Up @@ -493,7 +497,10 @@ func (e *objectExec) execSelectionSet(ctx context.Context, r *request, selSet *q
}

for name, a := range e.typeAssertions {
out := callWithLimiter(resolver.Method(a.methodIndex), nil, r)
out, err := callWithLimiter(ctx, resolver.Method(a.methodIndex), nil, r)
if err != nil {
return
}
if out[1].Bool() {
addResult(f.Alias, name)
return
Expand Down Expand Up @@ -556,7 +563,10 @@ func (e *objectExec) execFragment(ctx context.Context, r *request, frag *query.F
if !ok {
panic(fmt.Errorf("%q does not implement %q", frag.On, e.name)) // TODO proper error handling
}
out := callWithLimiter(resolver.Method(a.methodIndex), nil, r)
out, err := callWithLimiter(ctx, resolver.Method(a.methodIndex), nil, r)
if err != nil {
return
}
if !out[1].Bool() {
return
}
Expand Down Expand Up @@ -620,18 +630,26 @@ func (e *fieldExec) execField2(ctx context.Context, r *request, f *query.Field,
}

m := resolver.Method(e.methodIndex)
out := callWithLimiter(m, in, r)
out, err := callWithLimiter(ctx, m, in, r)
if err != nil {
return nil, err
}
if e.hasError && !out[1].IsNil() {
return nil, out[1].Interface().(error)
}

return e.valueExec.exec(ctx, r, f.SelSet, out[0], false), nil
}

func callWithLimiter(fn reflect.Value, in []reflect.Value, r *request) []reflect.Value {
func callWithLimiter(ctx context.Context, fn reflect.Value, in []reflect.Value, r *request) ([]reflect.Value, error) {
r.limiter <- struct{}{}
defer func() { <-r.limiter }()
return fn.Call(in)

if err := ctx.Err(); err != nil {
return nil, err // don't execute any more resolvers if context got cancelled
}

return fn.Call(in), nil
}

type typeAssertExec struct {
Expand Down

0 comments on commit e8590a1

Please sign in to comment.