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