From 7aa279ebde561ad28ab9635a607ca4cd2d9d2064 Mon Sep 17 00:00:00 2001 From: Max Maximov Date: Mon, 29 Sep 2025 23:04:21 +0400 Subject: [PATCH] fix: use wrapped context err when <-ctx.Done() case is executed --- CHANGELOG.md | 2 ++ connection.go | 10 ++++++++-- example_test.go | 4 ++-- tarantool_test.go | 14 +++++++------- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e536967..b4aa48bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ Versioning](http://semver.org/spec/v2.0.0.html) except to the first release. ### Fixed +- Use wrapped context err when <-ctx.Done() case is executed + ## [v2.4.0] - 2025-07-11 This release focuses on adding schema/user/session operations, synchronous transaction diff --git a/connection.go b/connection.go index 5f976fbf..caa93b19 100644 --- a/connection.go +++ b/connection.go @@ -984,7 +984,10 @@ func (conn *Connection) newFuture(req Request) (fut *Future) { if ctx != nil { select { case <-ctx.Done(): - fut.SetError(fmt.Errorf("context is done (request ID %d)", fut.requestId)) + fut.SetError(fmt.Errorf( + "context is done (request ID %d): %w", + fut.requestId, context.Cause(ctx), + )) shard.rmut.Unlock() return default: @@ -1026,7 +1029,10 @@ func (conn *Connection) contextWatchdog(fut *Future, ctx context.Context) { case <-fut.done: return default: - conn.cancelFuture(fut, fmt.Errorf("context is done (request ID %d)", fut.requestId)) + conn.cancelFuture(fut, fmt.Errorf( + "context is done (request ID %d): %w", + fut.requestId, context.Cause(ctx), + )) } } diff --git a/example_test.go b/example_test.go index 463f3289..4f462bbf 100644 --- a/example_test.go +++ b/example_test.go @@ -16,7 +16,7 @@ import ( type Tuple struct { // Instruct msgpack to pack this struct as array, so no custom packer // is needed. - _msgpack struct{} `msgpack:",asArray"` //nolint: structcheck,unused + _msgpack struct{} `msgpack:",asArray"` // nolint: structcheck,unused Id uint Msg string Name string @@ -167,7 +167,7 @@ func ExamplePingRequest_Context() { fmt.Println("Ping Error", regexp.MustCompile("[0-9]+").ReplaceAllString(err.Error(), "N")) // Output: // Ping Resp data [] - // Ping Error context is done (request ID N) + // Ping Error context is done (request ID N): context deadline exceeded } func ExampleSelectRequest() { diff --git a/tarantool_test.go b/tarantool_test.go index 4902e96f..005252d7 100644 --- a/tarantool_test.go +++ b/tarantool_test.go @@ -48,7 +48,7 @@ type Member struct { Val uint } -var contextDoneErrRegexp = regexp.MustCompile(`^context is done \(request ID [0-9]+\)$`) +var contextDoneErrRegexp = regexp.MustCompile(`^context is done \(request ID [0-9]+\):.+$`) func (m *Member) EncodeMsgpack(e *msgpack.Encoder) error { if err := e.EncodeArrayLen(2); err != nil { @@ -89,8 +89,8 @@ var indexNo = uint32(0) var indexName = "primary" var opts = Opts{ Timeout: 5 * time.Second, - //Concurrency: 32, - //RateLimit: 4*1024, + // Concurrency: 32, + // RateLimit: 4*1024, } const N = 500 @@ -888,7 +888,7 @@ func TestFutureMultipleGetTypedWithError(t *testing.T) { } } -/////////////////// +// ///////////////// func TestClient(t *testing.T) { var err error @@ -2716,7 +2716,7 @@ func TestCallRequest(t *testing.T) { func TestClientRequestObjectsWithNilContext(t *testing.T) { conn := test_helpers.ConnectWithValidation(t, dialer, opts) defer conn.Close() - req := NewPingRequest().Context(nil) //nolint + req := NewPingRequest().Context(nil) // nolint data, err := conn.Do(req).Get() if err != nil { t.Fatalf("Failed to Ping: %s", err) @@ -3269,7 +3269,7 @@ func TestClientIdRequestObjectWithNilContext(t *testing.T) { req := NewIdRequest(ProtocolInfo{ Version: ProtocolVersion(1), Features: []iproto.Feature{iproto.IPROTO_FEATURE_STREAMS}, - }).Context(nil) //nolint + }).Context(nil) // nolint data, err := conn.Do(req).Get() require.Nilf(t, err, "No errors on Id request execution") require.NotNilf(t, data, "Response data not empty") @@ -3293,7 +3293,7 @@ func TestClientIdRequestObjectWithPassedCanceledContext(t *testing.T) { req := NewIdRequest(ProtocolInfo{ Version: ProtocolVersion(1), Features: []iproto.Feature{iproto.IPROTO_FEATURE_STREAMS}, - }).Context(ctx) //nolint + }).Context(ctx) // nolint cancel() resp, err := conn.Do(req).Get() require.Nilf(t, resp, "Response is empty")