Skip to content

Commit ef470e3

Browse files
committed
api: change Response type to interface
This commit creates a new `Response` interface. But still, only one `Response` implementation exists: `ConnResponse`. Custom responses (including mocks) are expected to implement this interface. Create a `Response` interface and its implementation `ConnResponse`. For the `Future` method `Get` now returns response data. To get the actual response new method `GetResponse` is added. `IsPush()` method is added to the response iterator. It returns the information if the current response is a `Push`. Right now it does not have a lot of usage, but it will be crucial once we create a separate response for pushes. Part of #237
1 parent 7d73f6a commit ef470e3

38 files changed

+1373
-1603
lines changed

CHANGELOG.md

+8
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ Versioning](http://semver.org/spec/v2.0.0.html) except to the first release.
2828
in requests instead of their IDs.
2929
- `GetSchema` function to get the actual schema (#7)
3030
- Support connection via an existing socket fd (#321)
31+
- `Header` struct for the response header (#237). It can be accessed via
32+
`Header()` method of the `Response` interface.
3133

3234
### Changed
3335

@@ -67,6 +69,12 @@ Versioning](http://semver.org/spec/v2.0.0.html) except to the first release.
6769
it (#321)
6870
- Rename `pool.GetPoolInfo` to `pool.GetInfo`. Change return type to
6971
`map[string]ConnectionInfo` (#321)
72+
- All responses are now implementations of an `Response` interface (#237)
73+
- `IsPush()` method is added to the response iterator (#237). It returns
74+
the information if the current response is a `PushResponse`.
75+
`PushCode` constant is removed.
76+
- Method `Get` for `Future` now returns response data (#237). To get the actual
77+
response new method added `GetResponse`.
7078

7179
### Deprecated
7280

README.md

+20-3
Original file line numberDiff line numberDiff line change
@@ -128,12 +128,13 @@ func main() {
128128
if err != nil {
129129
fmt.Println("Connection refused:", err)
130130
}
131-
resp, err := conn.Do(tarantool.NewInsertRequest(999).
131+
data, err := conn.Do(tarantool.NewInsertRequest(999).
132132
Tuple([]interface{}{99999, "BB"}),
133133
).Get()
134134
if err != nil {
135135
fmt.Println("Error", err)
136-
fmt.Println("Code", resp.Code)
136+
} else {
137+
fmt.Printf("Data: %v", data)
137138
}
138139
}
139140
```
@@ -241,7 +242,10 @@ of the requests is an array instead of array of arrays.
241242

242243
#### IPROTO constants
243244

244-
IPROTO constants have been moved to a separate package [go-iproto](https://github.com/tarantool/go-iproto).
245+
* IPROTO constants have been moved to a separate package [go-iproto](https://github.com/tarantool/go-iproto).
246+
* `PushCode` constant is removed. To get information, if the current response is
247+
a push response, new `IsPush()` method of the response iterator could be used
248+
instead.
245249

246250
#### Request changes
247251

@@ -255,6 +259,19 @@ needs to be passed instead.
255259
* `UpdateRequest` and `UpsertRequest` structs no longer accept `interface{}`
256260
for an `ops` field. `*Operations` needs to be used instead.
257261

262+
#### Response changes
263+
264+
* New interface `Response` added.
265+
* Response header stored in a new `Header` struct. It could be accessed via
266+
`Header()` method.
267+
* Method `IsPush()` is added to the `ResponseIterator` interface.
268+
It returns true if the current response is a push response.
269+
270+
#### Future changes
271+
272+
* Method `Get` now returns response data instead of the actual response.
273+
* New method `GetResponse` added to get an actual response.
274+
258275
#### Connect function
259276

260277
`connection.Connect` no longer return non-working connection objects. This function

box_error_test.go

+11-7
Original file line numberDiff line numberDiff line change
@@ -306,9 +306,11 @@ func TestErrorTypeEval(t *testing.T) {
306306
t.Run(name, func(t *testing.T) {
307307
resp, err := conn.Eval("return ...", []interface{}{&testcase.tuple.val})
308308
require.Nil(t, err)
309-
require.NotNil(t, resp.Data)
310-
require.Equal(t, len(resp.Data), 1)
311-
actual, ok := resp.Data[0].(*BoxError)
309+
data, err := resp.Decode()
310+
require.Nil(t, err)
311+
require.NotNil(t, data)
312+
require.Equal(t, len(data), 1)
313+
actual, ok := data[0].(*BoxError)
312314
require.Truef(t, ok, "Response data has valid type")
313315
require.Equal(t, testcase.tuple.val, *actual)
314316
})
@@ -436,15 +438,17 @@ func TestErrorTypeSelect(t *testing.T) {
436438
_, err := conn.Eval(insertEval, []interface{}{})
437439
require.Nilf(t, err, "Tuple has been successfully inserted")
438440

439-
var resp *Response
441+
var resp Response
440442
var offset uint32 = 0
441443
var limit uint32 = 1
442444
resp, err = conn.Select(space, index, offset, limit, IterEq,
443445
[]interface{}{testcase.tuple.pk})
444446
require.Nil(t, err)
445-
require.NotNil(t, resp.Data)
446-
require.Equalf(t, len(resp.Data), 1, "Exactly one tuple had been found")
447-
tpl, ok := resp.Data[0].([]interface{})
447+
data, err := resp.Decode()
448+
require.Nil(t, err)
449+
require.NotNil(t, data)
450+
require.Equalf(t, len(data), 1, "Exactly one tuple had been found")
451+
tpl, ok := data[0].([]interface{})
448452
require.Truef(t, ok, "Tuple has valid type")
449453
require.Equal(t, testcase.tuple.pk, tpl[0])
450454
actual, ok := tpl[1].(*BoxError)

connection.go

+12-14
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,9 @@ func (d defaultLogger) Report(event ConnLogKind, conn *Connection, v ...interfac
9797
log.Printf("tarantool: last reconnect to %s failed: %s, giving it up",
9898
conn.Addr(), err)
9999
case LogUnexpectedResultId:
100-
resp := v[0].(*Response)
100+
header := v[0].(Header)
101101
log.Printf("tarantool: connection %s got unexpected resultId (%d) in response",
102-
conn.Addr(), resp.RequestId)
102+
conn.Addr(), header.RequestId)
103103
case LogWatchEventReadFailed:
104104
err := v[0].(error)
105105
log.Printf("tarantool: unable to parse watch event: %s", err)
@@ -807,8 +807,8 @@ func (conn *Connection) reader(r io.Reader, c Conn) {
807807
conn.reconnect(err, c)
808808
return
809809
}
810-
resp := &Response{buf: smallBuf{b: respBytes}}
811-
err = resp.decodeHeader(conn.dec)
810+
buf := smallBuf{b: respBytes}
811+
header, err := decodeHeader(conn.dec, &buf)
812812
if err != nil {
813813
err = ClientError{
814814
ErrProtocolError,
@@ -818,8 +818,9 @@ func (conn *Connection) reader(r io.Reader, c Conn) {
818818
return
819819
}
820820

821+
resp := &ConnResponse{header: header, buf: buf}
821822
var fut *Future = nil
822-
if iproto.Type(resp.Code) == iproto.IPROTO_EVENT {
823+
if iproto.Type(header.Code) == iproto.IPROTO_EVENT {
823824
if event, err := readWatchEvent(&resp.buf); err == nil {
824825
events <- event
825826
} else {
@@ -830,19 +831,19 @@ func (conn *Connection) reader(r io.Reader, c Conn) {
830831
conn.opts.Logger.Report(LogWatchEventReadFailed, conn, err)
831832
}
832833
continue
833-
} else if resp.Code == PushCode {
834-
if fut = conn.peekFuture(resp.RequestId); fut != nil {
834+
} else if header.Code == uint32(iproto.IPROTO_CHUNK) {
835+
if fut = conn.peekFuture(header.RequestId); fut != nil {
835836
fut.AppendPush(resp)
836837
}
837838
} else {
838-
if fut = conn.fetchFuture(resp.RequestId); fut != nil {
839+
if fut = conn.fetchFuture(header.RequestId); fut != nil {
839840
fut.SetResponse(resp)
840841
conn.markDone(fut)
841842
}
842843
}
843844

844845
if fut == nil {
845-
conn.opts.Logger.Report(LogUnexpectedResultId, conn, resp)
846+
conn.opts.Logger.Report(LogUnexpectedResultId, conn, header)
846847
}
847848
}
848849
}
@@ -1052,10 +1053,7 @@ func (conn *Connection) putFuture(fut *Future, req Request, streamId uint64) {
10521053

10531054
if req.Async() {
10541055
if fut = conn.fetchFuture(reqid); fut != nil {
1055-
resp := &Response{
1056-
RequestId: reqid,
1057-
Code: OkCode,
1058-
}
1056+
resp := &ConnResponse{}
10591057
fut.SetResponse(resp)
10601058
conn.markDone(fut)
10611059
}
@@ -1236,7 +1234,7 @@ func (conn *Connection) SetSchema(s Schema) {
12361234
// NewPrepared passes a sql statement to Tarantool for preparation synchronously.
12371235
func (conn *Connection) NewPrepared(expr string) (*Prepared, error) {
12381236
req := NewPrepareRequest(expr)
1239-
resp, err := conn.Do(req).Get()
1237+
resp, err := conn.Do(req).GetResponse()
12401238
if err != nil {
12411239
return nil, err
12421240
}

connector.go

+12-12
Original file line numberDiff line numberDiff line change
@@ -13,41 +13,41 @@ type Connector interface {
1313

1414
// Deprecated: the method will be removed in the next major version,
1515
// use a PingRequest object + Do() instead.
16-
Ping() (*Response, error)
16+
Ping() (Response, error)
1717
// Deprecated: the method will be removed in the next major version,
1818
// use a SelectRequest object + Do() instead.
1919
Select(space, index interface{}, offset, limit uint32, iterator Iter,
20-
key interface{}) (*Response, error)
20+
key interface{}) (Response, error)
2121
// Deprecated: the method will be removed in the next major version,
2222
// use an InsertRequest object + Do() instead.
23-
Insert(space interface{}, tuple interface{}) (*Response, error)
23+
Insert(space interface{}, tuple interface{}) (Response, error)
2424
// Deprecated: the method will be removed in the next major version,
2525
// use a ReplicaRequest object + Do() instead.
26-
Replace(space interface{}, tuple interface{}) (*Response, error)
26+
Replace(space interface{}, tuple interface{}) (Response, error)
2727
// Deprecated: the method will be removed in the next major version,
2828
// use a DeleteRequest object + Do() instead.
29-
Delete(space, index interface{}, key interface{}) (*Response, error)
29+
Delete(space, index interface{}, key interface{}) (Response, error)
3030
// Deprecated: the method will be removed in the next major version,
3131
// use a UpdateRequest object + Do() instead.
32-
Update(space, index interface{}, key interface{}, ops *Operations) (*Response, error)
32+
Update(space, index interface{}, key interface{}, ops *Operations) (Response, error)
3333
// Deprecated: the method will be removed in the next major version,
3434
// use a UpsertRequest object + Do() instead.
35-
Upsert(space interface{}, tuple interface{}, ops *Operations) (*Response, error)
35+
Upsert(space interface{}, tuple interface{}, ops *Operations) (Response, error)
3636
// Deprecated: the method will be removed in the next major version,
3737
// use a CallRequest object + Do() instead.
38-
Call(functionName string, args interface{}) (*Response, error)
38+
Call(functionName string, args interface{}) (Response, error)
3939
// Deprecated: the method will be removed in the next major version,
4040
// use a Call16Request object + Do() instead.
41-
Call16(functionName string, args interface{}) (*Response, error)
41+
Call16(functionName string, args interface{}) (Response, error)
4242
// Deprecated: the method will be removed in the next major version,
4343
// use a Call17Request object + Do() instead.
44-
Call17(functionName string, args interface{}) (*Response, error)
44+
Call17(functionName string, args interface{}) (Response, error)
4545
// Deprecated: the method will be removed in the next major version,
4646
// use an EvalRequest object + Do() instead.
47-
Eval(expr string, args interface{}) (*Response, error)
47+
Eval(expr string, args interface{}) (Response, error)
4848
// Deprecated: the method will be removed in the next major version,
4949
// use an ExecuteRequest object + Do() instead.
50-
Execute(expr string, args interface{}) (*Response, error)
50+
Execute(expr string, args interface{}) (Response, error)
5151

5252
// Deprecated: the method will be removed in the next major version,
5353
// use a SelectRequest object + Do() instead.

const.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,5 @@ const (
99
)
1010

1111
const (
12-
OkCode = uint32(iproto.IPROTO_OK)
13-
PushCode = uint32(iproto.IPROTO_CHUNK)
12+
OkCode = uint32(iproto.IPROTO_OK)
1413
)

crud/tarantool_test.go

+28-35
Original file line numberDiff line numberDiff line change
@@ -517,39 +517,32 @@ func testSelectGeneratedData(t *testing.T, conn tarantool.Connector,
517517
Limit(20).
518518
Iterator(tarantool.IterGe).
519519
Key([]interface{}{uint(1010)})
520-
resp, err := conn.Do(req).Get()
520+
data, err := conn.Do(req).Get()
521521
if err != nil {
522522
t.Fatalf("Failed to Select: %s", err.Error())
523523
}
524-
if resp == nil {
525-
t.Fatalf("Response is nil after Select")
526-
}
527-
if len(resp.Data) != expectedTuplesCount {
528-
t.Fatalf("Response Data len %d != %d", len(resp.Data), expectedTuplesCount)
524+
if len(data) != expectedTuplesCount {
525+
t.Fatalf("Response Data len %d != %d", len(data), expectedTuplesCount)
529526
}
530527
}
531528

532529
func testCrudRequestCheck(t *testing.T, req tarantool.Request,
533-
resp *tarantool.Response, err error, expectedLen int) {
530+
data []interface{}, err error, expectedLen int) {
534531
t.Helper()
535532

536533
if err != nil {
537534
t.Fatalf("Failed to Do CRUD request: %s", err.Error())
538535
}
539536

540-
if resp == nil {
541-
t.Fatalf("Response is nil after Do CRUD request")
542-
}
543-
544-
if len(resp.Data) < expectedLen {
537+
if len(data) < expectedLen {
545538
t.Fatalf("Response Body len < %#v, actual len %#v",
546-
expectedLen, len(resp.Data))
539+
expectedLen, len(data))
547540
}
548541

549542
// resp.Data[0] - CRUD res.
550543
// resp.Data[1] - CRUD err.
551-
if expectedLen >= 2 && resp.Data[1] != nil {
552-
if crudErr, err := getCrudError(req, resp.Data[1]); err != nil {
544+
if expectedLen >= 2 && data[1] != nil {
545+
if crudErr, err := getCrudError(req, data[1]); err != nil {
553546
t.Fatalf("Failed to get CRUD error: %#v", err)
554547
} else if crudErr != nil {
555548
t.Fatalf("Failed to perform CRUD request on CRUD side: %#v", crudErr)
@@ -569,8 +562,8 @@ func TestCrudGenerateData(t *testing.T) {
569562
conn.Do(req).Get()
570563
}
571564

572-
resp, err := conn.Do(testCase.req).Get()
573-
testCrudRequestCheck(t, testCase.req, resp,
565+
data, err := conn.Do(testCase.req).Get()
566+
testCrudRequestCheck(t, testCase.req, data,
574567
err, testCase.expectedRespLen)
575568

576569
testSelectGeneratedData(t, conn, testCase.expectedTuplesCount)
@@ -591,8 +584,8 @@ func TestCrudProcessData(t *testing.T) {
591584
for _, testCase := range testProcessDataCases {
592585
t.Run(testCase.name, func(t *testing.T) {
593586
testCrudRequestPrepareData(t, conn)
594-
resp, err := conn.Do(testCase.req).Get()
595-
testCrudRequestCheck(t, testCase.req, resp,
587+
data, err := conn.Do(testCase.req).Get()
588+
testCrudRequestCheck(t, testCase.req, data,
596589
err, testCase.expectedRespLen)
597590
for i := 1010; i < 1020; i++ {
598591
req := tarantool.NewDeleteRequest(spaceName).
@@ -623,8 +616,8 @@ func TestCrudUpdateSplice(t *testing.T) {
623616
Opts(simpleOperationOpts)
624617

625618
testCrudRequestPrepareData(t, conn)
626-
resp, err := conn.Do(req).Get()
627-
testCrudRequestCheck(t, req, resp,
619+
data, err := conn.Do(req).Get()
620+
testCrudRequestCheck(t, req, data,
628621
err, 2)
629622
}
630623

@@ -648,8 +641,8 @@ func TestCrudUpsertSplice(t *testing.T) {
648641
Opts(simpleOperationOpts)
649642

650643
testCrudRequestPrepareData(t, conn)
651-
resp, err := conn.Do(req).Get()
652-
testCrudRequestCheck(t, req, resp,
644+
data, err := conn.Do(req).Get()
645+
testCrudRequestCheck(t, req, data,
653646
err, 2)
654647
}
655648

@@ -673,8 +666,8 @@ func TestCrudUpsertObjectSplice(t *testing.T) {
673666
Opts(simpleOperationOpts)
674667

675668
testCrudRequestPrepareData(t, conn)
676-
resp, err := conn.Do(req).Get()
677-
testCrudRequestCheck(t, req, resp,
669+
data, err := conn.Do(req).Get()
670+
testCrudRequestCheck(t, req, data,
678671
err, 2)
679672
}
680673

@@ -719,11 +712,11 @@ func TestUnflattenRows(t *testing.T) {
719712
req := crud.MakeReplaceRequest(spaceName).
720713
Tuple(tuple).
721714
Opts(simpleOperationOpts)
722-
resp, err := conn.Do(req).Get()
723-
testCrudRequestCheck(t, req, resp, err, 2)
715+
data, err := conn.Do(req).Get()
716+
testCrudRequestCheck(t, req, data, err, 2)
724717

725-
if res, ok = resp.Data[0].(map[interface{}]interface{}); !ok {
726-
t.Fatalf("Unexpected CRUD result: %#v", resp.Data[0])
718+
if res, ok = data[0].(map[interface{}]interface{}); !ok {
719+
t.Fatalf("Unexpected CRUD result: %#v", data[0])
727720
}
728721

729722
if rawMetadata, ok := res["metadata"]; !ok {
@@ -1293,21 +1286,21 @@ func TestNoreturnOption(t *testing.T) {
12931286
conn.Do(req).Get()
12941287
}
12951288

1296-
resp, err := conn.Do(testCase.req).Get()
1289+
data, err := conn.Do(testCase.req).Get()
12971290
if err != nil {
12981291
t.Fatalf("Failed to Do CRUD request: %s", err)
12991292
}
13001293

1301-
if len(resp.Data) == 0 {
1294+
if len(data) == 0 {
13021295
t.Fatalf("Expected explicit nil")
13031296
}
13041297

1305-
if resp.Data[0] != nil {
1306-
t.Fatalf("Expected nil result, got %v", resp.Data[0])
1298+
if data[0] != nil {
1299+
t.Fatalf("Expected nil result, got %v", data[0])
13071300
}
13081301

1309-
if len(resp.Data) >= 2 && resp.Data[1] != nil {
1310-
t.Fatalf("Expected no returned errors, got %v", resp.Data[1])
1302+
if len(data) >= 2 && data[1] != nil {
1303+
t.Fatalf("Expected no returned errors, got %v", data[1])
13111304
}
13121305

13131306
for i := 1010; i < 1020; i++ {

0 commit comments

Comments
 (0)