Skip to content

Commit 6ced96d

Browse files
committed
Proposal to add the context support to API
This patch adds the support of using context in API. The proposed API is based on using request objects. Added tests that cover almost all cases of using the context in a query. Added benchamrk tests are equivalent to other, that use the same query but without any context.
1 parent 017eb2a commit 6ced96d

File tree

6 files changed

+304
-19
lines changed

6 files changed

+304
-19
lines changed

config.lua

+6
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,12 @@ local function simple_incr(a)
110110
end
111111
rawset(_G, 'simple_incr', simple_incr)
112112

113+
local function simple_sleep(a)
114+
require('fiber').sleep(15)
115+
return a + 1
116+
end
117+
rawset(_G, 'simple_sleep', simple_sleep)
118+
113119
box.space.test:truncate()
114120

115121
--box.schema.user.revoke('guest', 'read,write,execute', 'universe')

connection.go

+24-6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package tarantool
55
import (
66
"bufio"
77
"bytes"
8+
"context"
89
"errors"
910
"fmt"
1011
"io"
@@ -877,9 +878,14 @@ func (conn *Connection) nextRequestId() (requestId uint32) {
877878
// Do verifies, sends the request and returns a response.
878879
//
879880
// An error is returned if the request was formed incorrectly, or failure to
880-
// communicate by the connection, or unable to decode the response.
881-
func (conn *Connection) Do(req Request) (*Response, error) {
882-
fut, err := conn.DoAsync(req)
881+
// communicate by the connection, or unable to decode the response, or nil context is passed
882+
// or context is canceled or done.
883+
func (conn *Connection) Do(ctx context.Context, req Request) (*Response, error) {
884+
if ctx == nil {
885+
return nil, errors.New("passed nil context")
886+
}
887+
888+
fut, err := conn.DoAsync(ctx, req)
883889
if err != nil {
884890
return nil, err
885891
}
@@ -890,8 +896,12 @@ func (conn *Connection) Do(req Request) (*Response, error) {
890896
//
891897
// An error is returned if the request was formed incorrectly, or failure to
892898
// communicate by the connection, or unable to decode the response.
893-
func (conn *Connection) DoTyped(req Request, result interface{}) error {
894-
fut, err := conn.DoAsync(req)
899+
func (conn *Connection) DoTyped(ctx context.Context, req Request, result interface{}) error {
900+
if ctx == nil {
901+
return errors.New("passed nil context")
902+
}
903+
904+
fut, err := conn.DoAsync(ctx, req)
895905
if err != nil {
896906
return err
897907
}
@@ -902,12 +912,20 @@ func (conn *Connection) DoTyped(req Request, result interface{}) error {
902912
//
903913
// An error is returned if the request was formed incorrectly, or failure to
904914
// create the future.
905-
func (conn *Connection) DoAsync(req Request) (*Future, error) {
915+
func (conn *Connection) DoAsync(ctx context.Context, req Request) (*Future, error) {
906916
bodyFunc, err := req.BodyFunc(conn.Schema)
907917
if err != nil {
908918
return nil, err
909919
}
910920
future := conn.newFuture(req.Code())
921+
if ctx != nil {
922+
select {
923+
case <-ctx.Done():
924+
return nil, fmt.Errorf("context is done")
925+
default:
926+
future.WithCtx(ctx)
927+
}
928+
}
911929
return future.send(conn, bodyFunc), nil
912930
}
913931

example_test.go

+11-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package tarantool_test
22

33
import (
4+
"context"
45
"fmt"
56
"github.com/tarantool/go-tarantool/test_helpers"
67
"time"
@@ -111,11 +112,12 @@ func ExampleConnection_SelectAsync() {
111112
func ExampleSelectRequest() {
112113
conn := example_connect()
113114
defer conn.Close()
115+
var ctx = context.Background()
114116

115117
req := tarantool.NewSelectRequest(517).
116118
Limit(100).
117119
Key(tarantool.IntKey{1111})
118-
resp, err := conn.Do(req)
120+
resp, err := conn.Do(ctx, req)
119121
if err != nil {
120122
fmt.Printf("error in do select request is %v", err)
121123
return
@@ -126,7 +128,7 @@ func ExampleSelectRequest() {
126128
Index("primary").
127129
Limit(100).
128130
Key(tarantool.IntKey{1111})
129-
fut, err := conn.DoAsync(req)
131+
fut, err := conn.DoAsync(ctx, req)
130132
if err != nil {
131133
fmt.Printf("error in do async select request is %v", err)
132134
}
@@ -144,11 +146,12 @@ func ExampleSelectRequest() {
144146
func ExampleUpdateRequest() {
145147
conn := example_connect()
146148
defer conn.Close()
149+
var ctx = context.Background()
147150

148151
req := tarantool.NewUpdateRequest(517).
149152
Key(tarantool.IntKey{1111}).
150153
Operations(tarantool.NewOperations().Assign(1, "bye"))
151-
resp, err := conn.Do(req)
154+
resp, err := conn.Do(ctx, req)
152155
if err != nil {
153156
fmt.Printf("error in do update request is %v", err)
154157
return
@@ -159,7 +162,7 @@ func ExampleUpdateRequest() {
159162
Index("primary").
160163
Key(tarantool.IntKey{1111}).
161164
Operations(tarantool.NewOperations().Assign(1, "hello"))
162-
fut, err := conn.DoAsync(req)
165+
fut, err := conn.DoAsync(ctx, req)
163166
if err != nil {
164167
fmt.Printf("error in do async update request is %v", err)
165168
}
@@ -177,12 +180,13 @@ func ExampleUpdateRequest() {
177180
func ExampleUpsertRequest() {
178181
conn := example_connect()
179182
defer conn.Close()
183+
var ctx = context.Background()
180184

181185
var req tarantool.Request
182186
req = tarantool.NewUpsertRequest(517).
183187
Tuple([]interface{}{uint(1113), "first", "first"}).
184188
Operations(tarantool.NewOperations().Assign(1, "updated"))
185-
resp, err := conn.Do(req)
189+
resp, err := conn.Do(ctx, req)
186190
if err != nil {
187191
fmt.Printf("error in do select upsert is %v", err)
188192
return
@@ -192,7 +196,7 @@ func ExampleUpsertRequest() {
192196
req = tarantool.NewUpsertRequest("test").
193197
Tuple([]interface{}{uint(1113), "second", "second"}).
194198
Operations(tarantool.NewOperations().Assign(2, "updated"))
195-
fut, err := conn.DoAsync(req)
199+
fut, err := conn.DoAsync(ctx, req)
196200
if err != nil {
197201
fmt.Printf("error in do async upsert request is %v", err)
198202
}
@@ -206,7 +210,7 @@ func ExampleUpsertRequest() {
206210
req = tarantool.NewSelectRequest(517).
207211
Limit(100).
208212
Key(tarantool.IntKey{1113})
209-
resp, err = conn.Do(req)
213+
resp, err = conn.Do(ctx, req)
210214
if err != nil {
211215
fmt.Printf("error in do select request is %v", err)
212216
return

future.go

+19-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package tarantool
22

33
import (
4+
"context"
5+
"fmt"
46
"time"
57

68
"gopkg.in/vmihailenco/msgpack.v2"
@@ -15,6 +17,14 @@ type Future struct {
1517
err error
1618
ready chan struct{}
1719
next *Future
20+
ctx context.Context
21+
}
22+
23+
// WithCtx sets a passed context to Future object and
24+
// returns the same object with that context.
25+
func (fut *Future) WithCtx(ctx context.Context) *Future {
26+
fut.ctx = ctx
27+
return fut
1828
}
1929

2030
// Get waits for Future to be filled and returns Response and error.
@@ -122,5 +132,13 @@ func (fut *Future) wait() {
122132
if fut.ready == nil {
123133
return
124134
}
125-
<-fut.ready
135+
if fut.ctx == nil {
136+
<-fut.ready
137+
return
138+
}
139+
select {
140+
case <-fut.ready:
141+
case <-fut.ctx.Done():
142+
fut.err = fmt.Errorf("context is done")
143+
}
126144
}

request.go

+6
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,12 @@ func (req *SelectRequest) Limit(limit uint32) *SelectRequest {
595595
return req
596596
}
597597

598+
//
599+
//func (req *SelectRequest) WithCtx(ctx *context.Context) *SelectRequest {
600+
// req.ctx = ctx
601+
// return req
602+
//}
603+
598604
// Iterator set the iterator for the select request.
599605
// Note: default value is IterEq.
600606
func (req *SelectRequest) Iterator(iterator uint32) *SelectRequest {

0 commit comments

Comments
 (0)