pkg/rpc/rpcstatus: fix drpc grpc compatibilty (#3306)
When code is compiled without -tags=drpc the statuses for drpc server weren't handled, which meant an uplink using -tags=drpc didn't get the correct status code.
This commit is contained in:
parent
071d1c4313
commit
f929310add
@ -6,45 +6,171 @@
|
||||
package rpcstatus
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"storj.io/drpc/drpcerr"
|
||||
)
|
||||
|
||||
// StatusCode is the type of status codes for grpc.
|
||||
type StatusCode = codes.Code
|
||||
// StatusCode is the type of status codes for drpc.
|
||||
type StatusCode uint64
|
||||
|
||||
// These constants are all the rpc error codes.
|
||||
const (
|
||||
OK = codes.OK
|
||||
Canceled = codes.Canceled
|
||||
Unknown = codes.Unknown
|
||||
InvalidArgument = codes.InvalidArgument
|
||||
DeadlineExceeded = codes.DeadlineExceeded
|
||||
NotFound = codes.NotFound
|
||||
AlreadyExists = codes.AlreadyExists
|
||||
PermissionDenied = codes.PermissionDenied
|
||||
ResourceExhausted = codes.ResourceExhausted
|
||||
FailedPrecondition = codes.FailedPrecondition
|
||||
Aborted = codes.Aborted
|
||||
OutOfRange = codes.OutOfRange
|
||||
Unimplemented = codes.Unimplemented
|
||||
Internal = codes.Internal
|
||||
Unavailable = codes.Unavailable
|
||||
DataLoss = codes.DataLoss
|
||||
Unauthenticated = codes.Unauthenticated
|
||||
Unknown StatusCode = iota
|
||||
OK
|
||||
Canceled
|
||||
InvalidArgument
|
||||
DeadlineExceeded
|
||||
NotFound
|
||||
AlreadyExists
|
||||
PermissionDenied
|
||||
ResourceExhausted
|
||||
FailedPrecondition
|
||||
Aborted
|
||||
OutOfRange
|
||||
Unimplemented
|
||||
Internal
|
||||
Unavailable
|
||||
DataLoss
|
||||
Unauthenticated
|
||||
)
|
||||
|
||||
// Code returns the status code associated with the error.
|
||||
func Code(err error) StatusCode {
|
||||
return status.Code(err)
|
||||
// special case: if the error is context canceled or deadline exceeded, the code
|
||||
// must be those.
|
||||
switch err {
|
||||
case context.Canceled:
|
||||
return Canceled
|
||||
case context.DeadlineExceeded:
|
||||
return DeadlineExceeded
|
||||
default:
|
||||
code := StatusCode(drpcerr.Code(err))
|
||||
if code == Unknown {
|
||||
// it's unknown, but it might be a known grpc error
|
||||
grpccode := status.Code(err)
|
||||
if grpccode != codes.Unknown {
|
||||
return codeGRPCToDRPC(grpccode)
|
||||
}
|
||||
}
|
||||
return code
|
||||
}
|
||||
}
|
||||
|
||||
// Error wraps the message with a status code into an error.
|
||||
func Error(code StatusCode, msg string) error {
|
||||
return status.Error(code, msg)
|
||||
return &codeErr{
|
||||
err: errors.New(msg),
|
||||
code: uint64(code),
|
||||
grpc: status.New(codeDRPCToGRPC(code), msg),
|
||||
}
|
||||
}
|
||||
|
||||
// Errorf : Error :: fmt.Sprintf : fmt.Sprint
|
||||
func Errorf(code StatusCode, format string, a ...interface{}) error {
|
||||
return status.Errorf(code, format, a...)
|
||||
return &codeErr{
|
||||
err: fmt.Errorf(format, a...),
|
||||
code: uint64(code),
|
||||
grpc: status.Newf(codeDRPCToGRPC(code), format, a...),
|
||||
}
|
||||
}
|
||||
|
||||
// codeErr implements error that can work both in grpc and drpc.
|
||||
type codeErr struct {
|
||||
err error
|
||||
code uint64
|
||||
grpc *status.Status
|
||||
}
|
||||
|
||||
func (c *codeErr) Error() string { return c.err.Error() }
|
||||
func (c *codeErr) Unwrap() error { return c.err }
|
||||
func (c *codeErr) Cause() error { return c.err }
|
||||
func (c *codeErr) Code() uint64 { return c.code }
|
||||
func (c *codeErr) GRPCStatus() *status.Status { return c.grpc }
|
||||
|
||||
func codeDRPCToGRPC(code StatusCode) codes.Code {
|
||||
switch code {
|
||||
case Unknown:
|
||||
return codes.Unknown
|
||||
case OK:
|
||||
return codes.OK
|
||||
case Canceled:
|
||||
return codes.Canceled
|
||||
case InvalidArgument:
|
||||
return codes.InvalidArgument
|
||||
case DeadlineExceeded:
|
||||
return codes.DeadlineExceeded
|
||||
case NotFound:
|
||||
return codes.NotFound
|
||||
case AlreadyExists:
|
||||
return codes.AlreadyExists
|
||||
case PermissionDenied:
|
||||
return codes.PermissionDenied
|
||||
case ResourceExhausted:
|
||||
return codes.ResourceExhausted
|
||||
case FailedPrecondition:
|
||||
return codes.FailedPrecondition
|
||||
case Aborted:
|
||||
return codes.Aborted
|
||||
case OutOfRange:
|
||||
return codes.OutOfRange
|
||||
case Unimplemented:
|
||||
return codes.Unimplemented
|
||||
case Internal:
|
||||
return codes.Internal
|
||||
case Unavailable:
|
||||
return codes.Unavailable
|
||||
case DataLoss:
|
||||
return codes.DataLoss
|
||||
case Unauthenticated:
|
||||
return codes.Unauthenticated
|
||||
default:
|
||||
return codes.Unknown
|
||||
}
|
||||
}
|
||||
|
||||
func codeGRPCToDRPC(code codes.Code) StatusCode {
|
||||
switch code {
|
||||
case codes.Unknown:
|
||||
return Unknown
|
||||
case codes.OK:
|
||||
return OK
|
||||
case codes.Canceled:
|
||||
return Canceled
|
||||
case codes.InvalidArgument:
|
||||
return InvalidArgument
|
||||
case codes.DeadlineExceeded:
|
||||
return DeadlineExceeded
|
||||
case codes.NotFound:
|
||||
return NotFound
|
||||
case codes.AlreadyExists:
|
||||
return AlreadyExists
|
||||
case codes.PermissionDenied:
|
||||
return PermissionDenied
|
||||
case codes.ResourceExhausted:
|
||||
return ResourceExhausted
|
||||
case codes.FailedPrecondition:
|
||||
return FailedPrecondition
|
||||
case codes.Aborted:
|
||||
return Aborted
|
||||
case codes.OutOfRange:
|
||||
return OutOfRange
|
||||
case codes.Unimplemented:
|
||||
return Unimplemented
|
||||
case codes.Internal:
|
||||
return Internal
|
||||
case codes.Unavailable:
|
||||
return Unavailable
|
||||
case codes.DataLoss:
|
||||
return DataLoss
|
||||
case codes.Unauthenticated:
|
||||
return Unauthenticated
|
||||
default:
|
||||
return Unknown
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user