Skip to content

Commit dc57834

Browse files
committed
connection: returing ctx.Cause error in canceled case
Returing wrapped context.Cause(ctx) error in <-ctx.Done() case. Allows compare errors using errors.Is/As. Fixes (#457)
1 parent 6111b79 commit dc57834

File tree

5 files changed

+24
-12
lines changed

5 files changed

+24
-12
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ Versioning](http://semver.org/spec/v2.0.0.html) except to the first release.
1414

1515
### Changed
1616

17-
* Required Go version is `1.24` now (#456).
17+
- Required Go version is `1.24` now (#456).
18+
- Now `connection.newFuture()` in case `<-ctx.Done()` returns wrapped error
19+
provided by `ctx.Cause()`. Allows you compare it using `errors.Is/As` (#457).
1820

1921
### Fixed
2022

connection.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -984,7 +984,8 @@ func (conn *Connection) newFuture(req Request) (fut *Future) {
984984
if ctx != nil {
985985
select {
986986
case <-ctx.Done():
987-
fut.SetError(fmt.Errorf("context is done (request ID %d)", fut.requestId))
987+
fut.SetError(fmt.Errorf("context is done (request ID %d) (%w)",
988+
fut.requestId, context.Cause(ctx)))
988989
shard.rmut.Unlock()
989990
return
990991
default:

errors.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ type ClientError struct {
3131

3232
// Error converts a ClientError to a string.
3333
func (clierr ClientError) Error() string {
34-
return fmt.Sprintf("%s (0x%x)", clierr.Msg, clierr.Code)
34+
return fmt.Sprintf("%s (%#x)", clierr.Msg, clierr.Code)
3535
}
3636

3737
// Temporary returns true if next attempt to perform request may succeeded.
@@ -54,11 +54,12 @@ func (clierr ClientError) Temporary() bool {
5454

5555
// Tarantool client error codes.
5656
const (
57-
ErrConnectionNotReady = 0x4000 + iota
58-
ErrConnectionClosed = 0x4000 + iota
59-
ErrProtocolError = 0x4000 + iota
60-
ErrTimeouted = 0x4000 + iota
61-
ErrRateLimited = 0x4000 + iota
62-
ErrConnectionShutdown = 0x4000 + iota
63-
ErrIoError = 0x4000 + iota
57+
ErrConnectionNotReady uint32 = 0x4000 + iota
58+
ErrConnectionClosed
59+
ErrProtocolError
60+
ErrTimeouted
61+
ErrRateLimited
62+
ErrConnectionShutdown
63+
ErrIoError
64+
ErrCancelledCtx
6465
)

example_test.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package tarantool_test
22

33
import (
44
"context"
5+
"errors"
56
"fmt"
67
"net"
78
"regexp"
@@ -165,9 +166,11 @@ func ExamplePingRequest_Context() {
165166
data, err := conn.Do(req).Get()
166167
fmt.Println("Ping Resp data", data)
167168
fmt.Println("Ping Error", regexp.MustCompile("[0-9]+").ReplaceAllString(err.Error(), "N"))
169+
fmt.Println(errors.Is(err, context.DeadlineExceeded))
168170
// Output:
169171
// Ping Resp data []
170-
// Ping Error context is done (request ID N)
172+
// Ping Error context is done (request ID N) (context deadline exceeded)
173+
// true
171174
}
172175

173176
func ExampleSelectRequest() {

tarantool_test.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package tarantool_test
33
import (
44
"context"
55
"encoding/binary"
6+
"errors"
67
"fmt"
78
"io"
89
"log"
@@ -48,7 +49,8 @@ type Member struct {
4849
Val uint
4950
}
5051

51-
var contextDoneErrRegexp = regexp.MustCompile(`^context is done \(request ID [0-9]+\)$`)
52+
var contextDoneErrRegexp = regexp.MustCompile(
53+
fmt.Sprintf(`^context is done \(request ID [0-9]+\) \(%s\)$`, "context canceled"))
5254

5355
func (m *Member) EncodeMsgpack(e *msgpack.Encoder) error {
5456
if err := e.EncodeArrayLen(2); err != nil {
@@ -2737,6 +2739,8 @@ func TestClientRequestObjectsWithPassedCanceledContext(t *testing.T) {
27372739
if !contextDoneErrRegexp.Match([]byte(err.Error())) {
27382740
t.Fatalf("Failed to catch an error from done context")
27392741
}
2742+
// Checking that we could use errors.Is to get known about error.
2743+
require.True(t, errors.Is(err, context.Canceled))
27402744
if resp != nil {
27412745
t.Fatalf("Response is not nil after the occurred error")
27422746
}
@@ -3298,6 +3302,7 @@ func TestClientIdRequestObjectWithPassedCanceledContext(t *testing.T) {
32983302
resp, err := conn.Do(req).Get()
32993303
require.Nilf(t, resp, "Response is empty")
33003304
require.NotNilf(t, err, "Error is not empty")
3305+
require.True(t, errors.Is(err, context.Canceled))
33013306
require.Regexp(t, contextDoneErrRegexp, err.Error())
33023307
}
33033308

0 commit comments

Comments
 (0)