Skip to content

Commit

Permalink
allowed to create xerrors.TransportError() from grpc status error + r…
Browse files Browse the repository at this point in the history
…efactoring of xerrors tests + added xtest.CurrentFileLine()
  • Loading branch information
asmyasnikov committed Oct 23, 2023
1 parent 461b0fe commit ed17dab
Show file tree
Hide file tree
Showing 9 changed files with 346 additions and 137 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
* Bumped `google.golang.org/grpc` to `v1.58.0`
* Bumped `google.golang.org/protobuf` to `v1.31.0`
* Bumped `golang.org/x/sync` to `v0.3.0`
* Allowed in `internal/xerrors.TransportError(err)` grpc status error as source
* Added `internal/credentials.IsAccessError(err)` helper for check access errors
* Changed period for re-fresh static credentials token from `1/2` to `1/10` to expiration time

Expand Down
10 changes: 5 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ require (
github.com/google/uuid v1.3.0
github.com/jonboulle/clockwork v0.3.0
github.com/ydb-platform/ydb-go-genproto v0.0.0-20231012155159-f85a672542fd
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4
golang.org/x/sync v0.3.0
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1
google.golang.org/grpc v1.53.0
google.golang.org/protobuf v1.28.1
google.golang.org/grpc v1.58.0
google.golang.org/protobuf v1.31.0
)

