Files
2026-08-30 09:46:58 -07:00

63 lines
1.6 KiB
Go

package kmsvc
import (
"errors"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
// Sentinel errors callers can match with errors.Is, so they never need to
// import google.golang.org/grpc/status themselves.
var (
ErrQueueNotFound = errors.New("kmsvc: queue not found")
ErrAlreadyExists = errors.New("kmsvc: already exists")
ErrInvalidArgument = errors.New("kmsvc: invalid argument")
ErrUnauthenticated = errors.New("kmsvc: unauthenticated")
ErrMessageTooLarge = errors.New("kmsvc: message body too large")
)
// mapError wraps a gRPC error with the matching sentinel above (when one
// applies) so errors.Is works for callers, while preserving the original
// error via %w for inspection/logging.
func mapError(err error) error {
if err == nil {
return nil
}
st, ok := status.FromError(err)
if !ok {
return err
}
switch st.Code() {
case codes.NotFound:
return joinSentinel(ErrQueueNotFound, err)
case codes.AlreadyExists:
return joinSentinel(ErrAlreadyExists, err)
case codes.InvalidArgument:
return joinSentinel(ErrInvalidArgument, err)
case codes.Unauthenticated:
return joinSentinel(ErrUnauthenticated, err)
case codes.ResourceExhausted:
return joinSentinel(ErrMessageTooLarge, err)
default:
return err
}
}
func joinSentinel(sentinel, original error) error {
return &sentinelError{sentinel: sentinel, original: original}
}
type sentinelError struct {
sentinel error
original error
}
func (e *sentinelError) Error() string { return e.original.Error() }
func (e *sentinelError) Unwrap() error { return e.original }
func (e *sentinelError) Is(target error) bool {
return target == e.sentinel
}