github.com/99designs/gqlgen@v0.17.45/graphql/fieldset.go (about) 1 package graphql 2 3 import ( 4 "context" 5 "io" 6 "sync" 7 ) 8 9 type FieldSet struct { 10 fields []CollectedField 11 Values []Marshaler 12 Invalids uint32 13 delayed []delayedResult 14 } 15 16 type delayedResult struct { 17 i int 18 f func(context.Context) Marshaler 19 } 20 21 func NewFieldSet(fields []CollectedField) *FieldSet { 22 return &FieldSet{ 23 fields: fields, 24 Values: make([]Marshaler, len(fields)), 25 } 26 } 27 28 func (m *FieldSet) AddField(field CollectedField) { 29 m.fields = append(m.fields, field) 30 m.Values = append(m.Values, nil) 31 } 32 33 func (m *FieldSet) Concurrently(i int, f func(context.Context) Marshaler) { 34 m.delayed = append(m.delayed, delayedResult{i: i, f: f}) 35 } 36 37 func (m *FieldSet) Dispatch(ctx context.Context) { 38 if len(m.delayed) == 1 { 39 // only one concurrent task, no need to spawn a goroutine or deal create waitgroups 40 d := m.delayed[0] 41 m.Values[d.i] = d.f(ctx) 42 } else if len(m.delayed) > 1 { 43 // more than one concurrent task, use the main goroutine to do one, only spawn goroutines for the others 44 45 var wg sync.WaitGroup 46 for _, d := range m.delayed[1:] { 47 wg.Add(1) 48 go func(d delayedResult) { 49 defer wg.Done() 50 m.Values[d.i] = d.f(ctx) 51 }(d) 52 } 53 54 m.Values[m.delayed[0].i] = m.delayed[0].f(ctx) 55 wg.Wait() 56 } 57 } 58 59 func (m *FieldSet) MarshalGQL(writer io.Writer) { 60 writer.Write(openBrace) 61 for i, field := range m.fields { 62 if i != 0 { 63 writer.Write(comma) 64 } 65 writeQuotedString(writer, field.Alias) 66 writer.Write(colon) 67 m.Values[i].MarshalGQL(writer) 68 } 69 writer.Write(closeBrace) 70 }