Concurrent Resolvers
main.go
package main
import ( "encoding/json" "fmt" "log"
"github.com/graphql-go/graphql")
type Foo struct { Name string}
var FieldFooType = graphql.NewObject(graphql.ObjectConfig{ Name: "Foo", Fields: graphql.Fields{ "name": &graphql.Field{Type: graphql.String}, },})
type Bar struct { Name string}
var FieldBarType = graphql.NewObject(graphql.ObjectConfig{ Name: "Bar", Fields: graphql.Fields{ "name": &graphql.Field{Type: graphql.String}, },})
// QueryType fields: `concurrentFieldFoo` and `concurrentFieldBar` are resolved// concurrently because they belong to the same field-level and their `Resolve`// function returns a function (thunk).var QueryType = graphql.NewObject(graphql.ObjectConfig{ Name: "Query", Fields: graphql.Fields{ "concurrentFieldFoo": &graphql.Field{ Type: FieldFooType, Resolve: func(p graphql.ResolveParams) (interface{}, error) { var foo = Foo{Name: "Foo's name"} return func() (interface{}, error) { return &foo, nil }, nil }, }, "concurrentFieldBar": &graphql.Field{ Type: FieldBarType, Resolve: func(p graphql.ResolveParams) (interface{}, error) { type result struct { data interface{} err error } ch := make(chan *result, 1) go func() { defer close(ch) bar := &Bar{Name: "Bar's name"} ch <- &result{data: bar, err: nil} }() return func() (interface{}, error) { r := <-ch return r.data, r.err }, nil }, }, },})
func main() { schema, err := graphql.NewSchema(graphql.SchemaConfig{ Query: QueryType, }) if err != nil { log.Fatal(err) } query := ` query { concurrentFieldFoo { name } concurrentFieldBar { name } } ` result := graphql.Do(graphql.Params{ RequestString: query, Schema: schema, }) b, err := json.Marshal(result) if err != nil { log.Fatal(err) } fmt.Printf("%s", b) /* { "data": { "concurrentFieldBar": { "name": "Bar's name" }, "concurrentFieldFoo": { "name": "Foo's name" } } } */}