forked from vitessio/vitess
-
Notifications
You must be signed in to change notification settings - Fork 0
/
vterrors.go
98 lines (86 loc) · 3.08 KB
/
vterrors.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// Copyright 2012, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package vterrors provides helpers for propagating internal errors through the Vitess
// system (including across RPC boundaries) in a structured way.
package vterrors
import (
"fmt"
mproto "github.com/youtube/vitess/go/mysql/proto"
pb "github.com/youtube/vitess/go/vt/proto/vtrpc"
)
const (
// TabletError is the base VtTablet error. All VtTablet errors should be 4 digits, starting with 1.
TabletError = 1000
// UnknownTabletError is the code for an unknown error that came from VtTablet.
UnknownTabletError = 1999
// VtgateError is the base VTGate error code. All VTGate errors should be 4 digits, starting with 2.
VtgateError = 2000
// UnknownVtgateError is the code for an unknown error that came from VTGate.
UnknownVtgateError = 2999
)
// VitessError is the error type that we use internally for passing structured errors
type VitessError struct {
// Error code of the Vitess error
Code int64
// Additional context string, distinct from the error message. For example, if
// you wanted an error like "foo error: original error", the Message string
// should be "foo error: "
Message string
err error
}
// Error implements the error interface. For now, it should exactly recreate the original error string.
// It intentionally (for now) does not expose all the information that VitessError has. This
// is so that it can be used in the mixed state where parts of the stack are trying to parse
// error strings.
func (e *VitessError) Error() string {
return fmt.Sprintf("%v", e.err)
}
// AsString returns a VitessError as a string, with more detailed information than Error().
func (e *VitessError) AsString() string {
if e.Message != "" {
return fmt.Sprintf("Code: %v, Message: %v, err: %v", e.Code, e.Message, e.err)
}
return fmt.Sprintf("Code: %v, err: %v", e.Code, e.err)
}
// FromError returns a VitessError with the supplied error code and wrapped error.
func FromError(code int64, err error) error {
return &VitessError{
Code: code,
err: err,
}
}
// FromRPCError recovers a VitessError from a *RPCError (which is how VitessErrors
// are transmitted across RPC boundaries).
func FromRPCError(rpcErr *mproto.RPCError) error {
if rpcErr == nil {
return nil
}
return &VitessError{
Code: rpcErr.Code,
err: fmt.Errorf("%v", rpcErr.Message),
}
}
// FromVtRPCError recovers a VitessError from a *vtrpc.RPCError (which is how VitessErrors
// are transmitted across proto3 RPC boundaries).
func FromVtRPCError(rpcErr *pb.RPCError) *VitessError {
if rpcErr == nil {
return nil
}
return &VitessError{
Code: int64(rpcErr.Code),
err: fmt.Errorf("%v", rpcErr.Message),
}
}
// WithPrefix allows a string to be prefixed to an error, without nesting a new VitessError.
func WithPrefix(prefix string, in error) error {
vtErr, ok := in.(*VitessError)
if !ok {
return fmt.Errorf("%s: %s", prefix, in)
}
return &VitessError{
Code: vtErr.Code,
err: vtErr.err,
Message: fmt.Sprintf("%s: %s", prefix, vtErr.Message),
}
}