Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
# Folders
_obj
_test
.idea

# Architecture specific extensions/prefixes
*.[568vq]
Expand Down
73 changes: 0 additions & 73 deletions terror_dsl.go

This file was deleted.

137 changes: 95 additions & 42 deletions terror_error.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,21 @@ import (
"runtime"
"strconv"
"strings"

"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)

// ErrCode represents a specific error type in a error class.
// Same error code can be used in different error classes.
type ErrCode int

// ErrCodeText is a textual error code that represents a specific error type in a error class.
type ErrCodeText string

type ErrorID string
type RFCErrorCode string

// Error is the 'prototype' of a type of errors.
// Use DefineError to make a *Error:
// var ErrUnavailable = ClassRegion.DefineError().
Expand All @@ -46,8 +59,7 @@ import (
// // handle this error.
// }
type Error struct {
class *ErrClass
code ErrCode
code ErrCode
// codeText is the textual describe of the error code
codeText ErrCodeText
// message is a template of the description of this error.
Expand All @@ -61,14 +73,11 @@ type Error struct {
// and the more detail this field explaining the better,
// even some guess of the cause could be included.
Description string
args []interface{}
file string
line int
}

// Class returns ErrClass
func (e *Error) Class() *ErrClass {
return e.class
// Cause is used to warp some third party error.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo

cause error
args []interface{}
file string
line int
}

// Code returns the numeric code of this error.
Expand All @@ -84,23 +93,7 @@ func (e *Error) Code() ErrCode {
// The error code is a 3-tuple of abbreviated component name, error class and error code,
// joined by a colon like {Component}:{ErrorClass}:{InnerErrorCode}.
func (e *Error) RFCCode() RFCErrorCode {
ec := e.Class()
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should return the e.codeText if the e.codeText had been assigned a value.

if ec == nil {
return RFCErrorCode(e.ID())
}
reg := ec.registry
// Maybe top-level errors.
if reg.Name == "" {
return RFCErrorCode(fmt.Sprintf("%s:%s",
ec.Description,
e.ID(),
))
}
return RFCErrorCode(fmt.Sprintf("%s:%s:%s",
reg.Name,
ec.Description,
e.ID(),
))
return RFCErrorCode(e.ID())
}

// ID returns the ID of this error.
Expand All @@ -122,16 +115,50 @@ func (e *Error) MessageTemplate() string {
return e.message
}

// NewError creates a standard error object.
func NewError(code int, message string) *Error {
return &Error{
code: ErrCode(code),
message: message,
}
}

// NewErrorWithText creates a standard error object using text error code.
func NewErrorWithText(code string, message string) *Error {
return &Error{
codeText: ErrCodeText(code),
message: message,
}
}

// SetWorkaround sets the workaround for standard error.
func (e *Error) SetWorkaround(workaround string) *Error {
e.Workaround = workaround
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we allow users to dynamically change the fields?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a decorator function. Since old error in TiDB do not have workaround field. Using this method can add workaround with miniumn change.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reference to the demo https://play.golang.org/p/rJBVbbkbXLP, we can minimize the change and make the error immutable.

return e
}

// SetWorkaround sets the description for standard error.
func (e *Error) SetDescription(description string) *Error {
e.Description = description
return e
}

// SetErrCodeText sets the text error code for standard error.
func (e *Error) SetErrCodeText(codeText string) *Error {
e.codeText = ErrCodeText(codeText)
return e
}

// Error implements error interface.
func (e *Error) Error() string {
describe := e.codeText
if len(describe) == 0 {
describe = ErrCodeText(strconv.Itoa(int(e.code)))
}
return fmt.Sprintf("[%s] %s", e.RFCCode(), e.getMsg())
return fmt.Sprintf("[%s] %s", e.RFCCode(), e.GetMsg())
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should use the local variable describe as the prefix of the error message.

}

func (e *Error) getMsg() string {
func (e *Error) GetMsg() string {
if len(e.args) > 0 {
return fmt.Sprintf(e.message, e.args...)
}
Expand Down Expand Up @@ -197,9 +224,8 @@ func (e *Error) Equal(err error) bool {
if !ok {
return false
}
classEquals := e.class.Equal(inErr.class)
idEquals := e.ID() == inErr.ID()
return classEquals && idEquals
return idEquals
}

// NotEqual checks if err is not equal to e.
Expand Down Expand Up @@ -239,7 +265,6 @@ type jsonError struct {
Error string `json:"message"`
Description string `json:"description,omitempty"`
Workaround string `json:"workaround,omitempty"`
Class ErrClassID `json:"classID"`
File string `json:"file"`
Line int `json:"line"`
}
Expand All @@ -251,11 +276,10 @@ type jsonError struct {
// This function is reserved for compatibility.
func (e *Error) MarshalJSON() ([]byte, error) {
return json.Marshal(&jsonError{
Error: e.getMsg(),
Error: e.GetMsg(),
Description: e.Description,
Workaround: e.Workaround,
RFCCode: e.RFCCode(),
Class: e.class.ID,
Line: e.line,
File: e.file,
})
Expand All @@ -273,9 +297,7 @@ func (e *Error) UnmarshalJSON(data []byte) error {
return Trace(err)
}
codes := strings.Split(string(err.RFCCode), ":")
regName := codes[0]
className := codes[1]
innerCode := codes[2]
innerCode := codes[0]
if i, errAtoi := strconv.Atoi(innerCode); errAtoi == nil {
e.code = ErrCode(i)
} else {
Expand All @@ -284,10 +306,41 @@ func (e *Error) UnmarshalJSON(data []byte) error {
e.line = err.Line
e.file = err.File
e.message = err.Error
e.class = &ErrClass{
Description: className,
ID: err.Class,
registry: &Registry{Name: regName},
}
return nil
}

func (e *Error) Wrap(err error) *Error {
e.cause = err
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should return a new instance of when Wrap a message instead of in-place changing the original instance. The error will be a global instance in many cases.

return e
}

func (e *Error) Cause() error {
root := Unwrap(e.cause)
if root == nil {
return e.cause
}
return root
}

func (e *Error) FastGenWithCause(args ...interface{}) error {
err := *e
err.message = e.cause.Error()
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will panic here is Wrap a nil error

err.args = args
return SuspendStack(&err)
}

func (e *Error) GenWithStackByCause(args ...interface{}) error {
err := *e
err.message = e.cause.Error()
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

err.args = args
err.fillLineAndFile(1)
return AddStack(&err)
}

func CauseError(err *Error) zap.Field {
return zap.Field{Key: "error", Type: zapcore.ErrorType, Interface: err.FastGenWithCause()}
}

func DetailError(err *Error) zap.Field {
return zap.Field{Key: "error", Type: zapcore.ErrorType, Interface: err.FastGenByArgs()}
}
Comment on lines +354 to +361
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to discussion with @rleungx, we can remove this two functions and use zap.Error directly. And PD will customize a function to adopt their scenarios.

79 changes: 0 additions & 79 deletions terror_gen.go

This file was deleted.

Loading