Skip to content

Commit

Permalink
Merge pull request 99designs#294 from 99designs/simplfy-concurrent-re…
Browse files Browse the repository at this point in the history
…solvers

Simplfy concurrent resolver logic
  • Loading branch information
vektah committed Aug 21, 2018
2 parents 4a8413f + fc01b11 commit 597dda5
Show file tree
Hide file tree
Showing 20 changed files with 3,542 additions and 3,756 deletions.
9 changes: 9 additions & 0 deletions codegen/object.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,15 @@ func (o *Object) HasResolvers() bool {
return false
}

func (o *Object) IsConcurrent() bool {
for _, f := range o.Fields {
if f.IsConcurrent() {
return true
}
}
return false
}

func (f *Field) IsResolver() bool {
return f.GoFieldName == ""
}
Expand Down
6 changes: 3 additions & 3 deletions codegen/templates/data.go

Large diffs are not rendered by default.

66 changes: 23 additions & 43 deletions codegen/templates/field.gotpl
Original file line number Diff line number Diff line change
Expand Up @@ -29,49 +29,29 @@
rawArgs := field.ArgumentMap(ec.Variables)
{{ template "args.gotpl" $field.Args }}
{{- end }}

{{- if $field.IsConcurrent }}
ctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{
Object: {{$object.GQLType|quote}},
Args: {{if $field.Args }}args{{else}}nil{{end}},
Field: field,
})
return graphql.Defer(func() (ret graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
userErr := ec.Recover(ctx, r)
ec.Error(ctx, userErr)
ret = graphql.Null
}
}()
{{ else }}
rctx := graphql.GetResolverContext(ctx)
rctx.Object = {{$object.GQLType|quote}}
rctx.Args = {{if $field.Args }}args{{else}}nil{{end}}
rctx.Field = field
rctx.PushField(field.Alias)
defer rctx.Pop()
{{- end }}
resTmp := ec.FieldMiddleware(ctx, func(ctx context.Context) (interface{}, error) {
{{- if $field.IsResolver }}
return ec.resolvers.{{ $field.ShortInvocation }}
{{- else if $field.IsMethod }}
{{- if $field.NoErr }}
return {{$field.GoReceiverName}}.{{$field.GoFieldName}}({{ $field.CallArgs }}), nil
{{- else }}
return {{$field.GoReceiverName}}.{{$field.GoFieldName}}({{ $field.CallArgs }})
{{- end }}
{{- else if $field.IsVariable }}
return {{$field.GoReceiverName}}.{{$field.GoFieldName}}, nil
rctx := &graphql.ResolverContext{
Object: {{$object.GQLType|quote}},
Args: {{if $field.Args }}args{{else}}nil{{end}},
Field: field,
}
ctx = graphql.WithResolverContext(ctx, rctx)
resTmp := ec.FieldMiddleware(ctx, func(ctx context.Context) (interface{}, error) {
{{- if $field.IsResolver }}
return ec.resolvers.{{ $field.ShortInvocation }}
{{- else if $field.IsMethod }}
{{- if $field.NoErr }}
return {{$field.GoReceiverName}}.{{$field.GoFieldName}}({{ $field.CallArgs }}), nil
{{- else }}
return {{$field.GoReceiverName}}.{{$field.GoFieldName}}({{ $field.CallArgs }})
{{- end }}
})
if resTmp == nil {
return graphql.Null
}
res := resTmp.({{$field.Signature}})
{{ $field.WriteJson }}
{{- if $field.IsConcurrent }}
})
{{- end }}
{{- else if $field.IsVariable }}
return {{$field.GoReceiverName}}.{{$field.GoFieldName}}, nil
{{- end }}
})
if resTmp == nil {
return graphql.Null
}
res := resTmp.({{$field.Signature}})
{{ $field.WriteJson }}
}
{{ end }}
8 changes: 7 additions & 1 deletion codegen/templates/generated.gotpl
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,13 @@ type executionContext struct {
{{ template "input.gotpl" $input }}
{{- end }}

func (ec *executionContext) FieldMiddleware(ctx context.Context, next graphql.Resolver) interface{} {
func (ec *executionContext) FieldMiddleware(ctx context.Context, next graphql.Resolver) (ret interface{}) {
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = nil
}
}()
{{- if .Directives }}
rctx := graphql.GetResolverContext(ctx)
for _, d := range rctx.Field.Definition.Directives {
Expand Down
14 changes: 12 additions & 2 deletions codegen/templates/object.gotpl
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ func (ec *executionContext) _{{$object.GQLType}}(ctx context.Context, sel ast.Se
Object: {{$object.GQLType|quote}},
})
{{end}}

{{if $object.IsConcurrent}} var wg sync.WaitGroup {{end}}
out := graphql.NewOrderedMap(len(fields))
for i, field := range fields {
out.Keys[i] = field.Alias
Expand All @@ -40,13 +42,21 @@ func (ec *executionContext) _{{$object.GQLType}}(ctx context.Context, sel ast.Se
out.Values[i] = graphql.MarshalString({{$object.GQLType|quote}})
{{- range $field := $object.Fields }}
case "{{$field.GQLName}}":
out.Values[i] = ec._{{$object.GQLType}}_{{$field.GQLName}}(ctx, field{{if not $object.Root}}, obj{{end}})
{{- if $field.IsConcurrent }}
wg.Add(1)
go func(i int, field graphql.CollectedField) {
{{- end }}
out.Values[i] = ec._{{$object.GQLType}}_{{$field.GQLName}}(ctx, field{{if not $object.Root}}, obj{{end}})
{{- if $field.IsConcurrent }}
wg.Done()
}(i, field)
{{- end }}
{{- end }}
default:
panic("unknown field " + strconv.Quote(field.Name))
}
}

{{if $object.IsConcurrent}} wg.Wait() {{end}}
return out
}
{{- end }}

0 comments on commit 597dda5

Please sign in to comment.