fieldset.go

 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}