@@ -10,6 +10,7 @@ import (
1010 "sync/atomic"
1111 "time"
1212
13+ "golang.org/x/net/context"
1314 p "gopkg.in/gorethink/gorethink.v3/ql2"
1415)
1516
@@ -104,7 +105,11 @@ func (c *Connection) Close() error {
104105// Cursor which should be used to view the query's response.
105106//
106107// This function is used internally by Run which should be used for most queries.
107- func (c * Connection ) Query (q Query ) (* Response , * Cursor , error ) {
108+ func (c * Connection ) Query (ctx context.Context , q Query ) (* Response , * Cursor , error ) {
109+ if ctx == nil {
110+ ctx = c .contextFromConnectionOpts ()
111+ }
112+
108113 if c == nil {
109114 return nil , nil , ErrConnectionClosed
110115 }
@@ -131,30 +136,51 @@ func (c *Connection) Query(q Query) (*Response, *Cursor, error) {
131136 }
132137 c .mu .Unlock ()
133138
134- err := c .sendQuery (q )
135- if err != nil {
136- return nil , nil , err
137- }
139+ var response * Response
140+ var cursor * Cursor
141+ var errchan chan error = make (chan error , 1 )
142+ go func () {
143+ err := c .sendQuery (q )
144+ if err != nil {
145+ errchan <- err
146+ return
147+ }
138148
139- if noreply , ok := q .Opts ["noreply" ]; ok && noreply .(bool ) {
140- return nil , nil , nil
141- }
149+ if noreply , ok := q .Opts ["noreply" ]; ok && noreply .(bool ) {
150+ errchan <- nil
151+ return
152+ }
142153
143- for {
144- response , err := c .readResponse ()
145- if err != nil {
146- return nil , nil , err
154+ for {
155+ response , err := c .readResponse ()
156+ if err != nil {
157+ errchan <- err
158+ return
159+ }
160+
161+ if response .Token == q .Token {
162+ // If this was the requested response process and return
163+ response , cursor , err = c .processResponse (ctx , q , response )
164+ errchan <- err
165+ return
166+ } else if _ , ok := c .cursors [response .Token ]; ok {
167+ // If the token is in the cursor cache then process the response
168+ c .processResponse (ctx , q , response )
169+ } else {
170+ putResponse (response )
171+ }
147172 }
173+ }()
148174
149- if response .Token == q .Token {
150- // If this was the requested response process and return
151- return c .processResponse (q , response )
152- } else if _ , ok := c .cursors [response .Token ]; ok {
153- // If the token is in the cursor cache then process the response
154- c .processResponse (q , response )
155- } else {
156- putResponse (response )
175+ select {
176+ case err := <- errchan :
177+ return response , cursor , err
178+ case <- ctx .Done ():
179+ if q .Type != p .Query_STOP {
180+ stopQuery := newStopQuery (q .Token )
181+ c .Query (c .contextFromConnectionOpts (), stopQuery )
157182 }
183+ return nil , nil , ErrQueryTimeout
158184 }
159185}
160186
@@ -167,7 +193,7 @@ type ServerResponse struct {
167193func (c * Connection ) Server () (ServerResponse , error ) {
168194 var response ServerResponse
169195
170- _ , cur , err := c .Query (Query {
196+ _ , cur , err := c .Query (c . contextFromConnectionOpts (), Query {
171197 Type : p .Query_SERVER_INFO ,
172198 })
173199 if err != nil {
@@ -255,7 +281,7 @@ func (c *Connection) readResponse() (*Response, error) {
255281 return response , nil
256282}
257283
258- func (c * Connection ) processResponse (q Query , response * Response ) (* Response , * Cursor , error ) {
284+ func (c * Connection ) processResponse (ctx context. Context , q Query , response * Response ) (* Response , * Cursor , error ) {
259285 switch response .Type {
260286 case p .Response_CLIENT_ERROR :
261287 return c .processErrorResponse (q , response , RQLClientError {rqlServerError {response , q .Term }})
@@ -264,11 +290,11 @@ func (c *Connection) processResponse(q Query, response *Response) (*Response, *C
264290 case p .Response_RUNTIME_ERROR :
265291 return c .processErrorResponse (q , response , createRuntimeError (response .ErrorType , response , q .Term ))
266292 case p .Response_SUCCESS_ATOM , p .Response_SERVER_INFO :
267- return c .processAtomResponse (q , response )
293+ return c .processAtomResponse (ctx , q , response )
268294 case p .Response_SUCCESS_PARTIAL :
269- return c .processPartialResponse (q , response )
295+ return c .processPartialResponse (ctx , q , response )
270296 case p .Response_SUCCESS_SEQUENCE :
271- return c .processSequenceResponse (q , response )
297+ return c .processSequenceResponse (ctx , q , response )
272298 case p .Response_WAIT_COMPLETE :
273299 return c .processWaitResponse (q , response )
274300 default :
@@ -287,17 +313,17 @@ func (c *Connection) processErrorResponse(q Query, response *Response, err error
287313 return response , cursor , err
288314}
289315
290- func (c * Connection ) processAtomResponse (q Query , response * Response ) (* Response , * Cursor , error ) {
316+ func (c * Connection ) processAtomResponse (ctx context. Context , q Query , response * Response ) (* Response , * Cursor , error ) {
291317 // Create cursor
292- cursor := newCursor (c , "Cursor" , response .Token , q .Term , q .Opts )
318+ cursor := newCursor (ctx , c , "Cursor" , response .Token , q .Term , q .Opts )
293319 cursor .profile = response .Profile
294320
295321 cursor .extend (response )
296322
297323 return response , cursor , nil
298324}
299325
300- func (c * Connection ) processPartialResponse (q Query , response * Response ) (* Response , * Cursor , error ) {
326+ func (c * Connection ) processPartialResponse (ctx context. Context , q Query , response * Response ) (* Response , * Cursor , error ) {
301327 cursorType := "Cursor"
302328 if len (response .Notes ) > 0 {
303329 switch response .Notes [0 ] {
@@ -318,7 +344,7 @@ func (c *Connection) processPartialResponse(q Query, response *Response) (*Respo
318344 cursor , ok := c .cursors [response .Token ]
319345 if ! ok {
320346 // Create a new cursor if needed
321- cursor = newCursor (c , cursorType , response .Token , q .Term , q .Opts )
347+ cursor = newCursor (ctx , c , cursorType , response .Token , q .Term , q .Opts )
322348 cursor .profile = response .Profile
323349
324350 c .cursors [response .Token ] = cursor
@@ -330,12 +356,12 @@ func (c *Connection) processPartialResponse(q Query, response *Response) (*Respo
330356 return response , cursor , nil
331357}
332358
333- func (c * Connection ) processSequenceResponse (q Query , response * Response ) (* Response , * Cursor , error ) {
359+ func (c * Connection ) processSequenceResponse (ctx context. Context , q Query , response * Response ) (* Response , * Cursor , error ) {
334360 c .mu .Lock ()
335361 cursor , ok := c .cursors [response .Token ]
336362 if ! ok {
337363 // Create a new cursor if needed
338- cursor = newCursor (c , "Cursor" , response .Token , q .Term , q .Opts )
364+ cursor = newCursor (ctx , c , "Cursor" , response .Token , q .Term , q .Opts )
339365 cursor .profile = response .Profile
340366 }
341367
0 commit comments