diff --git a/.golangci.yml b/.golangci.yml index 102d0e3ed..bc26001f6 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -231,7 +231,6 @@ linters: - gochecknoglobals - gocognit - godot - - goerr113 - golint - ifshort - interfacebloat diff --git a/balancers/config.go b/balancers/config.go index 8bc38199c..4883cb0fd 100644 --- a/balancers/config.go +++ b/balancers/config.go @@ -2,7 +2,6 @@ package balancers import ( "encoding/json" - "fmt" balancerConfig "github.com/ydb-platform/ydb-go-sdk/v3/internal/balancer/config" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" @@ -61,7 +60,10 @@ func createByType(t balancerType) (*balancerConfig.Config, error) { case typeRoundRobin: return RoundRobin(), nil default: - return nil, xerrors.WithStackTrace(fmt.Errorf("unknown type of balancer: %s", t)) + return nil, xerrors.WithStackTrace(&balancerTypeError{ + message: "unknown type of balancer: %s", + bType: t, + }) } } @@ -96,7 +98,10 @@ func CreateFromConfig(s string) (*balancerConfig.Config, error) { return PreferLocalDC(b), nil case preferTypeLocations: if len(c.Locations) == 0 { - return nil, xerrors.WithStackTrace(fmt.Errorf("empty locations list in balancer '%s' config", c.Type)) + return nil, xerrors.WithStackTrace(&balancerTypeError{ + message: "empty locations list in balancer '%s' config", + bType: c.Type, + }) } if c.Fallback { return PreferLocationsWithFallback(b, c.Locations...), nil diff --git a/balancers/errors.go b/balancers/errors.go new file mode 100644 index 000000000..c8a82a206 --- /dev/null +++ b/balancers/errors.go @@ -0,0 +1,12 @@ +package balancers + +import "fmt" + +type balancerTypeError struct { + message string + bType balancerType +} + +func (e *balancerTypeError) Error() string { + return fmt.Sprintf(e.message, e.bType) +} diff --git a/examples/basic/native/query/main.go b/examples/basic/native/query/main.go index bf13c8f2f..610690149 100644 --- a/examples/basic/native/query/main.go +++ b/examples/basic/native/query/main.go @@ -9,7 +9,7 @@ import ( "time" environ "github.com/ydb-platform/ydb-go-sdk-auth-environ" - ydb "github.com/ydb-platform/ydb-go-sdk/v3" + "github.com/ydb-platform/ydb-go-sdk/v3" "github.com/ydb-platform/ydb-go-sdk/v3/sugar" ) @@ -19,6 +19,7 @@ func isYdbVersionHaveQueryService() error { for i, component := range ydbVersion { if i < len(minYdbVersion) { if r := strings.Compare(component, minYdbVersion[i]); r < 0 { + //nolint:goerr113 return fmt.Errorf("example '%s' run on minimal YDB version '%v', but current version is '%s'", os.Args[0], strings.Join(minYdbVersion, "."), diff --git a/examples/read_table/main.go b/examples/read_table/main.go index 2e72d944a..65a2f45e6 100644 --- a/examples/read_table/main.go +++ b/examples/read_table/main.go @@ -9,7 +9,7 @@ import ( "path" environ "github.com/ydb-platform/ydb-go-sdk-auth-environ" - ydb "github.com/ydb-platform/ydb-go-sdk/v3" + "github.com/ydb-platform/ydb-go-sdk/v3" "github.com/ydb-platform/ydb-go-sdk/v3/table/options" "github.com/ydb-platform/ydb-go-sdk/v3/table/types" ) diff --git a/examples/serverless/url_shortener/service.go b/examples/serverless/url_shortener/service.go index 041c55d9d..b87a1a9ea 100644 --- a/examples/serverless/url_shortener/service.go +++ b/examples/serverless/url_shortener/service.go @@ -22,7 +22,7 @@ import ( "github.com/prometheus/client_golang/prometheus/promhttp" environ "github.com/ydb-platform/ydb-go-sdk-auth-environ" ydbMetrics "github.com/ydb-platform/ydb-go-sdk-prometheus/v2" - ydb "github.com/ydb-platform/ydb-go-sdk/v3" + "github.com/ydb-platform/ydb-go-sdk/v3" "github.com/ydb-platform/ydb-go-sdk/v3/table" "github.com/ydb-platform/ydb-go-sdk/v3/table/options" "github.com/ydb-platform/ydb-go-sdk/v3/table/result" @@ -306,7 +306,7 @@ func (s *service) selectLong(ctx context.Context, hash string) (url string, err } } - return "", fmt.Errorf("hash '%s' is not found", hash) + return "", fmt.Errorf("hash '%s' is not found", hash) //nolint:goerr113 } func writeResponse(w http.ResponseWriter, statusCode int, body string) { @@ -390,7 +390,7 @@ func (s *service) handleShorten(w http.ResponseWriter, r *http.Request) { return } if !isLongCorrect(string(url)) { - err = fmt.Errorf("'%s' is not a valid URL", url) + err = fmt.Errorf("'%s' is not a valid URL", url) //nolint:goerr113 writeResponse(w, http.StatusBadRequest, err.Error()) return @@ -428,7 +428,7 @@ func (s *service) handleLonger(w http.ResponseWriter, r *http.Request) { }() path := strings.Split(r.URL.Path, "/") if !isShortCorrect(path[len(path)-1]) { - err = fmt.Errorf("'%s' is not a valid short path", path[len(path)-1]) + err = fmt.Errorf("'%s' is not a valid short path", path[len(path)-1]) //nolint:goerr113 writeResponse(w, http.StatusBadRequest, err.Error()) return diff --git a/examples/topic/cdc-cache-bus-freeseats/webserver.go b/examples/topic/cdc-cache-bus-freeseats/webserver.go index 3825fabce..7bb86a71b 100644 --- a/examples/topic/cdc-cache-bus-freeseats/webserver.go +++ b/examples/topic/cdc-cache-bus-freeseats/webserver.go @@ -15,7 +15,10 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/table/types" ) -var errNotEnthoughtFreeSeats = errors.New("not enough free seats") +var ( + errNotEnthoughtFreeSeats = errors.New("not enough free seats") + errNotFound = errors.New("not found") +) type server struct { cache *Cache @@ -133,7 +136,7 @@ SELECT freeSeats FROM bus WHERE id=$id; if !res.NextRow() { freeSeats = 0 - return 0, errors.New("not found") + return 0, errNotFound } err = res.ScanWithDefaults(&freeSeats) diff --git a/examples/topic/cdc-fill-and-read/main.go b/examples/topic/cdc-fill-and-read/main.go index d0cfdbe47..62c39f726 100644 --- a/examples/topic/cdc-fill-and-read/main.go +++ b/examples/topic/cdc-fill-and-read/main.go @@ -10,7 +10,7 @@ import ( "time" environ "github.com/ydb-platform/ydb-go-sdk-auth-environ" - ydb "github.com/ydb-platform/ydb-go-sdk/v3" + "github.com/ydb-platform/ydb-go-sdk/v3" "github.com/ydb-platform/ydb-go-sdk/v3/topic/topicoptions" "github.com/ydb-platform/ydb-go-sdk/v3/topic/topictypes" ) diff --git a/examples/topic/cdc-fill-and-read/tables.go b/examples/topic/cdc-fill-and-read/tables.go index a522bdf11..61281a953 100644 --- a/examples/topic/cdc-fill-and-read/tables.go +++ b/examples/topic/cdc-fill-and-read/tables.go @@ -8,7 +8,7 @@ import ( "strconv" "time" - ydb "github.com/ydb-platform/ydb-go-sdk/v3" + "github.com/ydb-platform/ydb-go-sdk/v3" "github.com/ydb-platform/ydb-go-sdk/v3/table" "github.com/ydb-platform/ydb-go-sdk/v3/table/options" "github.com/ydb-platform/ydb-go-sdk/v3/table/types" diff --git a/examples/topic/topicreader/topicreader_advanced.go b/examples/topic/topicreader/topicreader_advanced.go index 256d38494..e9e7e6a2e 100644 --- a/examples/topic/topicreader/topicreader_advanced.go +++ b/examples/topic/topicreader/topicreader_advanced.go @@ -10,6 +10,8 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/topic/topicreader" ) +var errBadDataLen = errors.New("bad data len") + // ReadMessagesWithCustomBatching example of custom of readed message batch func ReadMessagesWithCustomBatching(ctx context.Context, db *ydb.Driver) { reader, _ := db.Topic().StartReader("consumer", nil) @@ -31,7 +33,7 @@ type MyMessage struct { // UnmarshalYDBTopicMessage implements topicreader.MessageContentUnmarshaler interface func (m *MyMessage) UnmarshalYDBTopicMessage(data []byte) error { if len(data) != 6 { - return errors.New("bad data len") + return errBadDataLen } m.ID = data[0] m.ChangeType = data[1] diff --git a/examples/ttl/main.go b/examples/ttl/main.go index b1a8ab963..b185fc4a4 100644 --- a/examples/ttl/main.go +++ b/examples/ttl/main.go @@ -8,7 +8,7 @@ import ( "path" environ "github.com/ydb-platform/ydb-go-sdk-auth-environ" - ydb "github.com/ydb-platform/ydb-go-sdk/v3" + "github.com/ydb-platform/ydb-go-sdk/v3" "github.com/ydb-platform/ydb-go-sdk/v3/sugar" ) diff --git a/examples/ttl_readtable/main.go b/examples/ttl_readtable/main.go index e867056d7..d0612ddf6 100644 --- a/examples/ttl_readtable/main.go +++ b/examples/ttl_readtable/main.go @@ -8,7 +8,7 @@ import ( "path" environ "github.com/ydb-platform/ydb-go-sdk-auth-environ" - ydb "github.com/ydb-platform/ydb-go-sdk/v3" + "github.com/ydb-platform/ydb-go-sdk/v3" "github.com/ydb-platform/ydb-go-sdk/v3/sugar" ) diff --git a/internal/background/worker.go b/internal/background/worker.go index c41ad4b0a..1ce2bc608 100644 --- a/internal/background/worker.go +++ b/internal/background/worker.go @@ -12,6 +12,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsync" ) +//nolint:goerr113 var ( ErrAlreadyClosed = xerrors.Wrap(errors.New("ydb: background worker already closed")) errClosedWithNilReason = xerrors.Wrap(errors.New("ydb: background worker closed with nil reason")) diff --git a/internal/balancer/balancer.go b/internal/balancer/balancer.go index b33f7266a..ff6afae25 100644 --- a/internal/balancer/balancer.go +++ b/internal/balancer/balancer.go @@ -24,7 +24,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/trace" ) -var ErrNoEndpoints = xerrors.Wrap(fmt.Errorf("no endpoints")) +var ErrNoEndpoints = xerrors.Wrap(fmt.Errorf("no endpoints")) //nolint:goerr113 type discoveryClient interface { closer.Closer diff --git a/internal/balancer/local_dc.go b/internal/balancer/local_dc.go index b1ee2e086..f499797a6 100644 --- a/internal/balancer/local_dc.go +++ b/internal/balancer/local_dc.go @@ -15,6 +15,11 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" ) +var ( + errEmptyEndpointsList = errors.New("empty endpoints list") + errFailCheckFastestAddress = errors.New("failed to check fastest address") +) + const ( maxEndpointsCheckPerLocation = 5 ) @@ -64,7 +69,7 @@ func checkFastestAddress(ctx context.Context, addresses []string) string { func detectFastestEndpoint(ctx context.Context, endpoints []endpoint.Endpoint) (endpoint.Endpoint, error) { if len(endpoints) == 0 { - return nil, xerrors.WithStackTrace(errors.New("empty endpoints list")) + return nil, xerrors.WithStackTrace(errEmptyEndpointsList) } var lastErr error @@ -86,7 +91,7 @@ func detectFastestEndpoint(ctx context.Context, endpoints []endpoint.Endpoint) ( continue } if len(addresses) == 0 { - lastErr = xerrors.WithStackTrace(fmt.Errorf("no ips for fqdn: %q", host)) + lastErr = xerrors.WithStackTrace(fmt.Errorf("no ips for fqdn: %q", host)) //nolint:goerr113 continue } @@ -106,7 +111,7 @@ func detectFastestEndpoint(ctx context.Context, endpoints []endpoint.Endpoint) ( fastestAddress := checkFastestAddress(ctx, addressesToPing) if fastestAddress == "" { - return nil, xerrors.WithStackTrace(errors.New("failed to check fastest address")) + return nil, xerrors.WithStackTrace(errFailCheckFastestAddress) } return addressToEndpoint[fastestAddress], nil diff --git a/internal/cmd/gstack/utils/utils.go b/internal/cmd/gstack/utils/utils.go index 19b35512d..d6fd03c4f 100644 --- a/internal/cmd/gstack/utils/utils.go +++ b/internal/cmd/gstack/utils/utils.go @@ -1,6 +1,7 @@ package utils import ( + "errors" "fmt" "go/ast" "go/parser" @@ -13,6 +14,11 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/version" ) +var ( + errGettingIdentFromExpr = errors.New("error during getting ident from expr") + errGetPackageName = errors.New("error during get package name function") +) + type FunctionIDArg struct { FuncDecl *ast.FuncDecl ArgPos token.Pos @@ -32,8 +38,10 @@ func ReadFile(filename string, info fs.FileInfo) ([]byte, error) { return nil, err } if n < size { + //nolint:goerr113 return nil, fmt.Errorf("error: size of %q changed during reading (from %d to %d bytes)", filename, size, n) } else if n > size { + //nolint:goerr113 return nil, fmt.Errorf("error: size of %q changed during reading (from %d to >=%d bytes)", filename, size, len(src)) } @@ -120,7 +128,7 @@ func getIdentNameFromExpr(expr ast.Expr) (string, error) { case *ast.IndexListExpr: return getIdentNameFromExpr(expr.X) default: - return "", fmt.Errorf("error during getting ident from expr") + return "", errGettingIdentFromExpr } } @@ -128,7 +136,7 @@ func getPackageName(fset *token.FileSet, arg FunctionIDArg) (string, error) { file := fset.File(arg.ArgPos) parsedFile, err := parser.ParseFile(fset, file.Name(), nil, parser.PackageClauseOnly) if err != nil { - return "", fmt.Errorf("error during get package name function") + return "", errGetPackageName } return parsedFile.Name.Name, nil diff --git a/internal/cmd/gtrace/main.go b/internal/cmd/gtrace/main.go index 84a16add4..9c21e35a6 100644 --- a/internal/cmd/gtrace/main.go +++ b/internal/cmd/gtrace/main.go @@ -3,6 +3,7 @@ package main import ( "bufio" "bytes" + "errors" "flag" "fmt" "go/ast" @@ -20,6 +21,8 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" ) +var errUnsupportedNumberOfFuncResults = errors.New("unsupported number of function results") + //nolint:gocyclo func main() { var ( @@ -276,9 +279,7 @@ func buildFunc(info *types.Info, traces map[string]*Trace, fn *ast.FuncType) (re return ret, nil } if len(fn.Results.List) > 1 { - return nil, fmt.Errorf( - "unsupported number of function results", - ) + return nil, errUnsupportedNumberOfFuncResults } r := fn.Results.List[0] @@ -302,6 +303,7 @@ func buildFunc(info *types.Info, traces map[string]*Trace, fn *ast.FuncType) (re } } + //nolint:goerr113 return nil, fmt.Errorf( "unsupported function result type %s", info.TypeOf(r.Type), diff --git a/internal/conn/conn.go b/internal/conn/conn.go index d7e05bd42..915df7f2c 100644 --- a/internal/conn/conn.go +++ b/internal/conn/conn.go @@ -25,13 +25,13 @@ import ( var ( // errOperationNotReady specified error when operation is not ready - errOperationNotReady = xerrors.Wrap(fmt.Errorf("operation is not ready yet")) + errOperationNotReady = xerrors.Wrap(fmt.Errorf("operation is not ready yet")) //nolint:goerr113 // errClosedConnection specified error when connection are closed early - errClosedConnection = xerrors.Wrap(fmt.Errorf("connection closed early")) + errClosedConnection = xerrors.Wrap(fmt.Errorf("connection closed early")) //nolint:goerr113 // errUnavailableConnection specified error when connection are closed early - errUnavailableConnection = xerrors.Wrap(fmt.Errorf("connection unavailable")) + errUnavailableConnection = xerrors.Wrap(fmt.Errorf("connection unavailable")) //nolint:goerr113 ) type Conn interface { diff --git a/internal/conn/error_test.go b/internal/conn/error_test.go index 569a38a31..cf2f2aaf5 100644 --- a/internal/conn/error_test.go +++ b/internal/conn/error_test.go @@ -7,29 +7,30 @@ import ( "github.com/stretchr/testify/require" ) +var ( + errTest = errors.New("test") + errTest2 = errors.New("test2") +) + func TestNodeErrorError(t *testing.T) { - testErr := errors.New("test") - nodeErr := newConnError(1, "localhost:1234", testErr) + nodeErr := newConnError(1, "localhost:1234", errTest) message := nodeErr.Error() require.Equal(t, "connError{node_id:1,address:'localhost:1234'}: test", message) } func TestNodeErrorUnwrap(t *testing.T) { - testErr := errors.New("test") - nodeErr := newConnError(1, "asd", testErr) + nodeErr := newConnError(1, "asd", errTest) unwrapped := errors.Unwrap(nodeErr) - require.Equal(t, testErr, unwrapped) + require.Equal(t, errTest, unwrapped) } func TestNodeErrorIs(t *testing.T) { - testErr := errors.New("test") - testErr2 := errors.New("test2") - nodeErr := newConnError(1, "localhost:1234", testErr) + nodeErr := newConnError(1, "localhost:1234", errTest) - require.ErrorIs(t, nodeErr, testErr) - require.NotErrorIs(t, nodeErr, testErr2) + require.ErrorIs(t, nodeErr, errTest) + require.NotErrorIs(t, nodeErr, errTest2) } type testType1Error struct { diff --git a/internal/coordination/client.go b/internal/coordination/client.go index c3685cc64..908d2eb1e 100644 --- a/internal/coordination/client.go +++ b/internal/coordination/client.go @@ -24,6 +24,7 @@ import ( //go:generate mockgen -destination grpc_client_mock_test.go -package coordination -write_package_comment=false github.com/ydb-platform/ydb-go-genproto/Ydb_Coordination_V1 CoordinationServiceClient,CoordinationService_SessionClient +//nolint:goerr113 var errNilClient = xerrors.Wrap(errors.New("coordination client is not initialized")) type Client struct { diff --git a/internal/credentials/access_error.go b/internal/credentials/access_error.go index 777bc3d80..38ff2ea5d 100644 --- a/internal/credentials/access_error.go +++ b/internal/credentials/access_error.go @@ -103,7 +103,7 @@ func AccessError(msg string, err error, opts ...authErrorOption) error { } buffer.WriteString("): %w") - return xerrors.WithStackTrace(fmt.Errorf(buffer.String(), err), xerrors.WithSkipDepth(1)) + return xerrors.WithStackTrace(fmt.Errorf(buffer.String(), err), xerrors.WithSkipDepth(1)) //nolint:goerr113 } func IsAccessError(err error) bool { diff --git a/internal/credentials/access_error_test.go b/internal/credentials/access_error_test.go index 565ad8975..8cf323eda 100644 --- a/internal/credentials/access_error_test.go +++ b/internal/credentials/access_error_test.go @@ -14,7 +14,12 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" ) -var _ Credentials = customCredentials{} +var ( + _ Credentials = customCredentials{} + + errTest = errors.New("test") + errSome = errors.New("some error") +) type customCredentials struct { token string @@ -32,7 +37,7 @@ func TestAccessError(t *testing.T) { { err: AccessError( "something went wrong", - errors.New("test"), + errTest, WithEndpoint("grps://localhost:2135"), WithDatabase("/local"), WithCredentials(NewAnonymousCredentials(WithSourceInfo(""))), @@ -42,12 +47,12 @@ func TestAccessError(t *testing.T) { "database:\"/local\"," + "credentials:\"Anonymous{}\"" + "): test " + - "at `github.com/ydb-platform/ydb-go-sdk/v3/internal/credentials.TestAccessError(access_error_test.go:33)`", //nolint:lll + "at `github.com/ydb-platform/ydb-go-sdk/v3/internal/credentials.TestAccessError(access_error_test.go:38)`", //nolint:lll }, { err: AccessError( "something went wrong", - errors.New("test"), + errTest, WithEndpoint("grps://localhost:2135"), WithDatabase("/local"), WithCredentials(NewAnonymousCredentials(WithSourceInfo(t.Name()))), @@ -57,12 +62,12 @@ func TestAccessError(t *testing.T) { "database:\"/local\"," + "credentials:\"Anonymous{From:\\\"TestAccessError\\\"}\"" + "): test " + - "at `github.com/ydb-platform/ydb-go-sdk/v3/internal/credentials.TestAccessError(access_error_test.go:48)`", //nolint:lll + "at `github.com/ydb-platform/ydb-go-sdk/v3/internal/credentials.TestAccessError(access_error_test.go:53)`", //nolint:lll }, { err: AccessError( "something went wrong", - errors.New("test"), + errTest, WithEndpoint("grps://localhost:2135"), WithDatabase("/local"), WithCredentials(NewAccessTokenCredentials("SECRET_TOKEN", WithSourceInfo(""))), @@ -72,12 +77,12 @@ func TestAccessError(t *testing.T) { "database:\"/local\"," + "credentials:\"AccessToken{Token:\\\"****(CRC-32c: 9B7801F4)\\\"}\"" + "): test " + - "at `github.com/ydb-platform/ydb-go-sdk/v3/internal/credentials.TestAccessError(access_error_test.go:63)`", //nolint:lll + "at `github.com/ydb-platform/ydb-go-sdk/v3/internal/credentials.TestAccessError(access_error_test.go:68)`", //nolint:lll }, { err: AccessError( "something went wrong", - errors.New("test"), + errTest, WithEndpoint("grps://localhost:2135"), WithDatabase("/local"), WithCredentials(NewAccessTokenCredentials("SECRET_TOKEN", WithSourceInfo(t.Name()))), @@ -87,12 +92,12 @@ func TestAccessError(t *testing.T) { "database:\"/local\"," + "credentials:\"AccessToken{Token:\\\"****(CRC-32c: 9B7801F4)\\\",From:\\\"TestAccessError\\\"}\"" + "): test " + - "at `github.com/ydb-platform/ydb-go-sdk/v3/internal/credentials.TestAccessError(access_error_test.go:78)`", //nolint:lll + "at `github.com/ydb-platform/ydb-go-sdk/v3/internal/credentials.TestAccessError(access_error_test.go:83)`", //nolint:lll }, { err: AccessError( "something went wrong", - errors.New("test"), + errTest, WithEndpoint("grps://localhost:2135"), WithDatabase("/local"), WithCredentials( @@ -106,12 +111,12 @@ func TestAccessError(t *testing.T) { "database:\"/local\"," + "credentials:\"Static{User:\\\"USER\\\",Password:\\\"SEC**********RD\\\",Token:\\\"****(CRC-32c: 00000000)\\\"}\"" + //nolint:lll "): test " + - "at `github.com/ydb-platform/ydb-go-sdk/v3/internal/credentials.TestAccessError(access_error_test.go:93)`", //nolint:lll + "at `github.com/ydb-platform/ydb-go-sdk/v3/internal/credentials.TestAccessError(access_error_test.go:98)`", //nolint:lll }, { err: AccessError( "something went wrong", - errors.New("test"), + errTest, WithEndpoint("grps://localhost:2135"), WithDatabase("/local"), WithCredentials( @@ -125,12 +130,12 @@ func TestAccessError(t *testing.T) { "database:\"/local\"," + "credentials:\"Static{User:\\\"USER\\\",Password:\\\"SEC**********RD\\\",Token:\\\"****(CRC-32c: 00000000)\\\",From:\\\"TestAccessError\\\"}\"" + //nolint:lll "): test " + - "at `github.com/ydb-platform/ydb-go-sdk/v3/internal/credentials.TestAccessError(access_error_test.go:112)`", //nolint:lll + "at `github.com/ydb-platform/ydb-go-sdk/v3/internal/credentials.TestAccessError(access_error_test.go:117)`", //nolint:lll }, { err: AccessError( "something went wrong", - errors.New("test"), + errTest, WithEndpoint("grps://localhost:2135"), WithDatabase("/local"), WithCredentials(customCredentials{token: "SECRET_TOKEN"}), @@ -140,12 +145,12 @@ func TestAccessError(t *testing.T) { "database:\"/local\"," + "credentials:\"github.com/ydb-platform/ydb-go-sdk/v3/internal/credentials.customCredentials\"" + "): test " + - "at `github.com/ydb-platform/ydb-go-sdk/v3/internal/credentials.TestAccessError(access_error_test.go:131)`", //nolint:lll + "at `github.com/ydb-platform/ydb-go-sdk/v3/internal/credentials.TestAccessError(access_error_test.go:136)`", //nolint:lll }, { err: AccessError( "something went wrong", - errors.New("test"), + errTest, WithEndpoint("grps://localhost:2135"), WithDatabase("/local"), WithCredentials(NewAnonymousCredentials(WithSourceInfo(""))), @@ -155,7 +160,7 @@ func TestAccessError(t *testing.T) { "database:\"/local\"," + "credentials:\"Anonymous{}\"" + "): test " + - "at `github.com/ydb-platform/ydb-go-sdk/v3/internal/credentials.TestAccessError(access_error_test.go:146)`", //nolint:lll + "at `github.com/ydb-platform/ydb-go-sdk/v3/internal/credentials.TestAccessError(access_error_test.go:151)`", //nolint:lll }, } { t.Run("", func(t *testing.T) { @@ -194,7 +199,7 @@ func TestIsAccessError(t *testing.T) { is: true, }, { - error: errors.New("some error"), + error: errSome, is: false, }, } { diff --git a/internal/credentials/static.go b/internal/credentials/static.go index 7d9437dfb..40be39c56 100644 --- a/internal/credentials/static.go +++ b/internal/credentials/static.go @@ -111,7 +111,7 @@ func (c *Static) Token(ctx context.Context) (token string, err error) { switch { case !response.GetOperation().GetReady(): return "", xerrors.WithStackTrace( - fmt.Errorf("operation '%s' not ready: %v", + fmt.Errorf("operation '%s' not ready: %v", //nolint:goerr113 response.GetOperation().GetId(), response.GetOperation().GetIssues(), ), diff --git a/internal/decimal/errors.go b/internal/decimal/errors.go index a015ad1f6..07dc34664 100644 --- a/internal/decimal/errors.go +++ b/internal/decimal/errors.go @@ -6,6 +6,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" ) +//nolint:goerr113 var errSyntax = xerrors.Wrap(fmt.Errorf("invalid syntax")) type ParseError struct { @@ -32,7 +33,7 @@ func syntaxError(s string) *ParseError { func precisionError(s string, precision, scale uint32) *ParseError { return &ParseError{ - Err: fmt.Errorf("invalid precision/scale: %d/%d", precision, scale), + Err: fmt.Errorf("invalid precision/scale: %d/%d", precision, scale), //nolint:goerr113 Input: s, } } diff --git a/internal/dsn/dsn.go b/internal/dsn/dsn.go index 17e77088e..968c3aae8 100644 --- a/internal/dsn/dsn.go +++ b/internal/dsn/dsn.go @@ -30,6 +30,7 @@ func Parse(dsn string) (info parsedInfo, err error) { return info, xerrors.WithStackTrace(err) } if port := uri.Port(); port == "" { + //nolint:goerr113 return info, xerrors.WithStackTrace(fmt.Errorf("bad connection string '%s': port required", dsn)) } info.Options = append(info.Options, diff --git a/internal/grpcwrapper/rawscheme/entry.go b/internal/grpcwrapper/rawscheme/entry.go index f1fb68bde..de7b5f966 100644 --- a/internal/grpcwrapper/rawscheme/entry.go +++ b/internal/grpcwrapper/rawscheme/entry.go @@ -9,8 +9,8 @@ import ( ) var ( - errUnexpectedNilForSchemePermissions = xerrors.Wrap(errors.New("ydb: unexpected nil for scheme permissions")) - errUnexpectedNilForSchemeEntry = xerrors.Wrap(errors.New("ydb: unexpected nil for scheme entry")) + errUnexpectedNilForSchemePermissions = xerrors.Wrap(errors.New("ydb: unexpected nil for scheme permissions")) //nolint:lll,goerr113 + errUnexpectedNilForSchemeEntry = xerrors.Wrap(errors.New("ydb: unexpected nil for scheme entry")) //nolint:lll,goerr113 ) type Entry struct { diff --git a/internal/grpcwrapper/rawtopic/controlplane_types.go b/internal/grpcwrapper/rawtopic/controlplane_types.go index 6df4322fb..ce274c5d1 100644 --- a/internal/grpcwrapper/rawtopic/controlplane_types.go +++ b/internal/grpcwrapper/rawtopic/controlplane_types.go @@ -10,7 +10,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" ) -var errUnexpectedNilPartitioningSettings = xerrors.Wrap(errors.New("ydb: unexpected nil partitioning settings")) +var errUnexpectedNilPartitioningSettings = xerrors.Wrap(errors.New("ydb: unexpected nil partitioning settings")) //nolint:lll,goerr113 type Consumer struct { Name string diff --git a/internal/grpcwrapper/rawtopic/rawtopicreader/messages.go b/internal/grpcwrapper/rawtopic/rawtopicreader/messages.go index ad60427fa..69eaffd8b 100644 --- a/internal/grpcwrapper/rawtopic/rawtopicreader/messages.go +++ b/internal/grpcwrapper/rawtopic/rawtopicreader/messages.go @@ -12,14 +12,15 @@ import ( ) var ( - errUnexpectedNilStreamReadMessageReadResponse = xerrors.Wrap(errors.New("ydb: unexpected nil Ydb_Topic.StreamReadMessage_ReadResponse")) //nolint:lll - errNilPartitionData = xerrors.Wrap(errors.New("ydb: unexpected nil partition data")) - errUnexpectedNilBatchInPartitionData = xerrors.Wrap(errors.New("ydb: unexpected nil batch in partition data")) //nolint:lll - errUnexpectedMessageNilInPartitionData = xerrors.Wrap(errors.New("ydb: unexpected message nil in partition data")) //nolint:lll - errUnexpectedProtobufInOffsets = xerrors.Wrap(errors.New("ydb: unexpected protobuf nil offsets")) - errUnexpectedProtoNilStartPartitionSessionRequest = xerrors.Wrap(errors.New("ydb: unexpected proto nil start partition session request")) //nolint:lll - errUnexpectedNilPartitionSession = xerrors.Wrap(errors.New("ydb: unexpected proto nil partition session in start partition session request")) //nolint:lll - errUnexpectedGrpcNilStopPartitionSessionRequest = xerrors.Wrap(errors.New("ydb: unexpected grpc nil stop partition session request")) //nolint:lll + errUnexpectedNilStreamReadMessageReadResponse = xerrors.Wrap(errors.New("ydb: unexpected nil Ydb_Topic.StreamReadMessage_ReadResponse")) //nolint:lll,goerr113 + errNilPartitionData = xerrors.Wrap(errors.New("ydb: unexpected nil partition data")) //nolint:goerr113 + errUnexpectedNilBatchInPartitionData = xerrors.Wrap(errors.New("ydb: unexpected nil batch in partition data")) //nolint:lll,goerr113 + errUnexpectedMessageNilInPartitionData = xerrors.Wrap(errors.New("ydb: unexpected message nil in partition data")) //nolint:lll,goerr113 + errUnexpectedProtobufInOffsets = xerrors.Wrap(errors.New("ydb: unexpected protobuf nil offsets")) //nolint:goerr113 + errUnexpectedProtoNilStartPartitionSessionRequest = xerrors.Wrap(errors.New("ydb: unexpected proto nil start partition session request")) //nolint:lll,goerr113 + errUnexpectedNilPartitionSession = xerrors.Wrap(errors.New("ydb: unexpected proto nil partition session in start partition session request")) //nolint:lll,goerr113 + errUnexpectedGrpcNilStopPartitionSessionRequest = xerrors.Wrap(errors.New("ydb: unexpected grpc nil stop partition session request")) //nolint:lll,goerr113 + errUnexpectedNilWhileParseCommitOffsetResponse = xerrors.Wrap(errors.New("unexpected nil while parse commit offset response")) //nolint:lll,goerr113 ) type PartitionSessionID int64 @@ -364,7 +365,7 @@ func (r *CommitOffsetResponse) fromProto(proto *Ydb_Topic.StreamReadMessage_Comm for i := range r.PartitionsCommittedOffsets { srcCommitted := proto.GetPartitionsCommittedOffsets()[i] if srcCommitted == nil { - return xerrors.WithStackTrace(errors.New("unexpected nil while parse commit offset response")) + return xerrors.WithStackTrace(errUnexpectedNilWhileParseCommitOffsetResponse) } dstCommitted := &r.PartitionsCommittedOffsets[i] diff --git a/internal/grpcwrapper/rawtopic/rawtopicreader/rawtopicreader.go b/internal/grpcwrapper/rawtopic/rawtopicreader/rawtopicreader.go index 17ccc026e..03a7ccb4e 100644 --- a/internal/grpcwrapper/rawtopic/rawtopicreader/rawtopicreader.go +++ b/internal/grpcwrapper/rawtopic/rawtopicreader/rawtopicreader.go @@ -47,7 +47,7 @@ func (s StreamReader) Recv() (ServerMessage, error) { return nil, err } if !meta.Status.IsSuccess() { - return nil, xerrors.WithStackTrace(fmt.Errorf("ydb: bad status from topic server: %v", meta.Status)) + return nil, xerrors.WithStackTrace(fmt.Errorf("ydb: bad status from topic server: %v", meta.Status)) //nolint:lll,goerr113 } switch m := grpcMess.GetServerMessage().(type) { @@ -170,7 +170,7 @@ func (s StreamReader) Send(msg ClientMessage) (err error) { return s.Stream.Send(grpcMess) default: - return xerrors.WithStackTrace(fmt.Errorf("ydb: send unexpected message type: %v", reflect.TypeOf(msg))) + return xerrors.WithStackTrace(fmt.Errorf("ydb: send unexpected message type: %v", reflect.TypeOf(msg))) //nolint:lll,goerr113 } } diff --git a/internal/grpcwrapper/rawtopic/rawtopicwriter/messages.go b/internal/grpcwrapper/rawtopic/rawtopicwriter/messages.go index 252b4b3cb..a5c478fe7 100644 --- a/internal/grpcwrapper/rawtopic/rawtopicwriter/messages.go +++ b/internal/grpcwrapper/rawtopic/rawtopicwriter/messages.go @@ -14,9 +14,9 @@ import ( ) var ( - errWriteResultProtoIsNil = xerrors.Wrap(errors.New("ydb: write result proto is nil")) - errWriteResultResponseWriteAckIsNil = xerrors.Wrap(errors.New("ydb: write result response write ack is nil")) - errWriteResultResponseStatisticIsNil = xerrors.Wrap(errors.New("ydb: write result response statistic is nil")) + errWriteResultProtoIsNil = xerrors.Wrap(errors.New("ydb: write result proto is nil")) //nolint:lll,goerr113 + errWriteResultResponseWriteAckIsNil = xerrors.Wrap(errors.New("ydb: write result response write ack is nil")) //nolint:lll,goerr113 + errWriteResultResponseStatisticIsNil = xerrors.Wrap(errors.New("ydb: write result response statistic is nil")) //nolint:lll,goerr113 ) type InitRequest struct { @@ -83,6 +83,7 @@ func (p *Partitioning) setToProtoInitRequest(r *Ydb_Topic.StreamWriteMessage_Ini PartitionId: p.PartitionID, } default: + //nolint:goerr113 return xerrors.WithStackTrace(xerrors.Wrap(fmt.Errorf( "ydb: unexpected partition type while set to init request: %v", p.Type, @@ -105,6 +106,7 @@ func (p *Partitioning) setToProtoMessage(m *Ydb_Topic.StreamWriteMessage_WriteRe PartitionId: p.PartitionID, } default: + //nolint:goerr113 return xerrors.WithStackTrace(xerrors.Wrap(fmt.Errorf( "ydb: unexpected partition type while set to message proto: %v", p.Type, @@ -257,7 +259,7 @@ func (s *MessageWriteStatus) fromProto(status interface{}) error { return nil default: - return xerrors.WithStackTrace(xerrors.Wrap(fmt.Errorf("ydb: unexpected write status type: %v", reflect.TypeOf(v)))) + return xerrors.WithStackTrace(xerrors.Wrap(fmt.Errorf("ydb: unexpected write status type: %v", reflect.TypeOf(v)))) //nolint:lll,goerr113 } } diff --git a/internal/grpcwrapper/rawtopic/rawtopicwriter/streamwriter.go b/internal/grpcwrapper/rawtopic/rawtopicwriter/streamwriter.go index 8ff0b9727..ae248ccfc 100644 --- a/internal/grpcwrapper/rawtopic/rawtopicwriter/streamwriter.go +++ b/internal/grpcwrapper/rawtopic/rawtopicwriter/streamwriter.go @@ -16,7 +16,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" ) -var errConcurencyReadDenied = xerrors.Wrap(errors.New("ydb: read from rawtopicwriter in parallel")) +var errConcurencyReadDenied = xerrors.Wrap(errors.New("ydb: read from rawtopicwriter in parallel")) //nolint:goerr113 type GrpcStream interface { Send(messageNew *Ydb_Topic.StreamWriteMessage_FromClient) error @@ -56,7 +56,7 @@ func (w *StreamWriter) Recv() (ServerMessage, error) { return nil, err } if !meta.Status.IsSuccess() { - return nil, xerrors.WithStackTrace(fmt.Errorf("ydb: bad status from topic server: %v", meta.Status)) + return nil, xerrors.WithStackTrace(fmt.Errorf("ydb: bad status from topic server: %v", meta.Status)) //nolint:lll,goerr113 } switch v := grpcMsg.GetServerMessage().(type) { @@ -81,6 +81,7 @@ func (w *StreamWriter) Recv() (ServerMessage, error) { return &res, nil default: + //nolint:goerr113 return nil, xerrors.WithStackTrace(xerrors.Wrap(fmt.Errorf( "ydb: unexpected message type received from raw writer stream: '%v'", reflect.TypeOf(grpcMsg), @@ -117,6 +118,7 @@ func (w *StreamWriter) Send(rawMsg ClientMessage) (err error) { UpdateTokenRequest: v.ToProto(), } default: + //nolint:goerr113 return xerrors.WithStackTrace(xerrors.Wrap(fmt.Errorf( "ydb: unexpected message type for send to raw writer stream: '%v'", reflect.TypeOf(rawMsg), diff --git a/internal/grpcwrapper/rawydb/issues.go b/internal/grpcwrapper/rawydb/issues.go index 09ed1b3e3..8ad31d956 100644 --- a/internal/grpcwrapper/rawydb/issues.go +++ b/internal/grpcwrapper/rawydb/issues.go @@ -10,6 +10,8 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" ) +var errNilIssueMsgPointerFromProtobuf = xerrors.Wrap(errors.New("receive nil issue message pointer from protobuf")) //nolint:lll,goerr113 + type Issues []Issue func (issuesPointer *Issues) FromProto(p []*Ydb_Issue.IssueMessage) error { @@ -42,7 +44,7 @@ type Issue struct { func (issue *Issue) FromProto(p *Ydb_Issue.IssueMessage) error { if p == nil { - return xerrors.WithStackTrace(errors.New("receive nil issue message pointer from protobuf")) + return xerrors.WithStackTrace(errNilIssueMsgPointerFromProtobuf) } issue.Code = p.GetIssueCode() issue.Message = p.GetMessage() diff --git a/internal/grpcwrapper/rawydb/operation.go b/internal/grpcwrapper/rawydb/operation.go index 5073cb8aa..b01d00c70 100644 --- a/internal/grpcwrapper/rawydb/operation.go +++ b/internal/grpcwrapper/rawydb/operation.go @@ -27,7 +27,7 @@ func (o *Operation) FromProto(proto *Ydb_Operations.Operation) error { func (o *Operation) OperationStatusToError() error { if !o.Status.IsSuccess() { - return xerrors.WithStackTrace(fmt.Errorf("ydb: create topic error [%v]: %v", o.Status, o.Issues)) + return xerrors.WithStackTrace(fmt.Errorf("ydb: create topic error [%v]: %v", o.Status, o.Issues)) //nolint:lll,goerr113 } return nil diff --git a/internal/meta/trace_id_test.go b/internal/meta/trace_id_test.go index 09c71a034..d791923d9 100644 --- a/internal/meta/trace_id_test.go +++ b/internal/meta/trace_id_test.go @@ -10,6 +10,8 @@ import ( "google.golang.org/grpc/metadata" ) +var errEmpty = errors.New("") + func TestTraceID(t *testing.T) { t.Run("TraceID from rand", func(t *testing.T) { ctx, id, err := TraceID( @@ -32,7 +34,7 @@ func TestTraceID(t *testing.T) { context.Background(), func(opts *newTraceIDOpts) { opts.newRandom = func() (uuid.UUID, error) { - return uuid.UUID{}, errors.New("") + return uuid.UUID{}, errEmpty } }, ) @@ -43,7 +45,7 @@ func TestTraceID(t *testing.T) { WithTraceID(context.Background(), "{test}"), func(opts *newTraceIDOpts) { opts.newRandom = func() (uuid.UUID, error) { - return uuid.UUID{}, errors.New("") + return uuid.UUID{}, errEmpty } }, ) diff --git a/internal/pool/pool_test.go b/internal/pool/pool_test.go index 63f8a1c11..078123188 100644 --- a/internal/pool/pool_test.go +++ b/internal/pool/pool_test.go @@ -18,6 +18,8 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/xtest" ) +var errExpected = errors.New("expected error") + type testItem struct { v uint32 @@ -227,7 +229,7 @@ func TestPool(t *testing.T) { var ( newItems int64 deleteItems int64 - expErr = xerrors.Retryable(errors.New("expected error"), xerrors.InvalidObject()) + expErr = xerrors.Retryable(errExpected, xerrors.InvalidObject()) ) p := New(rootCtx, WithLimit[*testItem, testItem](1), diff --git a/internal/query/client_test.go b/internal/query/client_test.go index 1b7260750..e178c7b98 100644 --- a/internal/query/client_test.go +++ b/internal/query/client_test.go @@ -22,6 +22,8 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/trace" ) +var errEmpty = errors.New("") + func TestCreateSession(t *testing.T) { t.Run("HappyWay", func(t *testing.T) { xtest.TestManyTimes(t, func(t testing.TB) { @@ -198,7 +200,7 @@ func TestDo(t *testing.T) { }), func(ctx context.Context, s query.Session) error { counter++ if counter < 10 { - return xerrors.Retryable(errors.New("")) + return xerrors.Retryable(errEmpty) } return nil @@ -246,7 +248,7 @@ func TestDoTx(t *testing.T) { }), func(ctx context.Context, tx query.TxActor) error { counter++ if counter < 10 { - return xerrors.Retryable(errors.New("")) + return xerrors.Retryable(errEmpty) } return nil diff --git a/internal/query/result_set_test.go b/internal/query/result_set_test.go index 93f0491bf..00eb4d4f6 100644 --- a/internal/query/result_set_test.go +++ b/internal/query/result_set_test.go @@ -630,6 +630,7 @@ func TestResultSetNext(t *testing.T) { return nil, xerrors.WithStackTrace(err) } if resultSetIndex := part.GetResultSetIndex(); resultSetIndex != 0 { + //nolint:goerr113 return nil, xerrors.WithStackTrace(fmt.Errorf( "critical violation of the logic: wrong result set index: %d != %d", resultSetIndex, 0, @@ -731,6 +732,7 @@ func TestResultSetNext(t *testing.T) { return nil, xerrors.WithStackTrace(err) } if resultSetIndex := part.GetResultSetIndex(); resultSetIndex != 0 { + //nolint:goerr113 return nil, xerrors.WithStackTrace(fmt.Errorf( "critical violation of the logic: wrong result set index: %d != %d", resultSetIndex, 0, diff --git a/internal/query/scanner/named.go b/internal/query/scanner/named.go index 07f31aa94..3790b6181 100644 --- a/internal/query/scanner/named.go +++ b/internal/query/scanner/named.go @@ -25,7 +25,7 @@ func NamedRef(columnName string, destinationValueReference interface{}) (dst Nam dst.name = columnName v := reflect.TypeOf(destinationValueReference) if v.Kind() != reflect.Ptr { - panic(fmt.Errorf("%T is not reference type", destinationValueReference)) + panic(fmt.Errorf("%T is not reference type", destinationValueReference)) //nolint:goerr113 } dst.ref = destinationValueReference diff --git a/internal/ratelimiter/client.go b/internal/ratelimiter/client.go index c1db4c0ce..7820a5c11 100644 --- a/internal/ratelimiter/client.go +++ b/internal/ratelimiter/client.go @@ -20,8 +20,8 @@ import ( ) var ( - errUnknownAcquireType = xerrors.Wrap(errors.New("unknown acquire type")) - errNilClient = xerrors.Wrap(errors.New("ratelimiter client is not initialized")) + errUnknownAcquireType = xerrors.Wrap(errors.New("unknown acquire type")) //nolint:goerr113 + errNilClient = xerrors.Wrap(errors.New("ratelimiter client is not initialized")) //nolint:goerr113 ) type Client struct { diff --git a/internal/repeater/repeater_test.go b/internal/repeater/repeater_test.go index 6749ac19a..68fc83864 100644 --- a/internal/repeater/repeater_test.go +++ b/internal/repeater/repeater_test.go @@ -2,7 +2,7 @@ package repeater import ( "context" - "fmt" + "errors" "runtime" "testing" "time" @@ -10,6 +10,8 @@ import ( "github.com/jonboulle/clockwork" ) +var errForceWithLogBackoff = errors.New("special error for force with log backoff") + func TestRepeaterNoWakeUpsAfterStop(t *testing.T) { var ( interval = time.Millisecond @@ -85,7 +87,7 @@ func TestRepeaterForceLogBackoff(t *testing.T) { lastWakeUp = fakeClock.Now() wakeUps++ - return fmt.Errorf("special error for force with log backoff") + return errForceWithLogBackoff }, WithClock(fakeClock)) defer r.Stop() diff --git a/internal/scheme/client.go b/internal/scheme/client.go index 154c44eed..74a5c3489 100644 --- a/internal/scheme/client.go +++ b/internal/scheme/client.go @@ -17,8 +17,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/trace" ) -//nolint:gofumpt -//nolint:nolintlint +//nolint:gofumpt,nolintlint,goerr113 var errNilClient = xerrors.Wrap(errors.New("scheme client is not initialized")) type Client struct { diff --git a/internal/scheme/helpers/check_exists.go b/internal/scheme/helpers/check_exists.go index 534d12b36..279738456 100644 --- a/internal/scheme/helpers/check_exists.go +++ b/internal/scheme/helpers/check_exists.go @@ -19,6 +19,7 @@ func IsDirectoryExists(ctx context.Context, c schemeClient, directory string) ( exists bool, _ error, ) { if !strings.HasPrefix(directory, c.Database()) { + //nolint:goerr113 return false, xerrors.WithStackTrace(fmt.Errorf( "path '%s' must be inside database '%s'", directory, c.Database(), @@ -45,6 +46,7 @@ func IsDirectoryExists(ctx context.Context, c schemeClient, directory string) ( continue } if t := d.Children[i].Type; t != scheme.EntryDirectory { + //nolint:goerr113 return false, xerrors.WithStackTrace(fmt.Errorf( "entry '%s' in path '%s' is not a directory: %s", childDirectory, parentDirectory, t.String(), @@ -61,11 +63,13 @@ func IsEntryExists(ctx context.Context, c schemeClient, absPath string, entryTyp exists bool, _ error, ) { if !strings.HasPrefix(absPath, c.Database()) { + //nolint:goerr113 return false, xerrors.WithStackTrace(fmt.Errorf( "entry path '%s' must be inside database '%s'", absPath, c.Database(), )) } else if absPath == c.Database() { + //nolint:goerr113 return false, xerrors.WithStackTrace(fmt.Errorf( "entry path '%s' cannot be equals database name '%s'", absPath, c.Database(), @@ -95,6 +99,7 @@ func IsEntryExists(ctx context.Context, c schemeClient, absPath string, entryTyp } } + //nolint:goerr113 return false, xerrors.WithStackTrace(fmt.Errorf( "entry type of '%s' (%s) in path '%s' is not corresponds to %v", entryName, childrenType, directory, entryTypes, diff --git a/internal/scheme/helpers/check_exists_test.go b/internal/scheme/helpers/check_exists_test.go index 265346cae..72591d8b4 100644 --- a/internal/scheme/helpers/check_exists_test.go +++ b/internal/scheme/helpers/check_exists_test.go @@ -48,7 +48,7 @@ func (c isDirectoryExistsSchemeClient) ListDirectory(ctx context.Context, path s }, nil } - return d, fmt.Errorf("path '%s' not found in '%s'", path, c) + return d, fmt.Errorf("path '%s' not found in '%s'", path, c) //nolint:goerr113 } func TestIsDirectoryExists(t *testing.T) { @@ -176,7 +176,7 @@ func (c isTableExistsSchemeClient) ListDirectory(ctx context.Context, path strin } } - return d, fmt.Errorf("path '%s' not found in '%s'", path, c) + return d, fmt.Errorf("path '%s' not found in '%s'", path, c) //nolint:goerr113 } func TestIsTableExists(t *testing.T) { diff --git a/internal/scripting/client.go b/internal/scripting/client.go index 92b88b895..5a5da5d4a 100644 --- a/internal/scripting/client.go +++ b/internal/scripting/client.go @@ -29,7 +29,7 @@ import ( //nolint:gofumpt //nolint:nolintlint var ( - errNilClient = xerrors.Wrap(errors.New("scripting client is not initialized")) + errNilClient = xerrors.Wrap(errors.New("scripting client is not initialized")) //nolint:goerr113 ) type ( diff --git a/internal/table/client_test.go b/internal/table/client_test.go index 82b7eb6af..83bdeb247 100644 --- a/internal/table/client_test.go +++ b/internal/table/client_test.go @@ -31,6 +31,8 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/trace" ) +var errLimitOverflow = errors.New("stub session: limit overflow") + func TestSessionPoolCreateAbnormalResult(t *testing.T) { xtest.TestManyTimes(t, func(t testing.TB) { limit := 100 @@ -446,7 +448,7 @@ func TestSessionPoolRacyGet(t *testing.T) { return } if s != expSession { - err = fmt.Errorf("unexpected session: %v; want %v", s, expSession) + err = fmt.Errorf("unexpected session: %v; want %v", s, expSession) //nolint:goerr113 return } @@ -895,7 +897,7 @@ func (s *StubBuilder) createSession(ctx context.Context) (session *session, err s.mu.WithLock(func() { if s.Limit > 0 && s.actual == s.Limit { - err = fmt.Errorf("stub session: limit overflow") + err = errLimitOverflow } }) if err != nil { diff --git a/internal/table/errors.go b/internal/table/errors.go index 4ba5473f0..73174c6cd 100644 --- a/internal/table/errors.go +++ b/internal/table/errors.go @@ -9,6 +9,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" ) +//nolint:goerr113 var ( errNilClient = xerrors.Wrap(errors.New("table client is not initialized")) diff --git a/internal/table/retry_test.go b/internal/table/retry_test.go index 008633786..bb50b2d64 100644 --- a/internal/table/retry_test.go +++ b/internal/table/retry_test.go @@ -2,6 +2,7 @@ package table import ( "context" + "errors" "fmt" "io" "testing" @@ -20,6 +21,15 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/testutil" ) +var ( + errWhoa = errors.New("whoa") + errTest = errors.New("test error") + errCustom = errors.New("custom error") + errNoSession = xerrors.Wrap(fmt.Errorf("no session")) //nolint:goerr113 + errUnexpectedSession = xerrors.Wrap(fmt.Errorf("unexpected session")) //nolint:goerr113 + errSessionOverflow = xerrors.Wrap(fmt.Errorf("session overflow")) //nolint:goerr113 +) + func TestRetryerBackoffRetryCancelation(t *testing.T) { for _, testErr := range []error{ // Errors leading to Wait repeat. @@ -197,7 +207,7 @@ func TestRetryerImmediateReturn(t *testing.T) { fmt.Errorf("wrap transport error: %w", xerrors.Transport( grpcStatus.Error(grpcCodes.PermissionDenied, ""), )), - fmt.Errorf("whoa"), + errWhoa, } { t.Run("", func(t *testing.T) { defer func() { @@ -258,7 +268,7 @@ func TestRetryContextDeadline(t *testing.T) { errs := []error{ io.EOF, context.DeadlineExceeded, - fmt.Errorf("test error"), + errTest, xerrors.Transport( grpcStatus.Error(grpcCodes.Canceled, ""), ), @@ -390,7 +400,7 @@ func TestRetryWithCustomErrors(t *testing.T) { { error: &CustomError{ Err: retry.RetryableError( - fmt.Errorf("custom error"), + errCustom, retry.WithDeleteSession(), ), }, @@ -538,9 +548,3 @@ func (s *singleSession) Put(_ context.Context, x *session) error { return nil } - -var ( - errNoSession = xerrors.Wrap(fmt.Errorf("no session")) - errUnexpectedSession = xerrors.Wrap(fmt.Errorf("unexpected session")) - errSessionOverflow = xerrors.Wrap(fmt.Errorf("session overflow")) -) diff --git a/internal/table/scanner/result.go b/internal/table/scanner/result.go index fdebc2859..cfbd67950 100644 --- a/internal/table/scanner/result.go +++ b/internal/table/scanner/result.go @@ -15,6 +15,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/table/stats" ) +//nolint:goerr113 var errAlreadyClosed = xerrors.Wrap(errors.New("result closed early")) type baseResult struct { diff --git a/internal/table/scanner/scanner.go b/internal/table/scanner/scanner.go index 8a3effb2b..7896758c7 100644 --- a/internal/table/scanner/scanner.go +++ b/internal/table/scanner/scanner.go @@ -1167,7 +1167,7 @@ func (s *valueScanner) errorf(depth int, f string, args ...interface{}) error { if s.err != nil { return s.err } - s.err = xerrors.WithStackTrace(fmt.Errorf(f, args...), xerrors.WithSkipDepth(depth+1)) + s.err = xerrors.WithStackTrace(fmt.Errorf(f, args...), xerrors.WithSkipDepth(depth+1)) //nolint:goerr113 return s.err } diff --git a/internal/table/scanner/scanner_data_test.go b/internal/table/scanner/scanner_data_test.go index f47fffbac..1aeeb9479 100644 --- a/internal/table/scanner/scanner_data_test.go +++ b/internal/table/scanner/scanner_data_test.go @@ -26,7 +26,7 @@ type intIncScanner int64 func (s *intIncScanner) Scan(src interface{}) error { v, ok := src.(int64) if !ok { - return fmt.Errorf("wrong type: %T, exp: int64", src) + return fmt.Errorf("wrong type: %T, exp: int64", src) //nolint:goerr113 } *s = intIncScanner(v + 10) @@ -38,7 +38,7 @@ type dateScanner time.Time func (s *dateScanner) Scan(src interface{}) error { v, ok := src.(time.Time) if !ok { - return fmt.Errorf("wrong type: %T, exp: time.Time", src) + return fmt.Errorf("wrong type: %T, exp: time.Time", src) //nolint:goerr113 } *s = dateScanner(v) diff --git a/internal/table/session_test.go b/internal/table/session_test.go index 710bd57b6..9b1c19275 100644 --- a/internal/table/session_test.go +++ b/internal/table/session_test.go @@ -31,6 +31,8 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/testutil" ) +var errAny = errors.New("any error") + func TestSessionKeepAlive(t *testing.T) { ctx, cancel := xcontext.WithCancel(context.Background()) defer cancel() @@ -60,7 +62,7 @@ func TestSessionKeepAlive(t *testing.T) { if err != nil { t.Fatal(err) } - e = fmt.Errorf("any error") + e = errAny err = s.KeepAlive(ctx) if err == nil { t.Fatal(err) @@ -119,7 +121,7 @@ func TestSessionDescribeTable(t *testing.T) { } { - e = fmt.Errorf("any error") + e = errAny _, err = s.DescribeTable(ctx, "") if err == nil { t.Fatal(err) @@ -463,7 +465,7 @@ func TestCreateTableRegression(t *testing.T) { }, } if !proto.Equal(exp, act.(proto.Message)) { - //nolint:revive + //nolint:revive,goerr113 return nil, fmt.Errorf("proto's not equal: \n\nact: %v\n\nexp: %s\n\n", act, exp) } diff --git a/internal/table/transaction.go b/internal/table/transaction.go index a07576196..910cc0a95 100644 --- a/internal/table/transaction.go +++ b/internal/table/transaction.go @@ -19,6 +19,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/trace" ) +//nolint:goerr113 var ( errTxAlreadyCommitted = xerrors.Wrap(fmt.Errorf("transaction already committed")) errTxRollbackedEarly = xerrors.Wrap(fmt.Errorf("transaction rollbacked early")) diff --git a/internal/topic/retriable_error.go b/internal/topic/retriable_error.go index 744aca97a..87a7eedb8 100644 --- a/internal/topic/retriable_error.go +++ b/internal/topic/retriable_error.go @@ -86,7 +86,7 @@ func CheckRetryMode(err error, settings RetrySettings, retriesDuration time.Dura case PublicRetryDecisionStop: isRetriable = false default: - panic(fmt.Errorf("unexpected retry decision: %v", decision)) + panic(fmt.Errorf("unexpected retry decision: %v", decision)) //nolint:goerr113 } if !isRetriable { diff --git a/internal/topic/topicreaderinternal/batch.go b/internal/topic/topicreaderinternal/batch.go index e8e00ad01..cc45abb43 100644 --- a/internal/topic/topicreaderinternal/batch.go +++ b/internal/topic/topicreaderinternal/batch.go @@ -10,8 +10,10 @@ import ( ) var ( - errBadSessionWhileMessageBatchCreate = xerrors.Wrap(errors.New("ydb: bad session while messages batch create")) //nolint:lll - errBadMessageOffsetWhileMessageBatchCreate = xerrors.Wrap(errors.New("ydb: bad message offset while messages batch create")) //nolint:lll + errBadSessionWhileMessageBatchCreate = xerrors.Wrap(errors.New("ydb: bad session while messages batch create")) //nolint:lll,goerr113 + errBadMessageOffsetWhileMessageBatchCreate = xerrors.Wrap(errors.New("ydb: bad message offset while messages batch create")) //nolint:lll,goerr113 + errBadPartitionSessionForMerge = xerrors.Wrap(errors.New("ydb: bad partition session for merge")) //nolint:lll,goerr113 + errBadOffsetIntervalForMerge = xerrors.Wrap(errors.New("ydb: bad offset interval for merge")) //nolint:lll,goerr113 ) // PublicBatch is ordered group of message from one partition @@ -134,11 +136,11 @@ func (m *PublicBatch) append(b *PublicBatch) (*PublicBatch, error) { } if res.commitRange.partitionSession != b.commitRange.partitionSession { - return nil, xerrors.WithStackTrace(errors.New("ydb: bad partition session for merge")) + return nil, xerrors.WithStackTrace(errBadPartitionSessionForMerge) } if res.commitRange.commitOffsetEnd != b.commitRange.commitOffsetStart { - return nil, xerrors.WithStackTrace(errors.New("ydb: bad offset interval for merge")) + return nil, xerrors.WithStackTrace(errBadOffsetIntervalForMerge) } res.Messages = append(res.Messages, b.Messages...) diff --git a/internal/topic/topicreaderinternal/batcher.go b/internal/topic/topicreaderinternal/batcher.go index 8eaa5eb6b..6202bf953 100644 --- a/internal/topic/topicreaderinternal/batcher.go +++ b/internal/topic/topicreaderinternal/batcher.go @@ -12,6 +12,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsync" ) +//nolint:goerr113 var errBatcherPopConcurency = xerrors.Wrap(errors.New("ydb: batch pop concurency, internal state error")) type batcher struct { diff --git a/internal/topic/topicreaderinternal/batcher_test.go b/internal/topic/topicreaderinternal/batcher_test.go index c926e7076..65b3ade38 100644 --- a/internal/topic/topicreaderinternal/batcher_test.go +++ b/internal/topic/topicreaderinternal/batcher_test.go @@ -15,6 +15,8 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/xtest" ) +var errSecondClose = errors.New("second close") + func TestBatcher_PushBatch(t *testing.T) { session1 := &partitionSession{} session2 := &partitionSession{} @@ -223,7 +225,6 @@ func TestBatcher_Pop(t *testing.T) { xtest.TestManyTimesWithName(t, "CloseBatcherWhilePopWait", func(t testing.TB) { ctx := xtest.Context(t) - testErr := errors.New("test") b := newBatcher() b.notifyAboutNewMessages() @@ -236,7 +237,7 @@ func TestBatcher_Pop(t *testing.T) { close(popGoroutineStarted) _, popErr := b.Pop(ctx, batcherGetOptions{MinCount: 1}) - require.ErrorIs(t, popErr, testErr) + require.ErrorIs(t, popErr, errTest) close(popFinished) }() @@ -247,8 +248,8 @@ func TestBatcher_Pop(t *testing.T) { return len(b.hasNewMessages) == 0 }) - require.NoError(t, b.Close(testErr)) - require.Error(t, b.Close(errors.New("second close"))) + require.NoError(t, b.Close(errTest)) + require.Error(t, b.Close(errSecondClose)) xtest.WaitChannelClosed(t, popFinished) }) diff --git a/internal/topic/topicreaderinternal/committer.go b/internal/topic/topicreaderinternal/committer.go index f0fa1c425..7bc44c34a 100644 --- a/internal/topic/topicreaderinternal/committer.go +++ b/internal/topic/topicreaderinternal/committer.go @@ -16,6 +16,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/trace" ) +//nolint:goerr113 var ( ErrCommitDisabled = xerrors.Wrap(errors.New("ydb: commits disabled")) ErrWrongCommitOrderInSyncMode = xerrors.Wrap(errors.New("ydb: wrong commit order in sync mode")) diff --git a/internal/topic/topicreaderinternal/committer_test.go b/internal/topic/topicreaderinternal/committer_test.go index 7bf444d62..096c5a1b5 100644 --- a/internal/topic/topicreaderinternal/committer_test.go +++ b/internal/topic/topicreaderinternal/committer_test.go @@ -17,6 +17,8 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/trace" ) +var errTestCommitterClosed = errors.New("test committer closed") + func TestCommitterCommit(t *testing.T) { t.Run("CommitWithCancelledContext", func(t *testing.T) { ctx := xtest.Context(t) @@ -381,7 +383,7 @@ func newTestCommitter(ctx context.Context, t testing.TB) *committer { return nil }) t.Cleanup(func() { - if err := res.Close(ctx, errors.New("test comitter closed")); err != nil { + if err := res.Close(ctx, errTestCommitterClosed); err != nil { require.ErrorIs(t, err, background.ErrAlreadyClosed) } }) diff --git a/internal/topic/topicreaderinternal/message.go b/internal/topic/topicreaderinternal/message.go index 13cc98f0c..fc4b3e67a 100644 --- a/internal/topic/topicreaderinternal/message.go +++ b/internal/topic/topicreaderinternal/message.go @@ -12,6 +12,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" ) +//nolint:goerr113 var errMessageWasReadEarly = xerrors.Wrap(errors.New("ydb: message was read early")) // ErrPublicUnexpectedCodec return when try to read message content with unknown codec diff --git a/internal/topic/topicreaderinternal/message_content_pool_test.go b/internal/topic/topicreaderinternal/message_content_pool_test.go index 60a6477f5..e74f1fc02 100644 --- a/internal/topic/topicreaderinternal/message_content_pool_test.go +++ b/internal/topic/topicreaderinternal/message_content_pool_test.go @@ -2,7 +2,6 @@ package topicreaderinternal import ( "bytes" - "errors" "io" "testing" @@ -132,22 +131,20 @@ func TestCallbackOnReaderContent(t *testing.T) { require.True(t, called) }) t.Run("ReturnErrorFromReader", func(t *testing.T) { - testErr := errors.New("test") - err := callbackOnReaderContent(globalReadMessagePool, ErrReader(testErr), 0, nil) - require.ErrorIs(t, err, testErr) + err := callbackOnReaderContent(globalReadMessagePool, ErrReader(errTest), 0, nil) + require.ErrorIs(t, err, errTest) require.False(t, xerrors.IsYdb(err)) }) t.Run("ReturnErrorFromUnmarshal", func(t *testing.T) { - testErr := errors.New("test") err := callbackOnReaderContent( globalReadMessagePool, ErrReader(io.EOF), 0, testFuncConsumer(func(data []byte) error { - return testErr + return errTest }), ) - require.ErrorIs(t, err, testErr) + require.ErrorIs(t, err, errTest) require.False(t, xerrors.IsYdb(err)) }) } diff --git a/internal/topic/topicreaderinternal/one_time_reader_test.go b/internal/topic/topicreaderinternal/one_time_reader_test.go index 003b3c2e5..d532371cb 100644 --- a/internal/topic/topicreaderinternal/one_time_reader_test.go +++ b/internal/topic/topicreaderinternal/one_time_reader_test.go @@ -2,7 +2,6 @@ package topicreaderinternal import ( "bytes" - "errors" "io" "testing" "testing/iotest" @@ -47,11 +46,10 @@ func TestOneTimeReader(t *testing.T) { require.NoError(t, r.err) }) t.Run("ReadAfterError", func(t *testing.T) { - testErr := errors.New("err") - r := &oneTimeReader{err: testErr} + r := &oneTimeReader{err: errTest} dstBuf := make([]byte, 2) n, err := r.Read(dstBuf) - require.Equal(t, testErr, err) + require.Equal(t, errTest, err) require.Equal(t, 0, n) }) t.Run("InnerErr", func(t *testing.T) { diff --git a/internal/topic/topicreaderinternal/partition_session.go b/internal/topic/topicreaderinternal/partition_session.go index 781de1782..507b674c7 100644 --- a/internal/topic/topicreaderinternal/partition_session.go +++ b/internal/topic/topicreaderinternal/partition_session.go @@ -112,7 +112,7 @@ func (c *partitionSessionStorage) Add(session *partitionSession) error { defer c.m.Unlock() if _, ok := c.sessions[session.partitionSessionID]; ok { - return xerrors.WithStackTrace(fmt.Errorf("session id already existed: %v", session.partitionSessionID)) + return xerrors.WithStackTrace(fmt.Errorf("session id already existed: %v", session.partitionSessionID)) //nolint:lll,goerr113 } c.sessions[session.partitionSessionID] = &sessionInfo{Session: session} @@ -125,7 +125,7 @@ func (c *partitionSessionStorage) Get(id partitionSessionID) (*partitionSession, partitionInfo, has := c.sessions[id] if !has || partitionInfo.Session == nil { - return nil, xerrors.WithStackTrace(fmt.Errorf("ydb: read undefined partition session with id: %v", id)) + return nil, xerrors.WithStackTrace(fmt.Errorf("ydb: read undefined partition session with id: %v", id)) //nolint:lll,goerr113 } return partitionInfo.Session, nil @@ -145,7 +145,7 @@ func (c *partitionSessionStorage) Remove(id partitionSessionID) (*partitionSessi c.compactionNeedLock(now) - return nil, xerrors.WithStackTrace(fmt.Errorf("ydb: delete undefined partition session with id: %v", id)) + return nil, xerrors.WithStackTrace(fmt.Errorf("ydb: delete undefined partition session with id: %v", id)) //nolint:lll,goerr113 } func (c *partitionSessionStorage) compactionNeedLock(now time.Time) { diff --git a/internal/topic/topicreaderinternal/reader.go b/internal/topic/topicreaderinternal/reader.go index bc2dc865c..3b408864a 100644 --- a/internal/topic/topicreaderinternal/reader.go +++ b/internal/topic/topicreaderinternal/reader.go @@ -17,6 +17,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/trace" ) +//nolint:goerr113 var ( errUnconnected = xerrors.Retryable(xerrors.Wrap( errors.New("ydb: first connection attempt not finished"), diff --git a/internal/topic/topicreaderinternal/reader_test.go b/internal/topic/topicreaderinternal/reader_test.go index 4b73a9559..03552ff62 100644 --- a/internal/topic/topicreaderinternal/reader_test.go +++ b/internal/topic/topicreaderinternal/reader_test.go @@ -2,7 +2,6 @@ package topicreaderinternal import ( "context" - "errors" "runtime" "testing" @@ -19,21 +18,20 @@ func TestReader_Close(t *testing.T) { mc := gomock.NewController(t) defer mc.Finish() - testErr := errors.New("test error") readerContext, readerCancel := xcontext.WithCancel(context.Background()) baseReader := NewMockbatchedStreamReader(mc) baseReader.EXPECT().ReadMessageBatch(gomock.Any(), ReadMessageBatchOptions{}).Do(func(_, _ interface{}) { <-readerContext.Done() - }).Return(nil, testErr) + }).Return(nil, errTest) baseReader.EXPECT().ReadMessageBatch( gomock.Any(), ReadMessageBatchOptions{batcherGetOptions: batcherGetOptions{MaxCount: 1, MinCount: 1}}, ).Do(func(_, _ interface{}) { <-readerContext.Done() - }).Return(nil, testErr) + }).Return(nil, errTest) baseReader.EXPECT().Commit(gomock.Any(), gomock.Any()).Do(func(_, _ interface{}) { <-readerContext.Done() - }).Return(testErr) + }).Return(errTest) baseReader.EXPECT().CloseWithError(gomock.Any(), gomock.Any()).Do(func(_, _ interface{}) { readerCancel() }) @@ -137,9 +135,8 @@ func TestReader_Commit(t *testing.T) { }, } - testErr := errors.New("test err") - baseReader.EXPECT().Commit(gomock.Any(), expectedRangeErr).Return(testErr) - require.ErrorIs(t, reader.Commit(context.Background(), &PublicMessage{commitRange: expectedRangeErr}), testErr) + baseReader.EXPECT().Commit(gomock.Any(), expectedRangeErr).Return(errTest) + require.ErrorIs(t, reader.Commit(context.Background(), &PublicMessage{commitRange: expectedRangeErr}), errTest) }) t.Run("CommitFromOtherReader", func(t *testing.T) { diff --git a/internal/topic/topicreaderinternal/stream_reader_impl.go b/internal/topic/topicreaderinternal/stream_reader_impl.go index 8eb91e0ac..5a614785b 100644 --- a/internal/topic/topicreaderinternal/stream_reader_impl.go +++ b/internal/topic/topicreaderinternal/stream_reader_impl.go @@ -24,10 +24,13 @@ import ( const defaultBufferSize = 1024 * 1024 +//nolint:goerr113 var ( PublicErrCommitSessionToExpiredSession = xerrors.Wrap(errors.New("ydb: commit to expired session")) errCommitWithNilPartitionSession = xerrors.Wrap(errors.New("ydb: commit with nil partition session")) + errNotStarted = xerrors.Wrap(errors.New("not started: can be started only after initialize from constructor")) //nolint:lll + errAlreadyStarted = xerrors.Wrap(errors.New("already started")) ) type partitionSessionID = rawtopicreader.PartitionSessionID @@ -167,7 +170,7 @@ func newTopicStreamReaderStopped( func (r *topicStreamReaderImpl) WaitInit(_ context.Context) error { if !r.started { - return errors.New("not started: can be started only after initialize from constructor") + return errNotStarted } return nil @@ -230,7 +233,7 @@ func (r *topicStreamReaderImpl) consumeMessagesUntilBatch( case item.IsRawMessage(): r.sendRawMessageToChannelUnblocked(item.RawMessage) default: - return nil, xerrors.WithStackTrace(fmt.Errorf("ydb: unexpected item type from batcher: %#v", item)) + return nil, xerrors.WithStackTrace(fmt.Errorf("ydb: unexpected item type from batcher: %#v", item)) //nolint:lll,goerr113 } } } @@ -281,7 +284,7 @@ func (r *topicStreamReaderImpl) consumeRawMessageFromBuffer(ctx context.Context) r.onPartitionSessionStatusResponseFromBuffer(ctx, m) default: _ = r.CloseWithError(ctx, xerrors.WithStackTrace( - fmt.Errorf("ydb: unexpected server message from buffer: %v", reflect.TypeOf(msg))), + fmt.Errorf("ydb: unexpected server message from buffer: %v", reflect.TypeOf(msg))), //nolint:goerr113 ) } } @@ -432,7 +435,7 @@ func (r *topicStreamReaderImpl) setStarted() error { defer r.m.Unlock() if r.started { - return xerrors.WithStackTrace(errors.New("already started")) + return xerrors.WithStackTrace(errAlreadyStarted) } r.started = true @@ -458,12 +461,12 @@ func (r *topicStreamReaderImpl) initSession() (err error) { } if status := resp.StatusData(); !status.Status.IsSuccess() { - return xerrors.WithStackTrace(fmt.Errorf("bad status on initial error: %v (%v)", status.Status, status.Issues)) + return xerrors.WithStackTrace(fmt.Errorf("bad status on initial error: %v (%v)", status.Status, status.Issues)) //nolint:lll,goerr113 } initResp, ok := resp.(*rawtopicreader.InitResponse) if !ok { - return xerrors.WithStackTrace(fmt.Errorf("bad message type on session init: %v (%v)", resp, reflect.TypeOf(resp))) + return xerrors.WithStackTrace(fmt.Errorf("bad message type on session init: %v (%v)", resp, reflect.TypeOf(resp))) //nolint:lll,goerr113 } r.readConnectionID = initResp.SessionID @@ -507,7 +510,7 @@ func (r *topicStreamReaderImpl) readMessagesLoop(ctx context.Context) { if !status.Status.IsSuccess() { _ = r.CloseWithError(ctx, xerrors.WithStackTrace( - fmt.Errorf("ydb: bad status from pq grpc stream: %v, %v", status.Status, status.Issues.String()), + fmt.Errorf("ydb: bad status from pq grpc stream: %v, %v", status.Status, status.Issues.String()), //nolint:lll,goerr113 ), ) } @@ -542,10 +545,10 @@ func (r *topicStreamReaderImpl) readMessagesLoop(ctx context.Context) { trace.TopicOnReaderUnknownGrpcMessage( r.cfg.Trace, r.readConnectionID, - xerrors.WithStackTrace(xerrors.Wrap(fmt.Errorf( - "ydb: unexpected message type in stream reader: %v", - reflect.TypeOf(serverMessage), - ))), + xerrors.WithStackTrace(xerrors.Wrap( + fmt.Errorf("ydb: unexpected message type in stream reader: %v", //nolint:goerr113 + reflect.TypeOf(serverMessage), + ))), ) } } diff --git a/internal/topic/topicreaderinternal/stream_reader_impl_test.go b/internal/topic/topicreaderinternal/stream_reader_impl_test.go index 22fb2997a..7ae8fc121 100644 --- a/internal/topic/topicreaderinternal/stream_reader_impl_test.go +++ b/internal/topic/topicreaderinternal/stream_reader_impl_test.go @@ -23,6 +23,12 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/trace" ) +var ( + errTestFinished = errors.New("test finished") + errTestReaderClosed = errors.New("test reader closed") + errMockReaderClosed = errors.New("mock reader closed") +) + func TestTopicStreamReaderImpl_BufferCounterOnStopPartition(t *testing.T) { table := []struct { name string @@ -1039,7 +1045,7 @@ func newTopicReaderTestEnv(t testing.TB) streamEnv { defer cancel() close(env.stopReadEvents) - _ = env.reader.CloseWithError(ctx, errors.New("test finished")) + _ = env.reader.CloseWithError(ctx, errTestFinished) require.NoError(t, cleanupTimeout.Err()) xtest.WaitChannelClosed(t, streamClosed) }) @@ -1067,7 +1073,7 @@ func (e *streamEnv) readerReceiveWaitClose(callback func()) { callback() } <-e.ctx.Done() - }).Return(nil, errors.New("test reader closed")) + }).Return(nil, errTestReaderClosed) } func (e *streamEnv) SendFromServer(msg rawtopicreader.ServerMessage) { @@ -1106,7 +1112,7 @@ readMessages: case <-e.ctx.Done(): return nil, e.ctx.Err() case <-e.stopReadEvents: - return nil, xerrors.Wrap(errors.New("mock reader closed")) + return nil, xerrors.Wrap(errMockReaderClosed) case res := <-e.messagesFromServerToClient: if res.waitOnly { continue readMessages diff --git a/internal/topic/topicreaderinternal/stream_reconnector.go b/internal/topic/topicreaderinternal/stream_reconnector.go index f43044624..d7f685bcf 100644 --- a/internal/topic/topicreaderinternal/stream_reconnector.go +++ b/internal/topic/topicreaderinternal/stream_reconnector.go @@ -21,6 +21,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/trace" ) +//nolint:goerr113 var ( errReconnectRequestOutdated = xerrors.Wrap(errors.New("ydb: reconnect request outdated")) errReconnect = xerrors.Wrap(errors.New("ydb: reconnect to topic grpc stream")) @@ -413,7 +414,7 @@ func (r *readerReconnector) handlePanic() { p := recover() if p != nil { - _ = r.CloseWithError(context.Background(), xerrors.WithStackTrace(fmt.Errorf("handled panic: %v", p))) + _ = r.CloseWithError(context.Background(), xerrors.WithStackTrace(fmt.Errorf("handled panic: %v", p))) //nolint:lll,goerr113 } } diff --git a/internal/topic/topicreaderinternal/stream_reconnector_test.go b/internal/topic/topicreaderinternal/stream_reconnector_test.go index d9034066e..89959d2ad 100644 --- a/internal/topic/topicreaderinternal/stream_reconnector_test.go +++ b/internal/topic/topicreaderinternal/stream_reconnector_test.go @@ -18,7 +18,17 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/trace" ) -var _ batchedStreamReader = &readerReconnector{} // check interface implementation +var ( + _ batchedStreamReader = &readerReconnector{} // check interface implementation + + errUnexpectedCallTestConnect = errors.New("unexpected call test connect function") + errTest = errors.New("test") + errTest1 = errors.New("test1") + errTest2 = errors.New("test2") + errTestReconnect = errors.New("test reconnect error") + errUnexpectedCall = errors.New("unexpected call") + errStart = errors.New("start-error") +) func TestTopicReaderReconnectorReadMessageBatch(t *testing.T) { t.Run("Ok", func(t *testing.T) { @@ -59,7 +69,7 @@ func TestTopicReaderReconnectorReadMessageBatch(t *testing.T) { readerConnect: func(ctx context.Context) (batchedStreamReader, error) { connectCalled++ if connectCalled > 1 { - return nil, errors.New("unexpected call test connect function") + return nil, errUnexpectedCallTestConnect } return baseReader, nil @@ -83,12 +93,12 @@ func TestTopicReaderReconnectorReadMessageBatch(t *testing.T) { baseReader1 := NewMockbatchedStreamReader(mc) baseReader1.EXPECT().ReadMessageBatch(gomock.Any(), opts).MinTimes(1). - Return(nil, xerrors.Retryable(errors.New("test1"))) + Return(nil, xerrors.Retryable(errTest1)) baseReader1.EXPECT().CloseWithError(gomock.Any(), gomock.Any()).Return(nil) baseReader2 := NewMockbatchedStreamReader(mc) baseReader2.EXPECT().ReadMessageBatch(gomock.Any(), opts).MinTimes(1). - Return(nil, xerrors.Retryable(errors.New("test2"))) + Return(nil, xerrors.Retryable(errTest2)) baseReader2.EXPECT().CloseWithError(gomock.Any(), gomock.Any()).Return(nil) baseReader3 := NewMockbatchedStreamReader(mc) @@ -137,14 +147,13 @@ func TestTopicReaderReconnectorReadMessageBatch(t *testing.T) { streamErr: errUnconnected, } reconnector.initChannelsAndClock() - testErr := errors.New("test'") go func() { - _ = reconnector.CloseWithError(context.Background(), testErr) + _ = reconnector.CloseWithError(context.Background(), errTest) }() _, err := reconnector.ReadMessageBatch(context.Background(), ReadMessageBatchOptions{}) - require.ErrorIs(t, err, testErr) + require.ErrorIs(t, err, errTest) }) } @@ -152,8 +161,6 @@ func TestTopicReaderReconnectorCommit(t *testing.T) { type k struct{} ctx := context.WithValue(context.Background(), k{}, "v") expectedCommitRange := commitRange{commitOffsetStart: 1, commitOffsetEnd: 2} - testErr := errors.New("test") - testErr2 := errors.New("test2") t.Run("AllOk", func(t *testing.T) { mc := gomock.NewController(t) defer mc.Finish() @@ -173,25 +180,25 @@ func TestTopicReaderReconnectorCommit(t *testing.T) { stream.EXPECT().Commit(gomock.Any(), gomock.Any()).Do(func(ctx context.Context, offset commitRange) { require.Equal(t, "v", ctx.Value(k{})) require.Equal(t, expectedCommitRange, offset) - }).Return(testErr) + }).Return(errTest) reconnector := &readerReconnector{streamVal: stream, tracer: &trace.Topic{}} reconnector.initChannelsAndClock() - require.ErrorIs(t, reconnector.Commit(ctx, expectedCommitRange), testErr) + require.ErrorIs(t, reconnector.Commit(ctx, expectedCommitRange), errTest) }) t.Run("StreamErr", func(t *testing.T) { - reconnector := &readerReconnector{streamErr: testErr, tracer: &trace.Topic{}} + reconnector := &readerReconnector{streamErr: errTest, tracer: &trace.Topic{}} reconnector.initChannelsAndClock() - require.ErrorIs(t, reconnector.Commit(ctx, expectedCommitRange), testErr) + require.ErrorIs(t, reconnector.Commit(ctx, expectedCommitRange), errTest) }) t.Run("CloseErr", func(t *testing.T) { - reconnector := &readerReconnector{closedErr: testErr, tracer: &trace.Topic{}} + reconnector := &readerReconnector{closedErr: errTest, tracer: &trace.Topic{}} reconnector.initChannelsAndClock() - require.ErrorIs(t, reconnector.Commit(ctx, expectedCommitRange), testErr) + require.ErrorIs(t, reconnector.Commit(ctx, expectedCommitRange), errTest) }) t.Run("StreamAndCloseErr", func(t *testing.T) { - reconnector := &readerReconnector{closedErr: testErr, streamErr: testErr2, tracer: &trace.Topic{}} + reconnector := &readerReconnector{closedErr: errTest, streamErr: errTest2, tracer: &trace.Topic{}} reconnector.initChannelsAndClock() - require.ErrorIs(t, reconnector.Commit(ctx, expectedCommitRange), testErr) + require.ErrorIs(t, reconnector.Commit(ctx, expectedCommitRange), errTest) }) } @@ -225,7 +232,7 @@ func TestTopicReaderReconnectorConnectionLoop(t *testing.T) { }, }, { - err: xerrors.Retryable(errors.New("test reconnect error")), + err: xerrors.Retryable(errTestReconnect), }, { callback: func(ctx context.Context) (batchedStreamReader, error) { @@ -238,7 +245,7 @@ func TestTopicReaderReconnectorConnectionLoop(t *testing.T) { callback: func(ctx context.Context) (batchedStreamReader, error) { t.Fatal() - return nil, errors.New("unexpected call") + return nil, errUnexpectedCall }, }, }...) @@ -299,7 +306,7 @@ func TestTopicReaderReconnectorStart(t *testing.T) { {callback: func(ctx context.Context) (batchedStreamReader, error) { t.Error() - return nil, errors.New("unexpected call") + return nil, errUnexpectedCall }}, }...) @@ -406,7 +413,7 @@ func TestTopicReaderReconnectorFireReconnectOnRetryableError(t *testing.T) { // OK } - reconnector.fireReconnectOnRetryableError(stream, xerrors.Wrap(errors.New("test"))) + reconnector.fireReconnectOnRetryableError(stream, xerrors.Wrap(errTest)) select { case <-reconnector.reconnectFromBadStream: t.Fatal() @@ -414,11 +421,10 @@ func TestTopicReaderReconnectorFireReconnectOnRetryableError(t *testing.T) { // OK } - testErr := errors.New("test") - reconnector.fireReconnectOnRetryableError(stream, xerrors.Retryable(testErr)) + reconnector.fireReconnectOnRetryableError(stream, xerrors.Retryable(errTest)) res := <-reconnector.reconnectFromBadStream require.Equal(t, stream, res.oldReader) - require.ErrorIs(t, res.reason, testErr) + require.ErrorIs(t, res.reason, errTest) }) t.Run("SkipWriteOnFullChannel", func(t *testing.T) { @@ -442,7 +448,7 @@ func TestTopicReaderReconnectorFireReconnectOnRetryableError(t *testing.T) { } // write skipped - reconnector.fireReconnectOnRetryableError(stream, xerrors.Retryable(errors.New("test"))) + reconnector.fireReconnectOnRetryableError(stream, xerrors.Retryable(errTest)) res := <-reconnector.reconnectFromBadStream require.Nil(t, res.oldReader) }) @@ -450,19 +456,18 @@ func TestTopicReaderReconnectorFireReconnectOnRetryableError(t *testing.T) { func TestTopicReaderReconnectorReconnectWithError(t *testing.T) { ctx := context.Background() - testErr := errors.New("test") reconnector := &readerReconnector{ connectTimeout: value.InfiniteDuration, readerConnect: func(ctx context.Context) (batchedStreamReader, error) { - return nil, testErr + return nil, errTest }, - streamErr: errors.New("start-error"), + streamErr: errStart, tracer: &trace.Topic{}, } reconnector.initChannelsAndClock() err := reconnector.reconnect(ctx, nil, nil) - require.ErrorIs(t, err, testErr) - require.ErrorIs(t, reconnector.streamErr, testErr) + require.ErrorIs(t, err, errTest) + require.ErrorIs(t, reconnector.streamErr, errTest) } type readerConnectFuncAnswer struct { diff --git a/internal/topic/topicwriterinternal/encoders.go b/internal/topic/topicwriterinternal/encoders.go index a1ca73ad9..973ecb104 100644 --- a/internal/topic/topicwriterinternal/encoders.go +++ b/internal/topic/topicwriterinternal/encoders.go @@ -43,7 +43,7 @@ func (e *EncoderMap) CreateLazyEncodeWriter(codec rawtopiccommon.Codec, target i return encoderCreator(target) } - return nil, xerrors.WithStackTrace(xerrors.Wrap(fmt.Errorf("ydb: unexpected codec '%v' for encode message", codec))) + return nil, xerrors.WithStackTrace(xerrors.Wrap(fmt.Errorf("ydb: unexpected codec '%v' for encode message", codec))) //nolint:lll,goerr113 } func (e *EncoderMap) GetSupportedCodecs() rawtopiccommon.SupportedCodecs { diff --git a/internal/topic/topicwriterinternal/message.go b/internal/topic/topicwriterinternal/message.go index 5c618e631..603be5a45 100644 --- a/internal/topic/topicwriterinternal/message.go +++ b/internal/topic/topicwriterinternal/message.go @@ -12,7 +12,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" ) -var errNoRawContent = xerrors.Wrap(errors.New("ydb: internal state error - no raw message content")) +var errNoRawContent = xerrors.Wrap(errors.New("ydb: internal state error - no raw message content")) //nolint:lll,goerr113 type PublicMessage struct { SeqNo int64 diff --git a/internal/topic/topicwriterinternal/queue.go b/internal/topic/topicwriterinternal/queue.go index a834f7071..9c1733e83 100644 --- a/internal/topic/topicwriterinternal/queue.go +++ b/internal/topic/topicwriterinternal/queue.go @@ -12,6 +12,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/xsync" ) +//nolint:goerr113 var ( errCloseClosedMessageQueue = xerrors.Wrap(errors.New("ydb: close closed message queue")) errAckOnClosedMessageQueue = xerrors.Wrap(errors.New("ydb: ack on closed message queue")) @@ -136,7 +137,7 @@ func (q *messageQueue) addMessageNeedLock( } if _, ok := q.messagesByOrder[messageIndex]; ok { - panic(fmt.Errorf("ydb: bad internal state os message queue - already exists with index: %v", messageIndex)) + panic(fmt.Errorf("ydb: bad internal state os message queue - already exists with index: %v", messageIndex)) //nolint:lll,goerr113 } q.messagesByOrder[messageIndex] = mess diff --git a/internal/topic/topicwriterinternal/queue_test.go b/internal/topic/topicwriterinternal/queue_test.go index d62e6b16e..7e5f7bef5 100644 --- a/internal/topic/topicwriterinternal/queue_test.go +++ b/internal/topic/topicwriterinternal/queue_test.go @@ -17,6 +17,11 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/xcontext" ) +var ( + errTest = errors.New("test") + errSecond = errors.New("second") +) + func TestMessageQueue_AddMessages(t *testing.T) { t.Run("Empty", func(t *testing.T) { q := newMessageQueue() @@ -38,7 +43,7 @@ func TestMessageQueue_AddMessages(t *testing.T) { }) t.Run("Closed", func(t *testing.T) { q := newMessageQueue() - _ = q.Close(errors.New("err")) + _ = q.Close(errTest) require.Error(t, q.AddMessages(newTestMessagesWithContent(1, 3, 5))) }) t.Run("OverflowIndex", func(t *testing.T) { @@ -78,10 +83,9 @@ func TestMessageQueue_CheckMessages(t *testing.T) { func TestMessageQueue_Close(t *testing.T) { q := newMessageQueue() - testErr := errors.New("test") - require.NoError(t, q.Close(testErr)) - require.Error(t, q.Close(errors.New("second"))) - require.Equal(t, testErr, q.closedErr) + require.NoError(t, q.Close(errTest)) + require.Error(t, q.Close(errSecond)) + require.Equal(t, errTest, q.closedErr) require.True(t, q.closed) <-q.closedChan } @@ -207,7 +211,7 @@ func TestMessageQueue_GetMessages(t *testing.T) { t.Run("CallOnClosedQueue", func(t *testing.T) { q := newMessageQueue() - _ = q.Close(errors.New("test")) + _ = q.Close(errTest) _, err := q.GetMessagesForSend(ctx) require.Error(t, err) }) @@ -225,11 +229,10 @@ func TestMessageQueue_GetMessages(t *testing.T) { waitGetMessageStarted(&q) - testErr := errors.New("test") - require.NoError(t, q.Close(testErr)) + require.NoError(t, q.Close(errTest)) <-gotErr - require.ErrorIs(t, err, testErr) + require.ErrorIs(t, err, errTest) }) } @@ -417,7 +420,7 @@ func TestRegressionIssue1038_ReceiveAckAfterCloseQueue(t *testing.T) { require.NoError(t, q.AddMessages(newTestMessagesWithContent(1))) counter++ - require.NoError(t, q.Close(errors.New("test err"))) + require.NoError(t, q.Close(errTest)) require.ErrorIs(t, q.AcksReceived([]rawtopicwriter.WriteAck{ { SeqNo: 1, diff --git a/internal/topic/topicwriterinternal/writer_grpc_mock_test.go b/internal/topic/topicwriterinternal/writer_grpc_mock_test.go index 1a977cb75..8737fa337 100644 --- a/internal/topic/topicwriterinternal/writer_grpc_mock_test.go +++ b/internal/topic/topicwriterinternal/writer_grpc_mock_test.go @@ -20,6 +20,12 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/topic/topicwriter" ) +var ( + errFirstMessage = errors.New("first message must be init message") + errFailReadMsgBlock = errors.New("failed to read messages block") + errReceiveZeroMsgBlock = errors.New("received zero messages block") +) + func TestRegressionOperationUnavailableIssue1007(t *testing.T) { xtest.TestManyTimes(t, func(t testing.TB) { e := fixenv.New(t) @@ -58,7 +64,7 @@ func (t *topicWriterOperationUnavailable) StreamWrite(server Ydb_Topic_V1.TopicS } if initMsg.GetInitRequest() == nil { - return errors.New("first message must be init message") + return errFirstMessage } err = server.Send(&Ydb_Topic.StreamWriteMessage_FromServer{ @@ -98,12 +104,12 @@ func (t *topicWriterOperationUnavailable) StreamWrite(server Ydb_Topic_V1.TopicS // wait message block messagesMsg, err := server.Recv() if err != nil { - return errors.New("failed to read messages block") + return errFailReadMsgBlock } if len(messagesMsg.GetClientMessage().(*Ydb_Topic.StreamWriteMessage_FromClient_WriteRequest). WriteRequest.GetMessages()) == 0 { - return errors.New("received zero messages block") + return errReceiveZeroMsgBlock } err = server.Send(&Ydb_Topic.StreamWriteMessage_FromServer{ diff --git a/internal/topic/topicwriterinternal/writer_reconnector.go b/internal/topic/topicwriterinternal/writer_reconnector.go index 66d646291..7b62a3ba2 100644 --- a/internal/topic/topicwriterinternal/writer_reconnector.go +++ b/internal/topic/topicwriterinternal/writer_reconnector.go @@ -30,6 +30,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/trace" ) +//nolint:goerr113 var ( errConnTimeout = xerrors.Wrap(errors.New("ydb: connection timeout")) errStopWriterReconnector = xerrors.Wrap(errors.New("ydb: stop writer reconnector")) @@ -475,7 +476,9 @@ func (w *WriterReconnector) connectWithTimeout(streamLifetimeContext context.Con if p != nil { resCh <- resT{ stream: nil, - err: xerrors.WithStackTrace(xerrors.Wrap(fmt.Errorf("ydb: panic while connect to topic writer: %+v", p))), + err: xerrors.WithStackTrace(xerrors.Wrap( + fmt.Errorf("ydb: panic while connect to topic writer: %+v", p), //nolint:goerr113 + )), } } }() diff --git a/internal/topic/topicwriterinternal/writer_reconnector_test.go b/internal/topic/topicwriterinternal/writer_reconnector_test.go index 70630d74d..988dcb035 100644 --- a/internal/topic/topicwriterinternal/writer_reconnector_test.go +++ b/internal/topic/topicwriterinternal/writer_reconnector_test.go @@ -25,7 +25,15 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/xtest" ) -var testCommonEncoders = NewEncoderMap() +var ( + testCommonEncoders = NewEncoderMap() + errTestStreamClosed = errors.New("test stream closed") + errRetriableOnStrm2 = errors.New("retriable on strm2") + errStrm3 = errors.New("strm3") + errTest1 = errors.New("test-1") + errStopWriterTestEnv = errors.New("stop writer test environment") + errStopTestEnv = errors.New("test: stop test environment") +) func TestWriterImpl_AutoSeq(t *testing.T) { t.Run("OK", func(t *testing.T) { @@ -399,7 +407,6 @@ func TestWriterImpl_Reconnect(t *testing.T) { w := newTestWriterStopped() ctx := xtest.Context(t) - testErr := errors.New("test") connectCalled := false connectCalledChan := make(empty.Chan) @@ -414,13 +421,13 @@ func TestWriterImpl_Reconnect(t *testing.T) { initRequest := testCreateInitRequest(w) strm.EXPECT().Send(&initRequest) - strm.EXPECT().Recv().Return(nil, testErr) + strm.EXPECT().Recv().Return(nil, errTest) strm.EXPECT().CloseSend() w.connectionLoop(ctx) require.True(t, connectCalled) - require.ErrorIs(t, w.background.CloseReason(), testErr) + require.ErrorIs(t, w.background.CloseReason(), errTest) }) xtest.TestManyTimesWithName(t, "ReconnectOnErrors", func(t testing.TB) { @@ -467,7 +474,7 @@ func TestWriterImpl_Reconnect(t *testing.T) { t.Logf("waiting close channel: %v", name) xtest.WaitChannelClosed(t, streamClosed) t.Logf("channel closed: %v", name) - }).Return(nil, errors.New("test stream closed")).MaxTimes(1) + }).Return(nil, errTestStreamClosed).MaxTimes(1) return strm } @@ -480,7 +487,7 @@ func TestWriterImpl_Reconnect(t *testing.T) { Codec: rawtopiccommon.CodecRaw, }).Do(func(_ *rawtopicwriter.WriteRequest) { t.Logf("strm2 sent message and return retriable error") - }).Return(xerrors.Retryable(errors.New("retriable on strm2"))) + }).Return(xerrors.Retryable(errRetriableOnStrm2)) strm3 := newStream("strm3") strm3.EXPECT().Send(&rawtopicwriter.WriteRequest{ @@ -490,13 +497,13 @@ func TestWriterImpl_Reconnect(t *testing.T) { Codec: rawtopiccommon.CodecRaw, }).Do(func(_ *rawtopicwriter.WriteRequest) { t.Logf("strm3 sent message and return unretriable error") - }).Return(errors.New("strm3")) + }).Return(errStrm3) connectsResult := []connectionAttemptContext{ { name: "step-1 connection error", stream: nil, - connectionError: xerrors.Retryable(errors.New("test-1")), + connectionError: xerrors.Retryable(errTest1), }, { name: "step-2 connect and return retryable error on write", @@ -773,7 +780,7 @@ func TestCalculateAllowedCodecs(t *testing.T) { customCodecUnsupported := rawtopiccommon.Codec(rawtopiccommon.CodecCustomerFirst + 1) encoders := NewEncoderMap() encoders.AddEncoder(customCodecSupported, func(writer io.Writer) (io.WriteCloser, error) { - return nil, errors.New("test") + return nil, errTest }) table := []struct { @@ -996,7 +1003,7 @@ func newTestEnv(t testing.TB, options *testEnvOptions) *testEnv { require.NoError(t, res.writer.waitFirstInitResponse(res.ctx)) t.Cleanup(func() { - _ = res.writer.close(context.Background(), errors.New("stop writer test environment")) + _ = res.writer.close(context.Background(), errStopWriterTestEnv) close(res.stopReadEvents) <-streamClosed }) @@ -1015,7 +1022,7 @@ func (e *testEnv) sendFromServer(msg rawtopicwriter.ServerMessage) { func (e *testEnv) receiveMessageHandler() (rawtopicwriter.ServerMessage, error) { select { case <-e.stopReadEvents: - return nil, fmt.Errorf("test: stop test environment") + return nil, errStopTestEnv case res := <-e.sendFromServerChannel: return res.msg, res.err } diff --git a/internal/topic/topicwriterinternal/writer_single_stream.go b/internal/topic/topicwriterinternal/writer_single_stream.go index 4f01c56d1..faa451004 100644 --- a/internal/topic/topicwriterinternal/writer_single_stream.go +++ b/internal/topic/topicwriterinternal/writer_single_stream.go @@ -16,6 +16,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/trace" ) +//nolint:goerr113 var errSingleStreamWriterDoubleClose = xerrors.Wrap(errors.New("ydb: single stream writer impl double closed")) type SingleStreamWriterConfig struct { @@ -135,7 +136,7 @@ func (w *SingleStreamWriter) initStream() (err error) { result, ok := recvMessage.(*rawtopicwriter.InitResult) if !ok { return xerrors.WithStackTrace( - fmt.Errorf("ydb: failed init response message type: %v", reflect.TypeOf(recvMessage)), + fmt.Errorf("ydb: failed init response message type: %v", reflect.TypeOf(recvMessage)), //nolint:goerr113 ) } @@ -203,10 +204,10 @@ func (w *SingleStreamWriter) receiveMessagesLoop(ctx context.Context) { w.cfg.tracer, w.cfg.reconnectorInstanceID, w.SessionID, - xerrors.WithStackTrace(xerrors.Wrap(fmt.Errorf( - "ydb: unexpected message type in stream reader: %v", - reflect.TypeOf(m), - ))), + xerrors.WithStackTrace(xerrors.Wrap( + fmt.Errorf("ydb: unexpected message type in stream reader: %v", //nolint:goerr113 + reflect.TypeOf(m), + ))), ) } } diff --git a/internal/value/time.go b/internal/value/time.go index f8d836098..85375922c 100644 --- a/internal/value/time.go +++ b/internal/value/time.go @@ -63,7 +63,7 @@ func TimestampToTime(n uint64) time.Time { func TzDateToTime(s string) (t time.Time, err error) { ss := strings.Split(s, ",") if len(ss) != 2 { //nolint:gomnd - return t, xerrors.WithStackTrace(fmt.Errorf("not found timezone location in '%s'", s)) + return t, xerrors.WithStackTrace(fmt.Errorf("not found timezone location in '%s'", s)) //nolint:goerr113 } location, err := time.LoadLocation(ss[1]) if err != nil { @@ -80,7 +80,7 @@ func TzDateToTime(s string) (t time.Time, err error) { func TzDatetimeToTime(s string) (t time.Time, err error) { ss := strings.Split(s, ",") if len(ss) != 2 { //nolint:gomnd - return t, xerrors.WithStackTrace(fmt.Errorf("not found timezone location in '%s'", s)) + return t, xerrors.WithStackTrace(fmt.Errorf("not found timezone location in '%s'", s)) //nolint:goerr113 } location, err := time.LoadLocation(ss[1]) if err != nil { @@ -97,7 +97,7 @@ func TzDatetimeToTime(s string) (t time.Time, err error) { func TzTimestampToTime(s string) (t time.Time, err error) { ss := strings.Split(s, ",") if len(ss) != 2 { //nolint:gomnd - return t, xerrors.WithStackTrace(fmt.Errorf("not found timezone location in '%s'", s)) + return t, xerrors.WithStackTrace(fmt.Errorf("not found timezone location in '%s'", s)) //nolint:goerr113 } location, err := time.LoadLocation(ss[1]) if err != nil { diff --git a/internal/value/value.go b/internal/value/value.go index 8052667cf..d6289460c 100644 --- a/internal/value/value.go +++ b/internal/value/value.go @@ -135,7 +135,7 @@ func primitiveValueFromYDB(t types.Primitive, v *Ydb.Value) (Value, error) { case *Ydb.Value_BytesValue: return YSONValue(vv.BytesValue), nil default: - return nil, xerrors.WithStackTrace(fmt.Errorf("uncovered YSON internal type: %T", vv)) + return nil, xerrors.WithStackTrace(fmt.Errorf("uncovered YSON internal type: %T", vv)) //nolint:goerr113 } case types.JSON: @@ -163,7 +163,7 @@ func primitiveValueFromYDB(t types.Primitive, v *Ydb.Value) (Value, error) { return UUIDValue(BigEndianUint128(v.GetHigh_128(), v.GetLow_128())), nil default: - return nil, xerrors.WithStackTrace(fmt.Errorf("uncovered primitive type: %T", t)) + return nil, xerrors.WithStackTrace(fmt.Errorf("uncovered primitive type: %T", t)) //nolint:goerr113 } } @@ -296,7 +296,7 @@ func fromYDB(t *Ydb.Type, v *Ydb.Value) (Value, error) { }, nil default: - return nil, xerrors.WithStackTrace(fmt.Errorf("uncovered type: %T", ttt)) + return nil, xerrors.WithStackTrace(fmt.Errorf("uncovered type: %T", ttt)) //nolint:goerr113 } } diff --git a/internal/xerrors/operation_test.go b/internal/xerrors/operation_test.go index 41d735957..14fd53f38 100644 --- a/internal/xerrors/operation_test.go +++ b/internal/xerrors/operation_test.go @@ -1,6 +1,7 @@ package xerrors import ( + "errors" "fmt" "testing" @@ -9,6 +10,8 @@ import ( "github.com/ydb-platform/ydb-go-genproto/protos/Ydb_Issue" ) +var errTest = errors.New("test") + func TestIsOperationError(t *testing.T) { for _, tt := range []struct { err error @@ -26,9 +29,9 @@ func TestIsOperationError(t *testing.T) { }, { err: Join( - fmt.Errorf("test"), + errTest, &operationError{code: Ydb.StatusIds_BAD_REQUEST}, - Retryable(fmt.Errorf("test")), + Retryable(errTest), ), match: true, }, @@ -45,9 +48,9 @@ func TestIsOperationError(t *testing.T) { }, { err: Join( - fmt.Errorf("test"), + errTest, &operationError{code: Ydb.StatusIds_BAD_REQUEST}, - Retryable(fmt.Errorf("test")), + Retryable(errTest), ), codes: []Ydb.StatusIds_StatusCode{Ydb.StatusIds_BAD_REQUEST}, match: true, @@ -65,9 +68,9 @@ func TestIsOperationError(t *testing.T) { }, { err: Join( - fmt.Errorf("test"), + errTest, &operationError{code: Ydb.StatusIds_BAD_REQUEST}, - Retryable(fmt.Errorf("test")), + Retryable(errTest), ), codes: []Ydb.StatusIds_StatusCode{Ydb.StatusIds_ABORTED}, match: false, diff --git a/internal/xerrors/pessimized_error_test.go b/internal/xerrors/pessimized_error_test.go index 403587849..905492992 100644 --- a/internal/xerrors/pessimized_error_test.go +++ b/internal/xerrors/pessimized_error_test.go @@ -3,13 +3,14 @@ package xerrors import ( "context" "errors" - "fmt" "testing" grpcCodes "google.golang.org/grpc/codes" grpcStatus "google.golang.org/grpc/status" ) +var errUser = errors.New("user error") + func TestMustPessimizeEndpoint(t *testing.T) { for _, test := range []struct { error error @@ -88,7 +89,7 @@ func TestMustPessimizeEndpoint(t *testing.T) { pessimize: false, }, { - error: fmt.Errorf("user error"), + error: errUser, pessimize: false, }, } { diff --git a/internal/xerrors/retryable_test.go b/internal/xerrors/retryable_test.go index fa26e8f6d..527a106da 100644 --- a/internal/xerrors/retryable_test.go +++ b/internal/xerrors/retryable_test.go @@ -1,7 +1,7 @@ package xerrors import ( - "fmt" + "errors" "testing" "github.com/stretchr/testify/require" @@ -10,13 +10,15 @@ import ( grpcStatus "google.golang.org/grpc/status" ) +var errSome = errors.New("some") + func TestRetryableCode(t *testing.T) { for _, tt := range []struct { err error code int32 }{ { - err: Retryable(fmt.Errorf("some")), + err: Retryable(errSome), code: -1, }, { diff --git a/internal/xerrors/stacktrace_test.go b/internal/xerrors/stacktrace_test.go index fa981d847..4dd620d4a 100644 --- a/internal/xerrors/stacktrace_test.go +++ b/internal/xerrors/stacktrace_test.go @@ -2,7 +2,6 @@ package xerrors import ( "errors" - "fmt" "testing" "github.com/stretchr/testify/require" @@ -10,27 +9,33 @@ import ( grpcStatus "google.golang.org/grpc/status" ) +var ( + errFmtErrorf = errors.New("fmt.Errorf") + errFmtErrorPrintf = errors.New("fmt.Errorf Printf") + errErrorsNew = errors.New("errors.New") +) + func TestStackTraceError(t *testing.T) { for _, test := range []struct { error error text string }{ { - error: WithStackTrace(fmt.Errorf("fmt.Errorf")), + error: WithStackTrace(errFmtErrorf), //nolint:lll - text: "fmt.Errorf at `github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors.TestStackTraceError(stacktrace_test.go:19)`", + text: "fmt.Errorf at `github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors.TestStackTraceError(stacktrace_test.go:24)`", }, { - error: WithStackTrace(fmt.Errorf("fmt.Errorf %s", "Printf")), + error: WithStackTrace(errFmtErrorPrintf), //nolint:lll - text: "fmt.Errorf Printf at `github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors.TestStackTraceError(stacktrace_test.go:24)`", + text: "fmt.Errorf Printf at `github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors.TestStackTraceError(stacktrace_test.go:29)`", }, { error: WithStackTrace( - WithStackTrace(errors.New("errors.New")), + WithStackTrace(errErrorsNew), ), //nolint:lll - text: "errors.New at `github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors.TestStackTraceError(stacktrace_test.go:30)` at `github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors.TestStackTraceError(stacktrace_test.go:29)`", + text: "errors.New at `github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors.TestStackTraceError(stacktrace_test.go:35)` at `github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors.TestStackTraceError(stacktrace_test.go:34)`", }, } { t.Run(test.text, func(t *testing.T) { @@ -52,7 +57,7 @@ func TestTransportStackTraceError(t *testing.T) { ), ), //nolint:lll - text: "transport/Aborted (code = 10, source error = \"rpc error: code = Aborted desc = some error\", address: \"example.com\") at `github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors.TestTransportStackTraceError(stacktrace_test.go:48)`", + text: "transport/Aborted (code = 10, source error = \"rpc error: code = Aborted desc = some error\", address: \"example.com\") at `github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors.TestTransportStackTraceError(stacktrace_test.go:53)`", }, { error: WithStackTrace( @@ -63,7 +68,7 @@ func TestTransportStackTraceError(t *testing.T) { ), ), //nolint:lll - text: "transport/Aborted (code = 10, source error = \"rpc error: code = Aborted desc = some error\") at `github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors.TestTransportStackTraceError(stacktrace_test.go:59)` at `github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors.TestTransportStackTraceError(stacktrace_test.go:58)`", + text: "transport/Aborted (code = 10, source error = \"rpc error: code = Aborted desc = some error\") at `github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors.TestTransportStackTraceError(stacktrace_test.go:64)` at `github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors.TestTransportStackTraceError(stacktrace_test.go:63)`", }, { error: WithStackTrace( @@ -76,7 +81,7 @@ func TestTransportStackTraceError(t *testing.T) { ), ), //nolint:lll - text: "transport/Aborted (code = 10, source error = \"rpc error: code = Aborted desc = some error\") at `github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors.TestTransportStackTraceError(stacktrace_test.go:71)` at `github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors.TestTransportStackTraceError(stacktrace_test.go:70)` at `github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors.TestTransportStackTraceError(stacktrace_test.go:69)`", + text: "transport/Aborted (code = 10, source error = \"rpc error: code = Aborted desc = some error\") at `github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors.TestTransportStackTraceError(stacktrace_test.go:76)` at `github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors.TestTransportStackTraceError(stacktrace_test.go:75)` at `github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors.TestTransportStackTraceError(stacktrace_test.go:74)`", }, } { t.Run(test.text, func(t *testing.T) { diff --git a/internal/xerrors/transport_test.go b/internal/xerrors/transport_test.go index d94aa8ee4..8c573b58f 100644 --- a/internal/xerrors/transport_test.go +++ b/internal/xerrors/transport_test.go @@ -42,9 +42,9 @@ func TestIsTransportError(t *testing.T) { { name: xtest.CurrentFileLine(), err: Join( - fmt.Errorf("test"), + errTest, grpcStatus.Error(grpcCodes.Canceled, ""), - Retryable(fmt.Errorf("test")), + Retryable(errTest), ), match: true, }, @@ -76,9 +76,9 @@ func TestIsTransportError(t *testing.T) { { name: xtest.CurrentFileLine(), err: Join( - fmt.Errorf("test"), + errTest, grpcStatus.Error(grpcCodes.Canceled, ""), - Retryable(fmt.Errorf("test")), + Retryable(errTest), ), codes: []grpcCodes.Code{grpcCodes.Canceled}, match: true, @@ -111,9 +111,9 @@ func TestIsTransportError(t *testing.T) { { name: xtest.CurrentFileLine(), err: Join( - fmt.Errorf("test"), + errTest, grpcStatus.Error(grpcCodes.Canceled, ""), - Retryable(fmt.Errorf("test")), + Retryable(errTest), ), codes: []grpcCodes.Code{grpcCodes.Aborted}, match: false, diff --git a/internal/xerrors/ydb_test.go b/internal/xerrors/ydb_test.go index 2e30b90f9..ba6135bfa 100644 --- a/internal/xerrors/ydb_test.go +++ b/internal/xerrors/ydb_test.go @@ -2,7 +2,6 @@ package xerrors import ( "errors" - "fmt" "testing" "github.com/ydb-platform/ydb-go-genproto/protos/Ydb" @@ -10,6 +9,12 @@ import ( grpcStatus "google.golang.org/grpc/status" ) +var ( + errEmpty = errors.New("") + errTestError = errors.New("TestError") + errTestErrorPrintf = errors.New("TestErrorPrintf") +) + func TestIsYdb(t *testing.T) { for _, test := range []struct { error error @@ -28,7 +33,7 @@ func TestIsYdb(t *testing.T) { isYdbError: true, }, { - error: RetryableError(fmt.Errorf("")), + error: RetryableError(errEmpty), isYdbError: false, }, { @@ -40,7 +45,7 @@ func TestIsYdb(t *testing.T) { isYdbError: true, }, { - error: WithStackTrace(RetryableError(fmt.Errorf(""))), + error: WithStackTrace(RetryableError(errEmpty)), isYdbError: false, }, { @@ -52,23 +57,23 @@ func TestIsYdb(t *testing.T) { isYdbError: true, }, { - error: WithStackTrace(WithStackTrace(RetryableError(fmt.Errorf("")))), + error: WithStackTrace(WithStackTrace(RetryableError(errEmpty))), isYdbError: false, }, { - error: fmt.Errorf("TestError%s", "Printf"), + error: errTestErrorPrintf, isYdbError: false, }, { - error: errors.New("TestError"), + error: errTestError, isYdbError: false, }, { - error: Wrap(fmt.Errorf("TestError%s", "Printf")), + error: Wrap(errTestErrorPrintf), isYdbError: true, }, { - error: Wrap(errors.New("TestError")), + error: Wrap(errTestError), isYdbError: true, }, } { diff --git a/internal/xsql/badconn/badconn.go b/internal/xsql/badconn/badconn.go index 54f5deb8c..927007ce0 100644 --- a/internal/xsql/badconn/badconn.go +++ b/internal/xsql/badconn/badconn.go @@ -2,6 +2,7 @@ package badconn import ( "database/sql/driver" + "errors" "io" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" @@ -21,7 +22,7 @@ func (e Error) Error() string { func (e Error) Is(err error) bool { //nolint:nolintlint - if err == driver.ErrBadConn { //nolint:errorlint + if errors.Is(err, driver.ErrBadConn) { return true } diff --git a/internal/xsql/badconn/badconn_test.go b/internal/xsql/badconn/badconn_test.go index 7366542e2..2f65f53a5 100644 --- a/internal/xsql/badconn/badconn_test.go +++ b/internal/xsql/badconn/badconn_test.go @@ -4,7 +4,6 @@ import ( "context" "database/sql/driver" "errors" - "fmt" "io" "testing" @@ -18,104 +17,109 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" ) -var errsToCheck = []error{ - fmt.Errorf("unknown error"), - context.DeadlineExceeded, - context.Canceled, - xerrors.Transport( - //nolint:staticcheck - // ignore SA1019 - //nolint:nolintlint - grpc.ErrClientConnClosing, - ), - xerrors.Transport(grpcStatus.Error(grpcCodes.Canceled, "")), - xerrors.Transport(grpcStatus.Error(grpcCodes.Unknown, "")), - xerrors.Transport(grpcStatus.Error(grpcCodes.InvalidArgument, "")), - xerrors.Transport(grpcStatus.Error(grpcCodes.DeadlineExceeded, "")), - xerrors.Transport(grpcStatus.Error(grpcCodes.NotFound, "")), - xerrors.Transport(grpcStatus.Error(grpcCodes.AlreadyExists, "")), - xerrors.Transport(grpcStatus.Error(grpcCodes.PermissionDenied, "")), - xerrors.Transport(grpcStatus.Error(grpcCodes.ResourceExhausted, "")), - xerrors.Transport(grpcStatus.Error(grpcCodes.FailedPrecondition, "")), - xerrors.Transport(grpcStatus.Error(grpcCodes.Aborted, "")), - xerrors.Transport(grpcStatus.Error(grpcCodes.OutOfRange, "")), - xerrors.Transport(grpcStatus.Error(grpcCodes.Unimplemented, "")), - xerrors.Transport(grpcStatus.Error(grpcCodes.Internal, "")), - xerrors.Transport(grpcStatus.Error(grpcCodes.Unavailable, "")), - xerrors.Retryable( +var ( + errUnknown = errors.New("unknown error") + errRetryable = errors.New("retryable error") + + errsToCheck = []error{ + errUnknown, + context.DeadlineExceeded, + context.Canceled, + xerrors.Transport( + //nolint:staticcheck + // ignore SA1019 + //nolint:nolintlint + grpc.ErrClientConnClosing, + ), + xerrors.Transport(grpcStatus.Error(grpcCodes.Canceled, "")), + xerrors.Transport(grpcStatus.Error(grpcCodes.Unknown, "")), + xerrors.Transport(grpcStatus.Error(grpcCodes.InvalidArgument, "")), + xerrors.Transport(grpcStatus.Error(grpcCodes.DeadlineExceeded, "")), + xerrors.Transport(grpcStatus.Error(grpcCodes.NotFound, "")), + xerrors.Transport(grpcStatus.Error(grpcCodes.AlreadyExists, "")), + xerrors.Transport(grpcStatus.Error(grpcCodes.PermissionDenied, "")), + xerrors.Transport(grpcStatus.Error(grpcCodes.ResourceExhausted, "")), + xerrors.Transport(grpcStatus.Error(grpcCodes.FailedPrecondition, "")), + xerrors.Transport(grpcStatus.Error(grpcCodes.Aborted, "")), + xerrors.Transport(grpcStatus.Error(grpcCodes.OutOfRange, "")), + xerrors.Transport(grpcStatus.Error(grpcCodes.Unimplemented, "")), + xerrors.Transport(grpcStatus.Error(grpcCodes.Internal, "")), xerrors.Transport(grpcStatus.Error(grpcCodes.Unavailable, "")), - xerrors.WithBackoff(backoff.TypeFast), - xerrors.InvalidObject(), - ), - xerrors.Retryable( - grpcStatus.Error(grpcCodes.Unavailable, ""), - xerrors.WithBackoff(backoff.TypeFast), - xerrors.InvalidObject(), - ), - xerrors.Transport(grpcStatus.Error(grpcCodes.DataLoss, "")), - xerrors.Transport(grpcStatus.Error(grpcCodes.Unauthenticated, "")), - xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_STATUS_CODE_UNSPECIFIED), - ), - xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_BAD_REQUEST), - ), - xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_UNAUTHORIZED), - ), - xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_INTERNAL_ERROR), - ), - xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_ABORTED), - ), - xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_UNAVAILABLE), - ), - xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_OVERLOADED), - ), - xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_SCHEME_ERROR), - ), - xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_GENERIC_ERROR), - ), - xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_TIMEOUT), - ), - xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_BAD_SESSION), - ), - xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_PRECONDITION_FAILED), - ), - xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_ALREADY_EXISTS), - ), - xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_NOT_FOUND), - ), - xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_SESSION_EXPIRED), - ), - xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_CANCELLED), - ), - xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_UNDETERMINED), - ), - xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_UNSUPPORTED), - ), - xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_SESSION_BUSY), - ), - xerrors.Retryable(errors.New("retryable error")), - xerrors.Retryable(errors.New("retryable error"), xerrors.InvalidObject()), - io.EOF, - xerrors.WithStackTrace(io.EOF), -} + xerrors.Retryable( + xerrors.Transport(grpcStatus.Error(grpcCodes.Unavailable, "")), + xerrors.WithBackoff(backoff.TypeFast), + xerrors.InvalidObject(), + ), + xerrors.Retryable( + grpcStatus.Error(grpcCodes.Unavailable, ""), + xerrors.WithBackoff(backoff.TypeFast), + xerrors.InvalidObject(), + ), + xerrors.Transport(grpcStatus.Error(grpcCodes.DataLoss, "")), + xerrors.Transport(grpcStatus.Error(grpcCodes.Unauthenticated, "")), + xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_STATUS_CODE_UNSPECIFIED), + ), + xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_BAD_REQUEST), + ), + xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_UNAUTHORIZED), + ), + xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_INTERNAL_ERROR), + ), + xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_ABORTED), + ), + xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_UNAVAILABLE), + ), + xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_OVERLOADED), + ), + xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_SCHEME_ERROR), + ), + xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_GENERIC_ERROR), + ), + xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_TIMEOUT), + ), + xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_BAD_SESSION), + ), + xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_PRECONDITION_FAILED), + ), + xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_ALREADY_EXISTS), + ), + xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_NOT_FOUND), + ), + xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_SESSION_EXPIRED), + ), + xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_CANCELLED), + ), + xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_UNDETERMINED), + ), + xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_UNSUPPORTED), + ), + xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_SESSION_BUSY), + ), + xerrors.Retryable(errRetryable), + xerrors.Retryable(errRetryable, xerrors.InvalidObject()), + io.EOF, + xerrors.WithStackTrace(io.EOF), + } +) func Test_badConnError_Is(t *testing.T) { for _, err := range errsToCheck { diff --git a/internal/xsql/conn.go b/internal/xsql/conn.go index 42d5517e1..a34762912 100644 --- a/internal/xsql/conn.go +++ b/internal/xsql/conn.go @@ -263,7 +263,7 @@ func (c *conn) execContext(ctx context.Context, query string, args []driver.Name return resultNoRows{}, nil default: - return nil, fmt.Errorf("unsupported query mode '%s' for execute query", m) + return nil, fmt.Errorf("unsupported query mode '%s' for execute query", m) //nolint:goerr113 } } @@ -390,7 +390,7 @@ func (c *conn) queryContext(ctx context.Context, query string, args []driver.Nam result: res, }, nil default: - return nil, fmt.Errorf("unsupported query mode '%s' on conn query", m) + return nil, fmt.Errorf("unsupported query mode '%s' on conn query", m) //nolint:goerr113 } } @@ -487,7 +487,7 @@ func (c *conn) BeginTx(ctx context.Context, txOptions driver.TxOptions) (_ drive return nil, badconn.Map( xerrors.WithStackTrace( xerrors.Retryable( - fmt.Errorf("wrong query mode: %s", m.String()), + fmt.Errorf("wrong query mode: %s", m.String()), //nolint:goerr113 xerrors.InvalidObject(), xerrors.WithName("WRONG_QUERY_MODE"), ), @@ -540,7 +540,7 @@ func (c *conn) IsColumnExists(ctx context.Context, tableName, columnName string) return false, xerrors.WithStackTrace(err) } if !tableExists { - return false, xerrors.WithStackTrace(fmt.Errorf("table '%s' not exist", tableName)) + return false, xerrors.WithStackTrace(fmt.Errorf("table '%s' not exist", tableName)) //nolint:goerr113 } err = c.retryIdempotent(ctx, func(ctx context.Context) (err error) { @@ -575,7 +575,7 @@ func (c *conn) GetColumns(ctx context.Context, tableName string) (columns []stri return nil, xerrors.WithStackTrace(err) } if !tableExists { - return nil, xerrors.WithStackTrace(fmt.Errorf("table '%s' not exist", tableName)) + return nil, xerrors.WithStackTrace(fmt.Errorf("table '%s' not exist", tableName)) //nolint:goerr113 } err = c.retryIdempotent(ctx, func(ctx context.Context) (err error) { @@ -606,7 +606,7 @@ func (c *conn) GetColumnType(ctx context.Context, tableName, columnName string) return "", xerrors.WithStackTrace(err) } if !tableExists { - return "", xerrors.WithStackTrace(fmt.Errorf("table '%s' not exist", tableName)) + return "", xerrors.WithStackTrace(fmt.Errorf("table '%s' not exist", tableName)) //nolint:goerr113 } columnExist, err := c.IsColumnExists(ctx, tableName, columnName) @@ -614,6 +614,7 @@ func (c *conn) GetColumnType(ctx context.Context, tableName, columnName string) return "", xerrors.WithStackTrace(err) } if !columnExist { + //nolint:goerr113 return "", xerrors.WithStackTrace(fmt.Errorf("column '%s' not exist in table '%s'", columnName, tableName)) } @@ -649,7 +650,7 @@ func (c *conn) GetPrimaryKeys(ctx context.Context, tableName string) (pkCols []s return nil, xerrors.WithStackTrace(err) } if !tableExists { - return nil, xerrors.WithStackTrace(fmt.Errorf("table '%s' not exist", tableName)) + return nil, xerrors.WithStackTrace(fmt.Errorf("table '%s' not exist", tableName)) //nolint:goerr113 } err = c.retryIdempotent(ctx, func(ctx context.Context) (err error) { @@ -678,7 +679,7 @@ func (c *conn) IsPrimaryKey(ctx context.Context, tableName, columnName string) ( return false, xerrors.WithStackTrace(err) } if !tableExists { - return false, xerrors.WithStackTrace(fmt.Errorf("table '%s' not exist", tableName)) + return false, xerrors.WithStackTrace(fmt.Errorf("table '%s' not exist", tableName)) //nolint:goerr113 } columnExist, err := c.IsColumnExists(ctx, tableName, columnName) @@ -686,6 +687,7 @@ func (c *conn) IsPrimaryKey(ctx context.Context, tableName, columnName string) ( return false, xerrors.WithStackTrace(err) } if !columnExist { + //nolint:goerr113 return false, xerrors.WithStackTrace(fmt.Errorf("column '%s' not exist in table '%s'", columnName, tableName)) } @@ -739,7 +741,7 @@ func (c *conn) getTables(ctx context.Context, absPath string, recursive, exclude } if !d.IsDirectory() && !d.IsDatabase() { - return nil, xerrors.WithStackTrace(fmt.Errorf("'%s' is not a folder", absPath)) + return nil, xerrors.WithStackTrace(fmt.Errorf("'%s' is not a folder", absPath)) //nolint:goerr113 } for i := range d.Children { @@ -791,7 +793,7 @@ func (c *conn) GetTables(ctx context.Context, folder string, recursive, excludeS return tables, nil default: return nil, xerrors.WithStackTrace( - fmt.Errorf("'%s' is not a table or directory (%s)", folder, e.Type.String()), + fmt.Errorf("'%s' is not a table or directory (%s)", folder, e.Type.String()), //nolint:goerr113 ) } } @@ -806,6 +808,7 @@ func (c *conn) GetIndexes(ctx context.Context, tableName string) (indexes []stri return nil, xerrors.WithStackTrace(err) } if !tableExists { + //nolint:goerr113 return nil, xerrors.WithStackTrace(fmt.Errorf("table '%s' not exist", tableName)) } @@ -850,6 +853,7 @@ func (c *conn) GetIndexColumns(ctx context.Context, tableName, indexName string) return nil, xerrors.WithStackTrace(err) } if !tableExists { + //nolint:goerr113 return nil, xerrors.WithStackTrace(fmt.Errorf("table '%s' not exist", tableName)) } @@ -866,6 +870,7 @@ func (c *conn) GetIndexColumns(ctx context.Context, tableName, indexName string) } } + //nolint:goerr113 return xerrors.WithStackTrace(fmt.Errorf("index '%s' not found in table '%s'", indexName, tableName)) }) if err != nil { diff --git a/internal/xsql/dsn.go b/internal/xsql/dsn.go index 508308995..7b6f691a1 100644 --- a/internal/xsql/dsn.go +++ b/internal/xsql/dsn.go @@ -33,12 +33,14 @@ func Parse(dataSourceName string) (opts []config.Option, connectorOpts []Connect if queryMode := info.Params.Get("go_query_mode"); queryMode != "" { mode := QueryModeFromString(queryMode) if mode == UnknownQueryMode { + //nolint:goerr113 return nil, nil, xerrors.WithStackTrace(fmt.Errorf("unknown query mode: %s", queryMode)) } connectorOpts = append(connectorOpts, WithDefaultQueryMode(mode)) } else if queryMode := info.Params.Get("query_mode"); queryMode != "" { mode := QueryModeFromString(queryMode) if mode == UnknownQueryMode { + //nolint:goerr113 return nil, nil, xerrors.WithStackTrace(fmt.Errorf("unknown query mode: %s", queryMode)) } connectorOpts = append(connectorOpts, WithDefaultQueryMode(mode)) @@ -47,6 +49,7 @@ func Parse(dataSourceName string) (opts []config.Option, connectorOpts []Connect for _, queryMode := range strings.Split(fakeTx, ",") { mode := QueryModeFromString(queryMode) if mode == UnknownQueryMode { + //nolint:goerr113 return nil, nil, xerrors.WithStackTrace(fmt.Errorf("unknown query mode: %s", queryMode)) } connectorOpts = append(connectorOpts, WithFakeTx(mode)) @@ -71,6 +74,7 @@ func Parse(dataSourceName string) (opts []config.Option, connectorOpts []Connect } binders = append(binders, WithTablePathPrefix(prefix)) } else { + //nolint:goerr113 return nil, nil, xerrors.WithStackTrace( fmt.Errorf("unknown query rewriter: %s", transformer), ) diff --git a/internal/xsql/errors.go b/internal/xsql/errors.go index 8dbcc7ce9..f2f6d64d2 100644 --- a/internal/xsql/errors.go +++ b/internal/xsql/errors.go @@ -7,6 +7,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" ) +//nolint:goerr113 var ( ErrUnsupported = driver.ErrSkip errDeprecated = driver.ErrSkip diff --git a/internal/xsql/isolation/isolation.go b/internal/xsql/isolation/isolation.go index e7f6a7b9d..1cb27f4d6 100644 --- a/internal/xsql/isolation/isolation.go +++ b/internal/xsql/isolation/isolation.go @@ -26,6 +26,7 @@ func ToYDB(opts driver.TxOptions) (txcControl table.TxOption, err error) { } } + //nolint:goerr113 return nil, xerrors.WithStackTrace(fmt.Errorf( "unsupported transaction options: %+v", opts, )) diff --git a/internal/xsql/stmt.go b/internal/xsql/stmt.go index 6909e55ef..5e353ee41 100644 --- a/internal/xsql/stmt.go +++ b/internal/xsql/stmt.go @@ -44,7 +44,7 @@ func (stmt *stmt) QueryContext(ctx context.Context, args []driver.NamedValue) (_ case DataQueryMode: return stmt.processor.QueryContext(stmt.conn.withKeepInCache(ctx), stmt.query, args) default: - return nil, fmt.Errorf("unsupported query mode '%s' for execute query on prepared statement", m) + return nil, fmt.Errorf("unsupported query mode '%s' for execute query on prepared statement", m) //nolint:goerr113 } } @@ -63,7 +63,7 @@ func (stmt *stmt) ExecContext(ctx context.Context, args []driver.NamedValue) (_ case DataQueryMode: return stmt.processor.ExecContext(stmt.conn.withKeepInCache(ctx), stmt.query, args) default: - return nil, fmt.Errorf("unsupported query mode '%s' for execute query on prepared statement", m) + return nil, fmt.Errorf("unsupported query mode '%s' for execute query on prepared statement", m) //nolint:goerr113 } } diff --git a/internal/xsql/tx.go b/internal/xsql/tx.go index 2a58e2728..540981ed6 100644 --- a/internal/xsql/tx.go +++ b/internal/xsql/tx.go @@ -30,7 +30,7 @@ func (c *conn) beginTx(ctx context.Context, txOptions driver.TxOptions) (current if c.currentTx != nil { return nil, badconn.Map( xerrors.WithStackTrace( - fmt.Errorf("broken conn state: conn=%q already have current tx=%q", + fmt.Errorf("broken conn state: conn=%q already have current tx=%q", //nolint:goerr113 c.ID(), c.currentTx.ID(), ), ), @@ -62,12 +62,12 @@ func (tx *tx) checkTxState() error { return nil } if tx.conn.currentTx == nil { - return fmt.Errorf("broken conn state: tx=%q not related to conn=%q", + return fmt.Errorf("broken conn state: tx=%q not related to conn=%q", //nolint:goerr113 tx.ID(), tx.conn.ID(), ) } - return fmt.Errorf("broken conn state: tx=%s not related to conn=%q (conn have current tx=%q)", + return fmt.Errorf("broken conn state: tx=%s not related to conn=%q (conn have current tx=%q)", //nolint:goerr113 tx.conn.currentTx.ID(), tx.conn.ID(), tx.ID(), ) } @@ -137,7 +137,7 @@ func (tx *tx) QueryContext(ctx context.Context, query string, args []driver.Name return nil, badconn.Map( xerrors.WithStackTrace( xerrors.Retryable( - fmt.Errorf("wrong query mode: %s", m.String()), + fmt.Errorf("wrong query mode: %s", m.String()), //nolint:goerr113 xerrors.InvalidObject(), xerrors.WithName("WRONG_QUERY_MODE"), ), @@ -179,7 +179,7 @@ func (tx *tx) ExecContext(ctx context.Context, query string, args []driver.Named return nil, badconn.Map( xerrors.WithStackTrace( xerrors.Retryable( - fmt.Errorf("wrong query mode: %s", m.String()), + fmt.Errorf("wrong query mode: %s", m.String()), //nolint:goerr113 xerrors.InvalidObject(), xerrors.WithName("WRONG_QUERY_MODE"), ), diff --git a/internal/xsql/unwrap.go b/internal/xsql/unwrap.go index 5f54b0252..5c2f23bc0 100644 --- a/internal/xsql/unwrap.go +++ b/internal/xsql/unwrap.go @@ -16,7 +16,7 @@ func Unwrap[T *sql.DB | *sql.Conn](v T) (connector *Connector, err error) { return dw.c, nil } - return nil, xerrors.WithStackTrace(fmt.Errorf("%T is not a *driverWrapper", d)) + return nil, xerrors.WithStackTrace(fmt.Errorf("%T is not a *driverWrapper", d)) //nolint:goerr113 case *sql.Conn: if err = vv.Raw(func(driverConn interface{}) error { if cc, ok := driverConn.(*conn); ok { @@ -25,13 +25,13 @@ func Unwrap[T *sql.DB | *sql.Conn](v T) (connector *Connector, err error) { return nil } - return xerrors.WithStackTrace(fmt.Errorf("%T is not a *conn", driverConn)) + return xerrors.WithStackTrace(fmt.Errorf("%T is not a *conn", driverConn)) //nolint:goerr113 }); err != nil { return nil, badconn.Map(xerrors.WithStackTrace(err)) } return connector, nil default: - return nil, xerrors.WithStackTrace(fmt.Errorf("unknown type %T for Unwrap", vv)) + return nil, xerrors.WithStackTrace(fmt.Errorf("unknown type %T for Unwrap", vv)) //nolint:goerr113 } } diff --git a/internal/xsync/once_test.go b/internal/xsync/once_test.go index 003e9a7e7..6891f8d75 100644 --- a/internal/xsync/once_test.go +++ b/internal/xsync/once_test.go @@ -11,6 +11,8 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/xtest" ) +var errEmpty = errors.New("") + func TestOnceFunc(t *testing.T) { var ( ctx = xtest.Context(t) @@ -62,27 +64,25 @@ func TestOnceValue(t *testing.T) { wg.Wait() }) t.Run("GetBeforeClose", func(t *testing.T) { - constCloseErr := errors.New("") once := OnceValue(func() *testCloser { return &testCloser{ inited: true, - closeErr: constCloseErr, + closeErr: errEmpty, } }) v := once.Get() require.True(t, v.inited) require.False(t, v.closed) err := once.Close(ctx) - require.ErrorIs(t, err, constCloseErr) + require.ErrorIs(t, err, errEmpty) require.True(t, v.inited) require.True(t, v.closed) }) t.Run("CloseBeforeGet", func(t *testing.T) { - constCloseErr := errors.New("") once := OnceValue(func() *testCloser { return &testCloser{ inited: true, - closeErr: constCloseErr, + closeErr: errEmpty, } }) err := once.Close(ctx) diff --git a/log/field_test.go b/log/field_test.go index af2dfb217..5329b4f18 100644 --- a/log/field_test.go +++ b/log/field_test.go @@ -8,6 +8,11 @@ import ( "github.com/stretchr/testify/require" ) +var ( + errNamed = errors.New("named error") + errError = errors.New("error") +) + type stringerTest string func (s stringerTest) String() string { @@ -27,15 +32,15 @@ func TestField_String(t *testing.T) { {f: Bool("bool", true), want: "true"}, {f: Duration("duration", time.Hour), want: time.Hour.String()}, {f: Strings("strings", []string{"Abc", "Def", "Ghi"}), want: "[Abc Def Ghi]"}, - {f: NamedError("named_error", errors.New("named error")), want: "named error"}, - {f: Error(errors.New("error")), want: "error"}, + {f: NamedError("named_error", errNamed), want: "named error"}, + {f: Error(errError), want: "error"}, {f: Error(nil), want: ""}, {f: Any("any_int", 1), want: "1"}, {f: Any("any_int64", 9223372036854775807), want: "9223372036854775807"}, {f: Any("any_string", "any string"), want: "any string"}, {f: Any("any_bool", true), want: "true"}, {f: Any("any_strings", []string{"Abc", "Def", "Ghi"}), want: "[Abc Def Ghi]"}, - {f: Any("any_error", errors.New("error")), want: "*errors.errorString({error})"}, + {f: Any("any_error", errError), want: "*errors.errorString({error})"}, {f: Any("any_nil", nil), want: ""}, {f: Any("any_in64_ptr", func(v int64) *int64 { return &v }(9223372036854775807)), want: "*int64(9223372036854775807)"}, //nolint:lll {f: Any("any_in64_nil", (*int64)(nil)), want: ""}, @@ -73,7 +78,7 @@ func TestField_AnyValue(t *testing.T) { {name: "string", f: String("any", "any string"), want: "any string"}, {name: "bool", f: Bool("any", true), want: true}, {name: "[]string", f: Strings("any", []string{"Abc", "Def", "Ghi"}), want: []string{"Abc", "Def", "Ghi"}}, - {name: "error", f: Error(errors.New("error")), want: errors.New("error")}, + {name: "error", f: Error(errError), want: errError}, {name: "namedError", f: NamedError("any", nil), want: nil}, {name: "stringer", f: Stringer("any", stringerTest("stringerTest")), want: stringerTest("stringerTest")}, @@ -86,7 +91,7 @@ func TestField_AnyValue(t *testing.T) { {name: "any_string_nil", f: Any("any", (*string)(nil)), want: (*string)(nil)}, {name: "any_bool", f: Any("any", true), want: true}, {name: "any_[]string", f: Any("any", []string{"Abc", "Def", "Ghi"}), want: []string{"Abc", "Def", "Ghi"}}, - {name: "any_error", f: Any("any", errors.New("error")), want: errors.New("error")}, + {name: "any_error", f: Any("any", errError), want: errError}, {name: "struct", f: Any("any", struct{ str string }{str: "test"}), want: struct{ str string }{str: "test"}}, {name: "any_nil", f: Any("any", nil), want: nil}, } { diff --git a/metrics/error_brief_test.go b/metrics/error_brief_test.go index 021dc3b44..107193bd6 100644 --- a/metrics/error_brief_test.go +++ b/metrics/error_brief_test.go @@ -2,7 +2,7 @@ package metrics import ( "context" - "fmt" + "errors" "io" "net" "testing" @@ -16,6 +16,8 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/xtest" ) +var errTest = errors.New("test") + func TestErrorBrief(t *testing.T) { for _, tt := range []struct { name string @@ -49,7 +51,7 @@ func TestErrorBrief(t *testing.T) { }, { name: xtest.CurrentFileLine(), - err: fmt.Errorf("test"), + err: errTest, brief: "unknown", }, { @@ -71,23 +73,23 @@ func TestErrorBrief(t *testing.T) { }, { name: xtest.CurrentFileLine(), - err: xerrors.Retryable(fmt.Errorf("test")), + err: xerrors.Retryable(errTest), brief: "retryable/CUSTOM", }, { name: xtest.CurrentFileLine(), - err: xerrors.Retryable(fmt.Errorf("test"), xerrors.WithName("SomeName")), + err: xerrors.Retryable(errTest, xerrors.WithName("SomeName")), brief: "retryable/SomeName", }, { name: xtest.CurrentFileLine(), - err: xerrors.WithStackTrace(xerrors.Retryable(fmt.Errorf("test"))), + err: xerrors.WithStackTrace(xerrors.Retryable(errTest)), brief: "retryable/CUSTOM", }, { name: xtest.CurrentFileLine(), err: xerrors.WithStackTrace( - xerrors.Retryable(fmt.Errorf("test"), xerrors.WithName("SomeName")), + xerrors.Retryable(errTest, xerrors.WithName("SomeName")), ), brief: "retryable/SomeName", }, @@ -125,7 +127,7 @@ func TestErrorBrief(t *testing.T) { // errors with stack trace { name: xtest.CurrentFileLine(), - err: xerrors.WithStackTrace(fmt.Errorf("test")), + err: xerrors.WithStackTrace(errTest), brief: "unknown", }, { @@ -157,30 +159,30 @@ func TestErrorBrief(t *testing.T) { // joined errors { name: xtest.CurrentFileLine(), - err: xerrors.Join(fmt.Errorf("test")), + err: xerrors.Join(errTest), brief: "unknown", }, { name: xtest.CurrentFileLine(), err: xerrors.Join( - fmt.Errorf("test"), - xerrors.Retryable(fmt.Errorf("test")), + errTest, + xerrors.Retryable(errTest), ), brief: "retryable/CUSTOM", }, { name: xtest.CurrentFileLine(), err: xerrors.Join( - fmt.Errorf("test"), - xerrors.Retryable(fmt.Errorf("test"), xerrors.WithName("SomeName")), + errTest, + xerrors.Retryable(errTest, xerrors.WithName("SomeName")), ), brief: "retryable/SomeName", }, { name: xtest.CurrentFileLine(), err: xerrors.Join( - fmt.Errorf("test"), - xerrors.Retryable(fmt.Errorf("test"), xerrors.WithName("SomeName")), + errTest, + xerrors.Retryable(errTest, xerrors.WithName("SomeName")), grpcStatus.Error(grpcCodes.Unavailable, "test"), ), brief: "transport/Unavailable", @@ -214,7 +216,7 @@ func TestErrorBrief(t *testing.T) { // joined errors with stack trace { name: xtest.CurrentFileLine(), - err: xerrors.Join(xerrors.WithStackTrace(fmt.Errorf("test"))), + err: xerrors.Join(xerrors.WithStackTrace(errTest)), brief: "unknown", }, { @@ -240,7 +242,7 @@ func TestErrorBrief(t *testing.T) { { name: xtest.CurrentFileLine(), err: xerrors.Join( - xerrors.WithStackTrace(fmt.Errorf("test")), + xerrors.WithStackTrace(errTest), xerrors.WithStackTrace(io.EOF), ), brief: "io/EOF", @@ -248,7 +250,7 @@ func TestErrorBrief(t *testing.T) { { name: xtest.CurrentFileLine(), err: xerrors.WithStackTrace(xerrors.Join( - xerrors.WithStackTrace(fmt.Errorf("test")), + xerrors.WithStackTrace(errTest), xerrors.WithStackTrace(io.EOF), )), brief: "io/EOF", diff --git a/query/stats.go b/query/stats.go index f93b8867c..8ed5b9d66 100644 --- a/query/stats.go +++ b/query/stats.go @@ -14,5 +14,5 @@ func Stats(client Client) (*stats.Stats, error) { return c.Stats(), nil } - return nil, xerrors.WithStackTrace(fmt.Errorf("client %T not supported stats", client)) + return nil, xerrors.WithStackTrace(fmt.Errorf("client %T not supported stats", client)) //nolint:goerr113 } diff --git a/retry/budget/errors.go b/retry/budget/errors.go index 0eeb206f5..85665579b 100644 --- a/retry/budget/errors.go +++ b/retry/budget/errors.go @@ -10,7 +10,7 @@ var ( // ErrNoQuota is a special error for no quota provided by external retry budget // // Experimental: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#experimental - ErrNoQuota = xerrors.Wrap(errors.New("no retry quota")) + ErrNoQuota = xerrors.Wrap(errors.New("no retry quota")) //nolint:goerr113 - errClosedBudget = xerrors.Wrap(errors.New("retry budget closed")) + errClosedBudget = xerrors.Wrap(errors.New("retry budget closed")) //nolint:goerr113 ) diff --git a/retry/errors_data_test.go b/retry/errors_data_test.go index b2d5b2819..4ed318d9f 100644 --- a/retry/errors_data_test.go +++ b/retry/errors_data_test.go @@ -2,7 +2,7 @@ package retry import ( "context" - "fmt" + "errors" "github.com/ydb-platform/ydb-go-genproto/protos/Ydb" "google.golang.org/grpc" @@ -28,444 +28,449 @@ const ( nonIdempotent = false ) -var errsToCheck = []struct { - err error // given error - backoff backoff.Type // no backoff (=== no operationStatus), fast backoff, slow backoff - deleteSession bool // close session and delete from pool - canRetry map[idempotency]bool -}{ - { - // retryer given unknown error - we will not operationStatus and will close session - err: fmt.Errorf("unknown error"), - backoff: backoff.TypeNoBackoff, - deleteSession: false, - canRetry: map[idempotency]bool{ - idempotent: false, - nonIdempotent: false, - }, - }, - { - // golang context deadline exceeded - err: context.DeadlineExceeded, - backoff: backoff.TypeNoBackoff, - deleteSession: false, - canRetry: map[idempotency]bool{ - idempotent: false, - nonIdempotent: false, - }, - }, - { - // golang context canceled - err: context.Canceled, - backoff: backoff.TypeNoBackoff, - deleteSession: false, - canRetry: map[idempotency]bool{ - idempotent: false, - nonIdempotent: false, - }, - }, - { - err: xerrors.Transport( - //nolint:staticcheck - // ignore SA1019 - //nolint:nolintlint - grpc.ErrClientConnClosing, - ), - backoff: backoff.TypeFast, - deleteSession: true, - canRetry: map[idempotency]bool{ - idempotent: true, - nonIdempotent: false, - }, - }, - { - err: xerrors.Transport(grpcStatus.Error(grpcCodes.Canceled, "")), - backoff: backoff.TypeFast, - deleteSession: true, - canRetry: map[idempotency]bool{ - idempotent: true, // if client context is not done - nonIdempotent: false, - }, - }, - { - err: xerrors.Transport(grpcStatus.Error(grpcCodes.Unknown, "")), - backoff: backoff.TypeNoBackoff, - deleteSession: true, - canRetry: map[idempotency]bool{ - idempotent: false, - nonIdempotent: false, - }, - }, - { - err: xerrors.Transport(grpcStatus.Error(grpcCodes.InvalidArgument, "")), - backoff: backoff.TypeNoBackoff, - deleteSession: true, - canRetry: map[idempotency]bool{ - idempotent: false, - nonIdempotent: false, - }, - }, - { - err: xerrors.Transport(grpcStatus.Error(grpcCodes.DeadlineExceeded, "")), - backoff: backoff.TypeFast, - deleteSession: true, - canRetry: map[idempotency]bool{ - idempotent: true, // if client context is not done - nonIdempotent: false, - }, - }, - { - err: xerrors.Transport(grpcStatus.Error(grpcCodes.NotFound, "")), - backoff: backoff.TypeNoBackoff, - deleteSession: true, - canRetry: map[idempotency]bool{ - idempotent: false, - nonIdempotent: false, - }, - }, - { - err: xerrors.Transport(grpcStatus.Error(grpcCodes.AlreadyExists, "")), - backoff: backoff.TypeNoBackoff, - deleteSession: true, - canRetry: map[idempotency]bool{ - idempotent: false, - nonIdempotent: false, - }, - }, - { - err: xerrors.Transport(grpcStatus.Error(grpcCodes.PermissionDenied, "")), - backoff: backoff.TypeNoBackoff, - deleteSession: true, - canRetry: map[idempotency]bool{ - idempotent: false, - nonIdempotent: false, - }, - }, - { - err: xerrors.Transport(grpcStatus.Error(grpcCodes.ResourceExhausted, "")), - backoff: backoff.TypeSlow, - deleteSession: false, - canRetry: map[idempotency]bool{ - idempotent: true, - nonIdempotent: true, - }, - }, - { - err: xerrors.Transport(grpcStatus.Error(grpcCodes.FailedPrecondition, "")), - backoff: backoff.TypeNoBackoff, - deleteSession: true, - canRetry: map[idempotency]bool{ - idempotent: false, - nonIdempotent: false, - }, - }, - { - err: xerrors.Transport(grpcStatus.Error(grpcCodes.Aborted, "")), - backoff: backoff.TypeNoBackoff, - deleteSession: true, - canRetry: map[idempotency]bool{ - idempotent: true, - nonIdempotent: true, - }, - }, - { - err: xerrors.Transport(grpcStatus.Error(grpcCodes.OutOfRange, "")), - backoff: backoff.TypeNoBackoff, - deleteSession: false, - canRetry: map[idempotency]bool{ - idempotent: false, - nonIdempotent: false, - }, - }, - { - err: xerrors.Transport(grpcStatus.Error(grpcCodes.Unimplemented, "")), - backoff: backoff.TypeNoBackoff, - deleteSession: true, - canRetry: map[idempotency]bool{ - idempotent: false, - nonIdempotent: false, - }, - }, - { - err: xerrors.Transport(grpcStatus.Error(grpcCodes.Internal, "")), - backoff: backoff.TypeFast, - deleteSession: true, - canRetry: map[idempotency]bool{ - idempotent: true, - nonIdempotent: false, - }, - }, - { - err: xerrors.Transport(grpcStatus.Error(grpcCodes.Unavailable, "")), - backoff: backoff.TypeFast, - deleteSession: true, - canRetry: map[idempotency]bool{ - idempotent: true, - nonIdempotent: false, - }, - }, - { - err: xerrors.Retryable( - xerrors.Transport(grpcStatus.Error(grpcCodes.Unavailable, "")), - xerrors.WithBackoff(backoff.TypeFast), - xerrors.InvalidObject(), - ), - backoff: backoff.TypeFast, - deleteSession: true, - canRetry: map[idempotency]bool{ - idempotent: true, - nonIdempotent: true, - }, - }, - { - err: xerrors.Retryable( - grpcStatus.Error(grpcCodes.Unavailable, ""), - xerrors.WithBackoff(backoff.TypeFast), - xerrors.InvalidObject(), - ), - backoff: backoff.TypeFast, - deleteSession: true, - canRetry: map[idempotency]bool{ - idempotent: true, - nonIdempotent: true, - }, - }, - { - err: xerrors.Transport(grpcStatus.Error(grpcCodes.DataLoss, "")), - backoff: backoff.TypeNoBackoff, - deleteSession: true, - canRetry: map[idempotency]bool{ - idempotent: false, - nonIdempotent: false, - }, - }, - { - err: xerrors.Transport(grpcStatus.Error(grpcCodes.Unauthenticated, "")), - backoff: backoff.TypeNoBackoff, - deleteSession: true, - canRetry: map[idempotency]bool{ - idempotent: false, - nonIdempotent: false, - }, - }, - { - err: xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_STATUS_CODE_UNSPECIFIED), - ), - backoff: backoff.TypeNoBackoff, - deleteSession: false, - canRetry: map[idempotency]bool{ - idempotent: false, - nonIdempotent: false, - }, - }, - { - err: xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_BAD_REQUEST), - ), - backoff: backoff.TypeNoBackoff, - deleteSession: false, - canRetry: map[idempotency]bool{ - idempotent: false, - nonIdempotent: false, - }, - }, - { - err: xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_UNAUTHORIZED), - ), - backoff: backoff.TypeNoBackoff, - deleteSession: false, - canRetry: map[idempotency]bool{ - idempotent: false, - nonIdempotent: false, - }, - }, - { - err: xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_INTERNAL_ERROR), - ), - backoff: backoff.TypeNoBackoff, - deleteSession: false, - canRetry: map[idempotency]bool{ - idempotent: false, - nonIdempotent: false, - }, - }, - { - err: xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_EXTERNAL_ERROR), - ), - backoff: backoff.TypeNoBackoff, - deleteSession: false, - canRetry: map[idempotency]bool{ - idempotent: false, - nonIdempotent: false, - }, - }, - { - err: xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_ABORTED), - ), - backoff: backoff.TypeFast, - deleteSession: false, - canRetry: map[idempotency]bool{ - idempotent: true, - nonIdempotent: true, - }, - }, - { - err: xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_UNAVAILABLE), - ), - backoff: backoff.TypeFast, - deleteSession: false, - canRetry: map[idempotency]bool{ - idempotent: true, - nonIdempotent: true, - }, - }, - { - err: xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_OVERLOADED), - ), - backoff: backoff.TypeSlow, - deleteSession: false, - canRetry: map[idempotency]bool{ - idempotent: true, - nonIdempotent: true, - }, - }, - { - err: xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_SCHEME_ERROR), - ), - backoff: backoff.TypeNoBackoff, - deleteSession: false, - canRetry: map[idempotency]bool{ - idempotent: false, - nonIdempotent: false, - }, - }, - { - err: xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_GENERIC_ERROR), - ), - backoff: backoff.TypeNoBackoff, - deleteSession: false, - canRetry: map[idempotency]bool{ - idempotent: false, - nonIdempotent: false, - }, - }, - { - err: xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_TIMEOUT), - ), - backoff: backoff.TypeNoBackoff, - deleteSession: false, - canRetry: map[idempotency]bool{ - idempotent: false, - nonIdempotent: false, - }, - }, - { - err: xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_BAD_SESSION), - ), - backoff: backoff.TypeNoBackoff, - deleteSession: true, - canRetry: map[idempotency]bool{ - idempotent: true, - nonIdempotent: true, - }, - }, - { - err: xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_PRECONDITION_FAILED), - ), - backoff: backoff.TypeNoBackoff, - deleteSession: false, - canRetry: map[idempotency]bool{ - idempotent: false, - nonIdempotent: false, - }, - }, - { - err: xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_ALREADY_EXISTS), - ), - backoff: backoff.TypeNoBackoff, - deleteSession: false, - canRetry: map[idempotency]bool{ - idempotent: false, - nonIdempotent: false, - }, - }, - { - err: xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_NOT_FOUND), - ), - backoff: backoff.TypeNoBackoff, - deleteSession: false, - canRetry: map[idempotency]bool{ - idempotent: false, - nonIdempotent: false, - }, - }, - { - err: xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_SESSION_EXPIRED), - ), - backoff: backoff.TypeNoBackoff, - deleteSession: true, - canRetry: map[idempotency]bool{ - idempotent: true, - nonIdempotent: false, - }, - }, - { - err: xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_CANCELLED), - ), - backoff: backoff.TypeFast, - deleteSession: false, - canRetry: map[idempotency]bool{ - idempotent: false, - nonIdempotent: false, - }, - }, - { - err: xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_UNDETERMINED), - ), - backoff: backoff.TypeFast, - deleteSession: false, - canRetry: map[idempotency]bool{ - idempotent: true, - nonIdempotent: false, - }, - }, - { - err: xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_UNSUPPORTED), - ), - backoff: backoff.TypeNoBackoff, - deleteSession: false, - canRetry: map[idempotency]bool{ - idempotent: false, - nonIdempotent: false, - }, - }, - { - err: xerrors.Operation( - xerrors.WithStatusCode(Ydb.StatusIds_SESSION_BUSY), - ), - backoff: backoff.TypeFast, - deleteSession: true, - canRetry: map[idempotency]bool{ - idempotent: true, - nonIdempotent: true, - }, - }, -} +var ( + errUnknown = errors.New("unknown error") + errCustom = errors.New("custom error") + + errsToCheck = []struct { + err error // given error + backoff backoff.Type // no backoff (=== no operationStatus), fast backoff, slow backoff + deleteSession bool // close session and delete from pool + canRetry map[idempotency]bool + }{ + { + // retryer given unknown error - we will not operationStatus and will close session + err: errUnknown, + backoff: backoff.TypeNoBackoff, + deleteSession: false, + canRetry: map[idempotency]bool{ + idempotent: false, + nonIdempotent: false, + }, + }, + { + // golang context deadline exceeded + err: context.DeadlineExceeded, + backoff: backoff.TypeNoBackoff, + deleteSession: false, + canRetry: map[idempotency]bool{ + idempotent: false, + nonIdempotent: false, + }, + }, + { + // golang context canceled + err: context.Canceled, + backoff: backoff.TypeNoBackoff, + deleteSession: false, + canRetry: map[idempotency]bool{ + idempotent: false, + nonIdempotent: false, + }, + }, + { + err: xerrors.Transport( + //nolint:staticcheck + // ignore SA1019 + //nolint:nolintlint + grpc.ErrClientConnClosing, + ), + backoff: backoff.TypeFast, + deleteSession: true, + canRetry: map[idempotency]bool{ + idempotent: true, + nonIdempotent: false, + }, + }, + { + err: xerrors.Transport(grpcStatus.Error(grpcCodes.Canceled, "")), + backoff: backoff.TypeFast, + deleteSession: true, + canRetry: map[idempotency]bool{ + idempotent: true, // if client context is not done + nonIdempotent: false, + }, + }, + { + err: xerrors.Transport(grpcStatus.Error(grpcCodes.Unknown, "")), + backoff: backoff.TypeNoBackoff, + deleteSession: true, + canRetry: map[idempotency]bool{ + idempotent: false, + nonIdempotent: false, + }, + }, + { + err: xerrors.Transport(grpcStatus.Error(grpcCodes.InvalidArgument, "")), + backoff: backoff.TypeNoBackoff, + deleteSession: true, + canRetry: map[idempotency]bool{ + idempotent: false, + nonIdempotent: false, + }, + }, + { + err: xerrors.Transport(grpcStatus.Error(grpcCodes.DeadlineExceeded, "")), + backoff: backoff.TypeFast, + deleteSession: true, + canRetry: map[idempotency]bool{ + idempotent: true, // if client context is not done + nonIdempotent: false, + }, + }, + { + err: xerrors.Transport(grpcStatus.Error(grpcCodes.NotFound, "")), + backoff: backoff.TypeNoBackoff, + deleteSession: true, + canRetry: map[idempotency]bool{ + idempotent: false, + nonIdempotent: false, + }, + }, + { + err: xerrors.Transport(grpcStatus.Error(grpcCodes.AlreadyExists, "")), + backoff: backoff.TypeNoBackoff, + deleteSession: true, + canRetry: map[idempotency]bool{ + idempotent: false, + nonIdempotent: false, + }, + }, + { + err: xerrors.Transport(grpcStatus.Error(grpcCodes.PermissionDenied, "")), + backoff: backoff.TypeNoBackoff, + deleteSession: true, + canRetry: map[idempotency]bool{ + idempotent: false, + nonIdempotent: false, + }, + }, + { + err: xerrors.Transport(grpcStatus.Error(grpcCodes.ResourceExhausted, "")), + backoff: backoff.TypeSlow, + deleteSession: false, + canRetry: map[idempotency]bool{ + idempotent: true, + nonIdempotent: true, + }, + }, + { + err: xerrors.Transport(grpcStatus.Error(grpcCodes.FailedPrecondition, "")), + backoff: backoff.TypeNoBackoff, + deleteSession: true, + canRetry: map[idempotency]bool{ + idempotent: false, + nonIdempotent: false, + }, + }, + { + err: xerrors.Transport(grpcStatus.Error(grpcCodes.Aborted, "")), + backoff: backoff.TypeNoBackoff, + deleteSession: true, + canRetry: map[idempotency]bool{ + idempotent: true, + nonIdempotent: true, + }, + }, + { + err: xerrors.Transport(grpcStatus.Error(grpcCodes.OutOfRange, "")), + backoff: backoff.TypeNoBackoff, + deleteSession: false, + canRetry: map[idempotency]bool{ + idempotent: false, + nonIdempotent: false, + }, + }, + { + err: xerrors.Transport(grpcStatus.Error(grpcCodes.Unimplemented, "")), + backoff: backoff.TypeNoBackoff, + deleteSession: true, + canRetry: map[idempotency]bool{ + idempotent: false, + nonIdempotent: false, + }, + }, + { + err: xerrors.Transport(grpcStatus.Error(grpcCodes.Internal, "")), + backoff: backoff.TypeFast, + deleteSession: true, + canRetry: map[idempotency]bool{ + idempotent: true, + nonIdempotent: false, + }, + }, + { + err: xerrors.Transport(grpcStatus.Error(grpcCodes.Unavailable, "")), + backoff: backoff.TypeFast, + deleteSession: true, + canRetry: map[idempotency]bool{ + idempotent: true, + nonIdempotent: false, + }, + }, + { + err: xerrors.Retryable( + xerrors.Transport(grpcStatus.Error(grpcCodes.Unavailable, "")), + xerrors.WithBackoff(backoff.TypeFast), + xerrors.InvalidObject(), + ), + backoff: backoff.TypeFast, + deleteSession: true, + canRetry: map[idempotency]bool{ + idempotent: true, + nonIdempotent: true, + }, + }, + { + err: xerrors.Retryable( + grpcStatus.Error(grpcCodes.Unavailable, ""), + xerrors.WithBackoff(backoff.TypeFast), + xerrors.InvalidObject(), + ), + backoff: backoff.TypeFast, + deleteSession: true, + canRetry: map[idempotency]bool{ + idempotent: true, + nonIdempotent: true, + }, + }, + { + err: xerrors.Transport(grpcStatus.Error(grpcCodes.DataLoss, "")), + backoff: backoff.TypeNoBackoff, + deleteSession: true, + canRetry: map[idempotency]bool{ + idempotent: false, + nonIdempotent: false, + }, + }, + { + err: xerrors.Transport(grpcStatus.Error(grpcCodes.Unauthenticated, "")), + backoff: backoff.TypeNoBackoff, + deleteSession: true, + canRetry: map[idempotency]bool{ + idempotent: false, + nonIdempotent: false, + }, + }, + { + err: xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_STATUS_CODE_UNSPECIFIED), + ), + backoff: backoff.TypeNoBackoff, + deleteSession: false, + canRetry: map[idempotency]bool{ + idempotent: false, + nonIdempotent: false, + }, + }, + { + err: xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_BAD_REQUEST), + ), + backoff: backoff.TypeNoBackoff, + deleteSession: false, + canRetry: map[idempotency]bool{ + idempotent: false, + nonIdempotent: false, + }, + }, + { + err: xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_UNAUTHORIZED), + ), + backoff: backoff.TypeNoBackoff, + deleteSession: false, + canRetry: map[idempotency]bool{ + idempotent: false, + nonIdempotent: false, + }, + }, + { + err: xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_INTERNAL_ERROR), + ), + backoff: backoff.TypeNoBackoff, + deleteSession: false, + canRetry: map[idempotency]bool{ + idempotent: false, + nonIdempotent: false, + }, + }, + { + err: xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_EXTERNAL_ERROR), + ), + backoff: backoff.TypeNoBackoff, + deleteSession: false, + canRetry: map[idempotency]bool{ + idempotent: false, + nonIdempotent: false, + }, + }, + { + err: xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_ABORTED), + ), + backoff: backoff.TypeFast, + deleteSession: false, + canRetry: map[idempotency]bool{ + idempotent: true, + nonIdempotent: true, + }, + }, + { + err: xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_UNAVAILABLE), + ), + backoff: backoff.TypeFast, + deleteSession: false, + canRetry: map[idempotency]bool{ + idempotent: true, + nonIdempotent: true, + }, + }, + { + err: xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_OVERLOADED), + ), + backoff: backoff.TypeSlow, + deleteSession: false, + canRetry: map[idempotency]bool{ + idempotent: true, + nonIdempotent: true, + }, + }, + { + err: xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_SCHEME_ERROR), + ), + backoff: backoff.TypeNoBackoff, + deleteSession: false, + canRetry: map[idempotency]bool{ + idempotent: false, + nonIdempotent: false, + }, + }, + { + err: xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_GENERIC_ERROR), + ), + backoff: backoff.TypeNoBackoff, + deleteSession: false, + canRetry: map[idempotency]bool{ + idempotent: false, + nonIdempotent: false, + }, + }, + { + err: xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_TIMEOUT), + ), + backoff: backoff.TypeNoBackoff, + deleteSession: false, + canRetry: map[idempotency]bool{ + idempotent: false, + nonIdempotent: false, + }, + }, + { + err: xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_BAD_SESSION), + ), + backoff: backoff.TypeNoBackoff, + deleteSession: true, + canRetry: map[idempotency]bool{ + idempotent: true, + nonIdempotent: true, + }, + }, + { + err: xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_PRECONDITION_FAILED), + ), + backoff: backoff.TypeNoBackoff, + deleteSession: false, + canRetry: map[idempotency]bool{ + idempotent: false, + nonIdempotent: false, + }, + }, + { + err: xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_ALREADY_EXISTS), + ), + backoff: backoff.TypeNoBackoff, + deleteSession: false, + canRetry: map[idempotency]bool{ + idempotent: false, + nonIdempotent: false, + }, + }, + { + err: xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_NOT_FOUND), + ), + backoff: backoff.TypeNoBackoff, + deleteSession: false, + canRetry: map[idempotency]bool{ + idempotent: false, + nonIdempotent: false, + }, + }, + { + err: xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_SESSION_EXPIRED), + ), + backoff: backoff.TypeNoBackoff, + deleteSession: true, + canRetry: map[idempotency]bool{ + idempotent: true, + nonIdempotent: false, + }, + }, + { + err: xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_CANCELLED), + ), + backoff: backoff.TypeFast, + deleteSession: false, + canRetry: map[idempotency]bool{ + idempotent: false, + nonIdempotent: false, + }, + }, + { + err: xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_UNDETERMINED), + ), + backoff: backoff.TypeFast, + deleteSession: false, + canRetry: map[idempotency]bool{ + idempotent: true, + nonIdempotent: false, + }, + }, + { + err: xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_UNSUPPORTED), + ), + backoff: backoff.TypeNoBackoff, + deleteSession: false, + canRetry: map[idempotency]bool{ + idempotent: false, + nonIdempotent: false, + }, + }, + { + err: xerrors.Operation( + xerrors.WithStatusCode(Ydb.StatusIds_SESSION_BUSY), + ), + backoff: backoff.TypeFast, + deleteSession: true, + canRetry: map[idempotency]bool{ + idempotent: true, + nonIdempotent: true, + }, + }, + } +) diff --git a/retry/retry.go b/retry/retry.go index c2e601603..89b2c7391 100644 --- a/retry/retry.go +++ b/retry/retry.go @@ -365,7 +365,7 @@ func opWithRecover(ctx context.Context, options *retryOptions, op retryOperation if e := recover(); e != nil { options.panicCallback(e) err = xerrors.WithStackTrace( - fmt.Errorf("panic recovered: %v", e), + fmt.Errorf("panic recovered: %v", e), //nolint:goerr113 ) } }() diff --git a/retry/retry_test.go b/retry/retry_test.go index 40e2f0294..39ceaa906 100644 --- a/retry/retry_test.go +++ b/retry/retry_test.go @@ -84,7 +84,7 @@ func TestRetryWithCustomErrors(t *testing.T) { { error: &CustomError{ Err: RetryableError( - fmt.Errorf("custom error"), + errCustom, WithDeleteSession(), ), }, @@ -204,7 +204,7 @@ func TestRetryWithBudget(t *testing.T) { ctx, cancel := context.WithCancel(xtest.Context(t)) defer cancel() err := Retry(ctx, func(ctx context.Context) (err error) { - return RetryableError(errors.New("custom error")) + return RetryableError(errCustom) }, WithBudget(quota)) require.ErrorIs(t, err, errNoQuota) }) diff --git a/scripting/example_test.go b/scripting/example_test.go index aa96dd85a..a6b274ca9 100644 --- a/scripting/example_test.go +++ b/scripting/example_test.go @@ -2,6 +2,7 @@ package scripting_test import ( "context" + "errors" "fmt" "github.com/ydb-platform/ydb-go-sdk/v3" @@ -10,6 +11,12 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/table" ) +var ( + errNoResultSets = errors.New("no result sets") + errNoRows = errors.New("no rows") + errUnexpectedParameterTypes = errors.New("unexpected parameter types") +) + func Example_execute() { ctx := context.TODO() db, err := ydb.Open(ctx, "grpc://localhost:2136/local") @@ -31,13 +38,13 @@ func Example_execute() { defer res.Close() // cleanup resources if !res.NextResultSet(ctx) { return retry.RetryableError( - fmt.Errorf("no result sets"), + errNoResultSets, retry.WithBackoff(retry.TypeNoBackoff), ) } if !res.NextRow() { return retry.RetryableError( - fmt.Errorf("no rows"), + errNoRows, retry.WithBackoff(retry.TypeSlowBackoff), ) } @@ -46,7 +53,7 @@ func Example_execute() { return fmt.Errorf("scan failed: %w", err) } if sum != 2 { - return fmt.Errorf("unexpected sum: %v", sum) + return fmt.Errorf("unexpected sum: %v", sum) //nolint:goerr113 } return res.Err() @@ -76,14 +83,14 @@ func Example_streamExecute() { defer res.Close() // cleanup resources if !res.NextResultSet(ctx) { return retry.RetryableError( - fmt.Errorf("no result sets"), + errNoResultSets, retry.WithBackoff(retry.TypeNoBackoff), retry.WithDeleteSession(), ) } if !res.NextRow() { return retry.RetryableError( - fmt.Errorf("no rows"), + errNoRows, retry.WithBackoff(retry.TypeFastBackoff), ) } @@ -92,7 +99,7 @@ func Example_streamExecute() { return fmt.Errorf("scan failed: %w", err) } if sum != 2 { - return fmt.Errorf("unexpected sum: %v", sum) + return fmt.Errorf("unexpected sum: %v", sum) //nolint:goerr113 } return res.Err() @@ -147,7 +154,7 @@ func Example_explainValidate() { return err } if len(res.ParameterTypes) > 0 { - return retry.RetryableError(fmt.Errorf("unexpected parameter types")) + return retry.RetryableError(errUnexpectedParameterTypes) } return nil diff --git a/sugar/params.go b/sugar/params.go index 4285969a5..1e65e1ebe 100644 --- a/sugar/params.go +++ b/sugar/params.go @@ -33,7 +33,7 @@ func GenerateDeclareSection[T constraint](parameters T) (string, error) { case []sql.NamedArg: return namedArgsToDeclares(v) default: - return "", xerrors.WithStackTrace(fmt.Errorf("unsupported type: %T", v)) + return "", xerrors.WithStackTrace(fmt.Errorf("unsupported type: %T", v)) //nolint:goerr113 } } @@ -46,6 +46,7 @@ func ToYdbParam(param sql.NamedArg) (*params.Parameter, error) { return nil, xerrors.WithStackTrace(err) } if len(params) != 1 { + //nolint:goerr113 return nil, xerrors.WithStackTrace(fmt.Errorf("internal error: wrong parameters count: %v", params)) } diff --git a/sugar/path.go b/sugar/path.go index cc22e15aa..4c256cf82 100644 --- a/sugar/path.go +++ b/sugar/path.go @@ -50,6 +50,7 @@ type dbFoRemoveRecursive interface { // where `~` - is a root of database func MakeRecursive(ctx context.Context, db dbForMakeRecursive, pathToCreate string) error { if strings.HasPrefix(pathToCreate, sysDirectory+"/") { + //nolint:goerr113 return xerrors.WithStackTrace( fmt.Errorf("making directory %q inside system path %q not supported", pathToCreate, sysDirectory), ) @@ -77,6 +78,7 @@ func MakeRecursive(ctx context.Context, db dbForMakeRecursive, pathToCreate stri scheme.EntryDirectory: return nil default: + //nolint:goerr113 return xerrors.WithStackTrace( fmt.Errorf("entry %q exists but it is not a directory: %s", absPath, info.Type), ) @@ -151,6 +153,7 @@ func RemoveRecursive(ctx context.Context, db dbFoRemoveRecursive, pathToRemove s } default: + //nolint:goerr113 return xerrors.WithStackTrace( fmt.Errorf("unknown entry type: %s", t.String()), ) diff --git a/table/example_test.go b/table/example_test.go index 430c28f84..a7e9b7539 100644 --- a/table/example_test.go +++ b/table/example_test.go @@ -2,6 +2,7 @@ package table_test import ( "context" + "errors" "fmt" "path" "time" @@ -17,6 +18,11 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/table/types" ) +var ( + errNoResultSets = errors.New("no result sets") + errNoRows = errors.New("no rows") +) + func Example_select() { ctx := context.TODO() db, err := ydb.Open(ctx, "grpc://localhost:2136/local") @@ -213,10 +219,10 @@ func Example_lazyTransaction() { _ = result.Close() }() if !result.NextResultSet(ctx) { - return retry.RetryableError(fmt.Errorf("no result sets")) + return retry.RetryableError(errNoResultSets) } if !result.NextRow() { - return retry.RetryableError(fmt.Errorf("no rows")) + return retry.RetryableError(errNoRows) } var ( id uint64 diff --git a/table/types/cast.go b/table/types/cast.go index 064967678..f01397044 100644 --- a/table/types/cast.go +++ b/table/types/cast.go @@ -41,6 +41,7 @@ func ToDecimal(v Value) (*Decimal, error) { }, nil } + //nolint:goerr113 return nil, xerrors.WithStackTrace(fmt.Errorf("value type '%s' is not decimal type", v.Type().Yql())) } @@ -52,6 +53,7 @@ func ListItems(v Value) ([]Value, error) { return vv.ListItems(), nil } + //nolint:goerr113 return nil, xerrors.WithStackTrace(fmt.Errorf("cannot get list items from '%s'", v.Type().Yql())) } @@ -63,6 +65,7 @@ func TupleItems(v Value) ([]Value, error) { return vv.TupleItems(), nil } + //nolint:goerr113 return nil, xerrors.WithStackTrace(fmt.Errorf("cannot get tuple items from '%s'", v.Type().Yql())) } @@ -74,6 +77,7 @@ func StructFields(v Value) (map[string]Value, error) { return vv.StructFields(), nil } + //nolint:goerr113 return nil, xerrors.WithStackTrace(fmt.Errorf("cannot get struct fields from '%s'", v.Type().Yql())) } @@ -88,6 +92,7 @@ func VariantValue(v Value) (name string, idx uint32, _ Value, _ error) { return name, idx, vv.Value(), nil } + //nolint:goerr113 return "", 0, nil, xerrors.WithStackTrace(fmt.Errorf("cannot get variant value from '%s'", v.Type().Yql())) } @@ -108,5 +113,6 @@ func DictValues(v Value) (map[Value]Value, error) { return vv.DictValues(), nil } + //nolint:goerr113 return nil, xerrors.WithStackTrace(fmt.Errorf("cannot get dict values from '%s'", v.Type().Yql())) } diff --git a/tests/slo/database/sql/main.go b/tests/slo/database/sql/main.go index 6244e917a..14d527cd4 100644 --- a/tests/slo/database/sql/main.go +++ b/tests/slo/database/sql/main.go @@ -126,6 +126,6 @@ func main() { wg.Wait() default: - panic(fmt.Errorf("unknown mode: %v", cfg.Mode)) + panic(fmt.Errorf("unknown mode: %v", cfg.Mode)) //nolint:goerr113 } } diff --git a/tests/slo/gorm/main.go b/tests/slo/gorm/main.go index ef4a9a079..d48afc488 100644 --- a/tests/slo/gorm/main.go +++ b/tests/slo/gorm/main.go @@ -126,6 +126,6 @@ func main() { wg.Wait() default: - panic(fmt.Errorf("unknown mode: %v", cfg.Mode)) + panic(fmt.Errorf("unknown mode: %v", cfg.Mode)) //nolint:goerr113 } } diff --git a/tests/slo/native/query/main.go b/tests/slo/native/query/main.go index 138187877..59f4af448 100644 --- a/tests/slo/native/query/main.go +++ b/tests/slo/native/query/main.go @@ -134,6 +134,6 @@ func main() { wg.Wait() default: - panic(fmt.Errorf("unknown mode: %v", cfg.Mode)) + panic(fmt.Errorf("unknown mode: %v", cfg.Mode)) //nolint:goerr113 } } diff --git a/tests/slo/native/table/main.go b/tests/slo/native/table/main.go index 9d5df4e72..81f2c301f 100644 --- a/tests/slo/native/table/main.go +++ b/tests/slo/native/table/main.go @@ -126,6 +126,6 @@ func main() { wg.Wait() default: - panic(fmt.Errorf("unknown mode: %v", cfg.Mode)) + panic(fmt.Errorf("unknown mode: %v", cfg.Mode)) //nolint:goerr113 } } diff --git a/tests/slo/native/table/storage.go b/tests/slo/native/table/storage.go index affd5f60b..1d82e6754 100755 --- a/tests/slo/native/table/storage.go +++ b/tests/slo/native/table/storage.go @@ -135,7 +135,7 @@ func (s *Storage) Read(ctx context.Context, entryID generator.RowID) (_ generato } if !res.NextRow() { - return fmt.Errorf("entry not found, id = %v", entryID) + return fmt.Errorf("entry not found, id = %v", entryID) //nolint:goerr113 } err = res.ScanNamed( diff --git a/tests/slo/xorm/main.go b/tests/slo/xorm/main.go index 9d5df4e72..81f2c301f 100644 --- a/tests/slo/xorm/main.go +++ b/tests/slo/xorm/main.go @@ -126,6 +126,6 @@ func main() { wg.Wait() default: - panic(fmt.Errorf("unknown mode: %v", cfg.Mode)) + panic(fmt.Errorf("unknown mode: %v", cfg.Mode)) //nolint:goerr113 } } diff --git a/tests/slo/xorm/storage.go b/tests/slo/xorm/storage.go index 4550374c9..51d964a06 100644 --- a/tests/slo/xorm/storage.go +++ b/tests/slo/xorm/storage.go @@ -32,6 +32,8 @@ var ( writeTx = table.SerializableReadWriteTxControl( table.CommitTx(), ) + + errEntryNotFound = errors.New("get entry: entry not found") ) type mapper struct { @@ -133,7 +135,7 @@ func (s *Storage) Read(ctx context.Context, id generator.RowID) (row generator.R return fmt.Errorf("get entry error: %w", err) } if !has { - return errors.New("get entry: entry not found") + return errEntryNotFound } return nil diff --git a/testutil/compare.go b/testutil/compare.go index 8caf4b9bf..6e6c0f255 100644 --- a/testutil/compare.go +++ b/testutil/compare.go @@ -13,6 +13,7 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" ) +//nolint:goerr113 var ErrNotComparable = xerrors.Wrap(fmt.Errorf("not comparable")) // Compare compares its operands. diff --git a/testutil/driver.go b/testutil/driver.go index 48b82d4ca..cb9cfc5e3 100644 --- a/testutil/driver.go +++ b/testutil/driver.go @@ -2,6 +2,7 @@ package testutil import ( "context" + "errors" "fmt" "reflect" "strings" @@ -16,7 +17,13 @@ import ( "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" ) -var ErrNotImplemented = xerrors.Wrap(fmt.Errorf("testutil: not implemented")) +//nolint:goerr113 +var ( + ErrNotImplemented = xerrors.Wrap(errors.New("testutil: not implemented")) + + errOnInvokeNotDefined = errors.New("database.onInvoke() not defined") + errOnNewStreamNotDefined = errors.New("database.onNewStream() not defined") +) type MethodCode uint @@ -150,7 +157,7 @@ func (b *balancerStub) Invoke( opts ...grpc.CallOption, ) (err error) { if b.onInvoke == nil { - return fmt.Errorf("database.onInvoke() not defined") + return errOnInvokeNotDefined } return b.onInvoke(ctx, method, args, reply, opts...) @@ -163,7 +170,7 @@ func (b *balancerStub) NewStream( opts ...grpc.CallOption, ) (_ grpc.ClientStream, err error) { if b.onNewStream == nil { - return nil, fmt.Errorf("database.onNewStream() not defined") + return nil, errOnNewStreamNotDefined } return b.onNewStream(ctx, desc, method, opts...) @@ -224,7 +231,7 @@ func WithInvokeHandlers(invokeHandlers InvokeHandlers) balancerOption { return nil } - return fmt.Errorf("method '%s' not implemented", method) + return fmt.Errorf("method '%s' not implemented", method) //nolint:goerr113 } } } @@ -241,7 +248,7 @@ func WithNewStreamHandlers(newStreamHandlers NewStreamHandlers) balancerOption { return handler(desc) } - return nil, fmt.Errorf("method '%s' not implemented", method) + return nil, fmt.Errorf("method '%s' not implemented", method) //nolint:goerr113 } } } @@ -293,6 +300,7 @@ func (c *clientConn) Invoke( opts ...grpc.CallOption, ) error { if c.onInvoke == nil { + //nolint:goerr113 return fmt.Errorf("onInvoke not implemented (method: %s, request: %v, response: %v)", method, args, reply) } @@ -306,6 +314,7 @@ func (c *clientConn) NewStream( opts ...grpc.CallOption, ) (grpc.ClientStream, error) { if c.onNewStream == nil { + //nolint:goerr113 return nil, fmt.Errorf("onNewStream not implemented (method: %s, desc: %v)", method, desc) } diff --git a/topic/topicreader/errors.go b/topic/topicreader/errors.go index f5f4db2d0..569b92197 100644 --- a/topic/topicreader/errors.go +++ b/topic/topicreader/errors.go @@ -13,7 +13,7 @@ var ErrUnexpectedCodec = topicreaderinternal.ErrPublicUnexpectedCodec // ErrConcurrencyCall return if method on reader called in concurrency // client side must check error with errors.Is -var ErrConcurrencyCall = xerrors.Wrap(errors.New("ydb: concurrency call denied")) +var ErrConcurrencyCall = xerrors.Wrap(errors.New("ydb: concurrency call denied")) //nolint:goerr113 // ErrCommitToExpiredSession it is not fatal error and reader can continue work // client side must check error with errors.Is