@@ -3,148 +3,11 @@ package graphql
3
3
import (
4
4
"context"
5
5
"fmt"
6
- "sync"
7
6
8
7
"github.com/graphql-go/graphql/gqlerrors"
9
8
"github.com/graphql-go/graphql/language/ast"
10
9
)
11
10
12
- // Subscriber subscriber
13
- type Subscriber struct {
14
- message chan interface {}
15
- done chan interface {}
16
- }
17
-
18
- // Message returns the subscriber message channel
19
- func (c * Subscriber ) Message () chan interface {} {
20
- return c .message
21
- }
22
-
23
- // Done returns the subscriber done channel
24
- func (c * Subscriber ) Done () chan interface {} {
25
- return c .done
26
- }
27
-
28
- // NewSubscriber creates a new subscriber
29
- func NewSubscriber (message , done chan interface {}) * Subscriber {
30
- return & Subscriber {
31
- message : message ,
32
- done : done ,
33
- }
34
- }
35
-
36
- // ResultIteratorParams parameters passed to the result iterator handler
37
- type ResultIteratorParams struct {
38
- ResultCount int64 // number of results this iterator has processed
39
- Result * Result // the current result
40
- Done func () // Removes the current handler
41
- Cancel func () // Cancels the iterator, same as iterator.Cancel()
42
- }
43
-
44
- // ResultIteratorFn a result iterator handler
45
- type ResultIteratorFn func (p ResultIteratorParams )
46
-
47
- // holds subscription handler data
48
- type subscriptionHanlderConfig struct {
49
- handler ResultIteratorFn
50
- doneFunc func ()
51
- }
52
-
53
- // ResultIterator handles processing results from a chan *Result
54
- type ResultIterator struct {
55
- currentHandlerID int64
56
- count int64
57
- mx sync.Mutex
58
- ch chan * Result
59
- iterDone chan interface {}
60
- subDone chan interface {}
61
- cancelled bool
62
- handlers map [int64 ]* subscriptionHanlderConfig
63
- }
64
-
65
- func (c * ResultIterator ) incrimentCount () int64 {
66
- c .mx .Lock ()
67
- defer c .mx .Unlock ()
68
- c .count ++
69
- return c .count
70
- }
71
-
72
- // NewResultIterator creates a new iterator and starts handling message on the result channel
73
- func NewResultIterator (subDone chan interface {}, ch chan * Result ) * ResultIterator {
74
- iterator := & ResultIterator {
75
- currentHandlerID : 0 ,
76
- count : 0 ,
77
- iterDone : make (chan interface {}),
78
- subDone : subDone ,
79
- ch : ch ,
80
- cancelled : false ,
81
- handlers : map [int64 ]* subscriptionHanlderConfig {},
82
- }
83
-
84
- go func () {
85
- for {
86
- select {
87
- case <- iterator .iterDone :
88
- subDone <- true
89
- return
90
- case res := <- iterator .ch :
91
- if iterator .cancelled {
92
- return
93
- }
94
-
95
- count := iterator .incrimentCount ()
96
- for _ , h := range iterator .handlers {
97
- h .handler (ResultIteratorParams {
98
- ResultCount : int64 (count ),
99
- Result : res ,
100
- Done : h .doneFunc ,
101
- Cancel : iterator .Cancel ,
102
- })
103
- }
104
- }
105
- }
106
- }()
107
-
108
- return iterator
109
- }
110
-
111
- // adds a new handler
112
- func (c * ResultIterator ) addHandler (handler ResultIteratorFn ) {
113
- c .mx .Lock ()
114
- defer c .mx .Unlock ()
115
-
116
- handlerID := c .currentHandlerID + 1
117
- c .currentHandlerID = handlerID
118
- c .handlers [handlerID ] = & subscriptionHanlderConfig {
119
- handler : handler ,
120
- doneFunc : func () {
121
- c .removeHandler (handlerID )
122
- },
123
- }
124
- }
125
-
126
- // removes a handler and cancels if no more handlers exist
127
- func (c * ResultIterator ) removeHandler (handlerID int64 ) {
128
- c .mx .Lock ()
129
- defer c .mx .Unlock ()
130
-
131
- delete (c .handlers , handlerID )
132
- if len (c .handlers ) == 0 {
133
- c .Cancel ()
134
- }
135
- }
136
-
137
- // ForEach adds a handler and handles each message as they come
138
- func (c * ResultIterator ) ForEach (handler ResultIteratorFn ) {
139
- c .addHandler (handler )
140
- }
141
-
142
- // Cancel cancels the iterator
143
- func (c * ResultIterator ) Cancel () {
144
- c .cancelled = true
145
- c .iterDone <- true
146
- }
147
-
148
11
// SubscribeParams parameters for subscribing
149
12
type SubscribeParams struct {
150
13
Schema Schema
@@ -158,14 +21,8 @@ type SubscribeParams struct {
158
21
}
159
22
160
23
// Subscribe performs a subscribe operation
161
- func Subscribe (p SubscribeParams ) * ResultIterator {
24
+ func Subscribe (ctx context. Context , p SubscribeParams ) chan * Result {
162
25
resultChannel := make (chan * Result )
163
- doneChannel := make (chan interface {})
164
- // Use background context if no context was provided
165
- ctx := p .ContextValue
166
- if ctx == nil {
167
- ctx = context .Background ()
168
- }
169
26
170
27
var mapSourceToResponse = func (payload interface {}) * Result {
171
28
return Execute (ExecuteParams {
@@ -174,18 +31,18 @@ func Subscribe(p SubscribeParams) *ResultIterator {
174
31
AST : p .Document ,
175
32
OperationName : p .OperationName ,
176
33
Args : p .VariableValues ,
177
- Context : ctx ,
34
+ Context : p . ContextValue ,
178
35
})
179
36
}
180
37
181
38
go func () {
182
39
result := & Result {}
183
40
defer func () {
184
41
if err := recover (); err != nil {
185
- fmt .Println ("SUBSCRIPTION RECOVERER" , err )
186
42
result .Errors = append (result .Errors , gqlerrors .FormatError (err .(error )))
43
+ resultChannel <- result
187
44
}
188
- resultChannel <- result
45
+ close ( resultChannel )
189
46
}()
190
47
191
48
exeContext , err := buildExecutionContext (buildExecutionCtxParams {
@@ -195,7 +52,7 @@ func Subscribe(p SubscribeParams) *ResultIterator {
195
52
OperationName : p .OperationName ,
196
53
Args : p .VariableValues ,
197
54
Result : result ,
198
- Context : ctx ,
55
+ Context : p . ContextValue ,
199
56
})
200
57
201
58
if err != nil {
@@ -263,7 +120,7 @@ func Subscribe(p SubscribeParams) *ResultIterator {
263
120
Source : p .RootValue ,
264
121
Args : args ,
265
122
Info : info ,
266
- Context : ctx ,
123
+ Context : p . ContextValue ,
267
124
})
268
125
if err != nil {
269
126
result .Errors = append (result .Errors , gqlerrors .FormatError (err .(error )))
@@ -279,14 +136,14 @@ func Subscribe(p SubscribeParams) *ResultIterator {
279
136
}
280
137
281
138
switch fieldResult .(type ) {
282
- case * Subscriber :
283
- sub := fieldResult .(* Subscriber )
139
+ case chan interface {} :
140
+ sub := fieldResult .(chan interface {} )
284
141
for {
285
142
select {
286
- case <- doneChannel :
287
- sub .done <- true
143
+ case <- ctx .Done ():
288
144
return
289
- case res := <- sub .message :
145
+
146
+ case res := <- sub :
290
147
resultChannel <- mapSourceToResponse (res )
291
148
}
292
149
}
@@ -296,6 +153,6 @@ func Subscribe(p SubscribeParams) *ResultIterator {
296
153
}
297
154
}()
298
155
299
- // return a result iterator
300
- return NewResultIterator ( doneChannel , resultChannel )
156
+ // return a result channel
157
+ return resultChannel
301
158
}
0 commit comments