go.uber.org/yarpc@v1.72.1/yarpcerrors/codes.go (about)

     1  // Copyright (c) 2022 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package yarpcerrors
    22  
    23  import (
    24  	"fmt"
    25  	"strconv"
    26  	"strings"
    27  )
    28  
    29  const (
    30  	// CodeOK means no error; returned on success
    31  	CodeOK Code = 0
    32  
    33  	// CodeCancelled means the operation was cancelled, typically by the caller.
    34  	// This is considered as a client error.
    35  	CodeCancelled Code = 1
    36  
    37  	// CodeUnknown means an unknown error. Errors raised by APIs
    38  	// that do not return enough error information
    39  	// may be converted to this error.
    40  	// This is considered as a server error.
    41  	CodeUnknown Code = 2
    42  
    43  	// CodeInvalidArgument means the client specified an invalid argument.
    44  	// Note that this differs from `FailedPrecondition`. `InvalidArgument`
    45  	// indicates arguments that are problematic regardless of the state of
    46  	// the system (e.g., a malformed file name).
    47  	// This is considered as a client error.
    48  	CodeInvalidArgument Code = 3
    49  
    50  	// CodeDeadlineExceeded means the deadline expired before the operation could
    51  	// complete. For operations that change the state of the system, this error
    52  	// may be returned even if the operation has completed successfully. For example,
    53  	// a successful response from a server could have been delayed long
    54  	// enough for the deadline to expire.
    55  	// This is considered as a server error.
    56  	CodeDeadlineExceeded Code = 4
    57  
    58  	// CodeNotFound means some requested entity (e.g., file or directory) was not found.
    59  	// For privacy reasons, this code *may* be returned when the client
    60  	// does not have the access rights to the entity, though such usage is
    61  	// discouraged.
    62  	// This is considered as a client error.
    63  	CodeNotFound Code = 5
    64  
    65  	// CodeAlreadyExists means the entity that a client attempted to create
    66  	// (e.g., file or directory) already exists.
    67  	// This is considered as a client error.
    68  	CodeAlreadyExists Code = 6
    69  
    70  	// CodePermissionDenied means the caller does not have permission to execute
    71  	// the specified operation. `PermissionDenied` must not be used for rejections
    72  	// caused by exhausting some resource (use `ResourceExhausted`
    73  	// instead for those errors). `PermissionDenied` must not be
    74  	// used if the caller can not be identified (use `Unauthenticated`
    75  	// instead for those errors).
    76  	// This is considered as a client error.
    77  	CodePermissionDenied Code = 7
    78  
    79  	// CodeResourceExhausted means some resource has been exhausted, perhaps a per-user
    80  	// quota, or perhaps the entire file system is out of space.
    81  	// This is considered as a client error.
    82  	CodeResourceExhausted Code = 8
    83  
    84  	// CodeFailedPrecondition means the operation was rejected because the system is not
    85  	// in a state required for the operation's execution. For example, the directory
    86  	// to be deleted is non-empty, an rmdir operation is applied to
    87  	// a non-directory, etc.
    88  	//
    89  	// Service implementors can use the following guidelines to decide
    90  	// between `FailedPrecondition`, `Aborted`, and `Unavailable`:
    91  	//  (a) Use `Unavailable` if the client can retry just the failing call.
    92  	//  (b) Use `Aborted` if the client should retry at a higher level
    93  	//      (e.g., restarting a read-modify-write sequence).
    94  	//  (c) Use `FailedPrecondition` if the client should not retry until
    95  	//      the system state has been explicitly fixed. E.g., if an "rmdir"
    96  	//      fails because the directory is non-empty, `FailedPrecondition`
    97  	//      should be returned since the client should not retry unless
    98  	//      the files are deleted from the directory.
    99  	// This is considered as a client error.
   100  	CodeFailedPrecondition Code = 9
   101  
   102  	// CodeAborted means the operation was aborted, typically due to a concurrency issue
   103  	// such as a sequencer check failure or transaction abort.
   104  	//
   105  	// See the guidelines above for deciding between `FailedPrecondition`,
   106  	// `Aborted`, and `Unavailable`.
   107  	// This is considered as a client error.
   108  	CodeAborted Code = 10
   109  
   110  	// CodeOutOfRange means the operation was attempted past the valid range.
   111  	// E.g., seeking or reading past end-of-file.
   112  	//
   113  	// Unlike `InvalidArgument`, this error indicates a problem that may
   114  	// be fixed if the system state changes. For example, a 32-bit file
   115  	// system will generate `InvalidArgument` if asked to read at an
   116  	// offset that is not in the range [0,2^32-1], but it will generate
   117  	// `OutOfRange` if asked to read from an offset past the current
   118  	// file size.
   119  	//
   120  	// There is a fair bit of overlap between `FailedPrecondition` and
   121  	// `OutOfRange`.  We recommend using `OutOfRange` (the more specific
   122  	// error) when it applies so that callers who are iterating through
   123  	// a space can easily look for an `OutOfRange` error to detect when
   124  	// they are done.
   125  	// This is considered as a client error.
   126  	CodeOutOfRange Code = 11
   127  
   128  	// CodeUnimplemented means the operation is not implemented or is not
   129  	// supported/enabled in this service.
   130  	// This is considered as a client error.
   131  	CodeUnimplemented Code = 12
   132  
   133  	// CodeInternal means an internal error. This means that some invariants expected
   134  	// by the underlying system have been broken. This error code is reserved
   135  	// for serious errors.
   136  	// This is considered as a server error.
   137  	CodeInternal Code = 13
   138  
   139  	// CodeUnavailable means the service is currently unavailable. This is most likely a
   140  	// transient condition, which can be corrected by retrying with a backoff.
   141  	//
   142  	// See the guidelines above for deciding between `FailedPrecondition`,
   143  	// `Aborted`, and `Unavailable`.
   144  	// This is considered as a server error.
   145  	CodeUnavailable Code = 14
   146  
   147  	// CodeDataLoss means unrecoverable data loss or corruption.
   148  	// This is considered as a server error.
   149  	CodeDataLoss Code = 15
   150  
   151  	// CodeUnauthenticated means the request does not have valid authentication
   152  	// credentials for the operation.
   153  	// This is considered as a client error.
   154  	CodeUnauthenticated Code = 16
   155  )
   156  
   157  var (
   158  	_codeToString = map[Code]string{
   159  		CodeOK:                 "ok",
   160  		CodeCancelled:          "cancelled",
   161  		CodeUnknown:            "unknown",
   162  		CodeInvalidArgument:    "invalid-argument",
   163  		CodeDeadlineExceeded:   "deadline-exceeded",
   164  		CodeNotFound:           "not-found",
   165  		CodeAlreadyExists:      "already-exists",
   166  		CodePermissionDenied:   "permission-denied",
   167  		CodeResourceExhausted:  "resource-exhausted",
   168  		CodeFailedPrecondition: "failed-precondition",
   169  		CodeAborted:            "aborted",
   170  		CodeOutOfRange:         "out-of-range",
   171  		CodeUnimplemented:      "unimplemented",
   172  		CodeInternal:           "internal",
   173  		CodeUnavailable:        "unavailable",
   174  		CodeDataLoss:           "data-loss",
   175  		CodeUnauthenticated:    "unauthenticated",
   176  	}
   177  	_stringToCode = map[string]Code{
   178  		"ok":                  CodeOK,
   179  		"cancelled":           CodeCancelled,
   180  		"unknown":             CodeUnknown,
   181  		"invalid-argument":    CodeInvalidArgument,
   182  		"deadline-exceeded":   CodeDeadlineExceeded,
   183  		"not-found":           CodeNotFound,
   184  		"already-exists":      CodeAlreadyExists,
   185  		"permission-denied":   CodePermissionDenied,
   186  		"resource-exhausted":  CodeResourceExhausted,
   187  		"failed-precondition": CodeFailedPrecondition,
   188  		"aborted":             CodeAborted,
   189  		"out-of-range":        CodeOutOfRange,
   190  		"unimplemented":       CodeUnimplemented,
   191  		"internal":            CodeInternal,
   192  		"unavailable":         CodeUnavailable,
   193  		"data-loss":           CodeDataLoss,
   194  		"unauthenticated":     CodeUnauthenticated,
   195  	}
   196  )
   197  
   198  // Code represents the type of error for an RPC call.
   199  //
   200  // Sometimes multiple error codes may apply. Services should return
   201  // the most specific error code that applies. For example, prefer
   202  // `OutOfRange` over `FailedPrecondition` if both codes apply.
   203  // Similarly prefer `NotFound` or `AlreadyExists` over `FailedPrecondition`.
   204  //
   205  // These codes are meant to match gRPC status codes.
   206  // https://godoc.org/google.golang.org/grpc/codes#Code
   207  type Code int
   208  
   209  // String returns the the string representation of the Code.
   210  func (c Code) String() string {
   211  	s, ok := _codeToString[c]
   212  	if ok {
   213  		return s
   214  	}
   215  	return strconv.Itoa(int(c))
   216  }
   217  
   218  // MarshalText implements encoding.TextMarshaler.
   219  func (c Code) MarshalText() ([]byte, error) {
   220  	s, ok := _codeToString[c]
   221  	if ok {
   222  		return []byte(s), nil
   223  	}
   224  	return nil, fmt.Errorf("unknown code: %d", int(c))
   225  }
   226  
   227  // UnmarshalText implements encoding.TextUnmarshaler.
   228  func (c *Code) UnmarshalText(text []byte) error {
   229  	i, ok := _stringToCode[strings.ToLower(string(text))]
   230  	if !ok {
   231  		return fmt.Errorf("unknown code string: %s", string(text))
   232  	}
   233  	*c = i
   234  	return nil
   235  }
   236  
   237  // MarshalJSON implements json.Marshaler.
   238  func (c Code) MarshalJSON() ([]byte, error) {
   239  	s, ok := _codeToString[c]
   240  	if ok {
   241  		return []byte(`"` + s + `"`), nil
   242  	}
   243  	return nil, fmt.Errorf("unknown code: %d", int(c))
   244  }
   245  
   246  // UnmarshalJSON implements json.Unmarshaler.
   247  func (c *Code) UnmarshalJSON(text []byte) error {
   248  	s := string(text)
   249  	if len(s) < 3 || s[0] != '"' || s[len(s)-1] != '"' {
   250  		return fmt.Errorf("invalid code string: %s", s)
   251  	}
   252  	i, ok := _stringToCode[strings.ToLower(s[1:len(s)-1])]
   253  	if !ok {
   254  		return fmt.Errorf("unknown code string: %s", s)
   255  	}
   256  	*c = i
   257  	return nil
   258  }