// requires for tests only
Expand All @@ -22,11 +22,11 @@ require (

require (
github.com/davecgh/go-spew v1.1.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/net v0.15.0 // indirect
golang.org/x/sys v0.12.0 // indirect
golang.org/x/text v0.13.0 // indirect
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect
gopkg.in/yaml.v3 v3.0.0 // indirect
)
19 changes: 10 additions & 9 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
Expand Down Expand Up @@ -96,8 +97,8 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand Down Expand Up @@ -132,17 +133,17 @@ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoA
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w=
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc=
google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw=
google.golang.org/grpc v1.58.0 h1:32JY8YpPMSR45K+c3o6b8VL73V+rR8k+DeMIr4vRH8o=
google.golang.org/grpc v1.58.0/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
Expand All @@ -156,8 +157,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
Expand Down
79 changes: 65 additions & 14 deletions internal/xerrors/operation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,72 @@ import (
)

func TestIsOperationError(t *testing.T) {
for _, code := range [...]Ydb.StatusIds_StatusCode{
Ydb.StatusIds_BAD_REQUEST,
Ydb.StatusIds_BAD_SESSION,
for _, tt := range []struct {
err error
codes []Ydb.StatusIds_StatusCode
match bool
}{
// check only operation error with any ydb status code
{
err: &operationError{code: Ydb.StatusIds_BAD_REQUEST},
match: true,
},
{
err: fmt.Errorf("wrapped: %w", &operationError{code: Ydb.StatusIds_BAD_REQUEST}),
match: true,
},
{
err: Join(
fmt.Errorf("test"),
&operationError{code: Ydb.StatusIds_BAD_REQUEST},
Retryable(fmt.Errorf("test")),
),
match: true,
},
// match ydb status code
{
err: &operationError{code: Ydb.StatusIds_BAD_REQUEST},
codes: []Ydb.StatusIds_StatusCode{Ydb.StatusIds_BAD_REQUEST},
match: true,
},
{
err: fmt.Errorf("wrapped: %w", &operationError{code: Ydb.StatusIds_BAD_REQUEST}),
codes: []Ydb.StatusIds_StatusCode{Ydb.StatusIds_BAD_REQUEST},
match: true,
},
{
err: Join(
fmt.Errorf("test"),
&operationError{code: Ydb.StatusIds_BAD_REQUEST},
Retryable(fmt.Errorf("test")),
),
codes: []Ydb.StatusIds_StatusCode{Ydb.StatusIds_BAD_REQUEST},
match: true,
},
// no match ydb status code
{
err: &operationError{code: Ydb.StatusIds_BAD_REQUEST},
codes: []Ydb.StatusIds_StatusCode{Ydb.StatusIds_ABORTED},
match: false,
},
{
err: fmt.Errorf("wrapped: %w", &operationError{code: Ydb.StatusIds_BAD_REQUEST}),
codes: []Ydb.StatusIds_StatusCode{Ydb.StatusIds_ABORTED},
match: false,
},
{
err: Join(
fmt.Errorf("test"),
&operationError{code: Ydb.StatusIds_BAD_REQUEST},
Retryable(fmt.Errorf("test")),
),
codes: []Ydb.StatusIds_StatusCode{Ydb.StatusIds_ABORTED},
match: false,
},
} {
for _, err := range []error{
&operationError{code: code},
Operation(WithStatusCode(code)),
fmt.Errorf("wrapped: %w", &operationError{code: code}),
} {
t.Run("", func(t *testing.T) {
if !IsOperationError(err, code) {
t.Errorf("expected %v to be operationError with code=%v", err, code)
}
})
}
t.Run("", func(t *testing.T) {
require.Equal(t, tt.match, IsOperationError(tt.err, tt.codes...))
})
}
}

Expand Down
106 changes: 106 additions & 0 deletions internal/xerrors/pessimized_error_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package xerrors

import (
"context"
"errors"
"fmt"
"testing"

grpcCodes "google.golang.org/grpc/codes"
grpcStatus "google.golang.org/grpc/status"
)

func TestMustPessimizeEndpoint(t *testing.T) {
for _, test := range []struct {
error error
pessimize bool
}{
{
error: Transport(grpcStatus.Error(grpcCodes.Canceled, "")),
pessimize: true,
},
{
error: Transport(grpcStatus.Error(grpcCodes.Unknown, "")),
pessimize: true,
},
{
error: Transport(grpcStatus.Error(grpcCodes.InvalidArgument, "")),
pessimize: true,
},
{
error: Transport(grpcStatus.Error(grpcCodes.DeadlineExceeded, "")),
pessimize: true,
},
{
error: Transport(grpcStatus.Error(grpcCodes.NotFound, "")),
pessimize: true,
},
{
error: Transport(grpcStatus.Error(grpcCodes.AlreadyExists, "")),
pessimize: true,
},
{
error: Transport(grpcStatus.Error(grpcCodes.PermissionDenied, "")),
pessimize: true,
},
{
error: Transport(grpcStatus.Error(grpcCodes.ResourceExhausted, "")),
pessimize: false,
},
{
error: Transport(grpcStatus.Error(grpcCodes.FailedPrecondition, "")),
pessimize: true,
},
{
error: Transport(grpcStatus.Error(grpcCodes.Aborted, "")),
pessimize: true,
},
{
error: Transport(grpcStatus.Error(grpcCodes.OutOfRange, "")),
pessimize: false,
},
{
error: Transport(grpcStatus.Error(grpcCodes.Unimplemented, "")),
pessimize: true,
},
{
error: Transport(grpcStatus.Error(grpcCodes.Internal, "")),
pessimize: true,
},
{
error: Transport(grpcStatus.Error(grpcCodes.Unavailable, "")),
pessimize: true,
},
{
error: Transport(grpcStatus.Error(grpcCodes.DataLoss, "")),
pessimize: true,
},
{
error: Transport(grpcStatus.Error(grpcCodes.Unauthenticated, "")),
pessimize: true,
},
{
error: context.Canceled,
pessimize: false,
},
{
error: context.DeadlineExceeded,
pessimize: false,
},
{
error: fmt.Errorf("user error"),
pessimize: false,
},
} {
err := errors.Unwrap(test.error)
if err == nil {
err = test.error
}
t.Run(err.Error(), func(t *testing.T) {
pessimize := MustPessimizeEndpoint(test.error)
if pessimize != test.pessimize {
t.Errorf("unexpected pessimization status for error `%v`: %t, exp: %t", test.error, pessimize, test.pessimize)
}
})
}
}
21 changes: 17 additions & 4 deletions internal/xerrors/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,19 +113,23 @@ func IsTransportError(err error, codes ...grpcCodes.Code) bool {
if err == nil {
return false
}
var status *grpcStatus.Status
if t := (*transportError)(nil); errors.As(err, &t) {
status = t.status
} else if t, has := grpcStatus.FromError(err); has {
status = t
}
if status != nil {
if len(codes) == 0 {
return true
}
for _, code := range codes {
if t.status.Code() == code {
if status.Code() == code {
return true
}
}
return false
}
_, has := grpcStatus.FromError(err)
return has
return false
}

// Transport returns a new transport error with given options
Expand Down Expand Up @@ -178,9 +182,18 @@ func MustPessimizeEndpoint(err error, codes ...grpcCodes.Code) bool {
}

func TransportError(err error) Error {
if err == nil {
return nil
}
var t *transportError
if errors.As(err, &t) {
return t
}
if s, ok := grpcStatus.FromError(err); ok {
return &transportError{
status: s,
err: err,
}
}
return nil
}
Loading

0 comments on commit ed17dab

Please sign in to comment.