package transport import ( "context" "errors" pb "git.sendico.io/tech/sxchnge/notifications/interface/notifications/v1" "git.sendico.io/tech/sxchnge/notifications/model" merrors "git.sendico.io/tech/sxchnge/shared/errors" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) type API interface { Send(context.Context, string, model.Request) (*model.Notification, error) Get(context.Context, string, string) (*model.Notification, error) } type Server struct { pb.UnimplementedNotificationsServiceServer service API } // The private endpoint uses the existing product storage namespace without caller authentication. func New(service API) *Server { return &Server{service: service} } func (s *Server) Send(ctx context.Context, r *pb.SendRequest) (*pb.SendResponse, error) { input, err := request(r) if err != nil { return nil, rpcError(err) } n, err := s.service.Send(ctx, "product", input) if err != nil { return nil, rpcError(err) } return &pb.SendResponse{Notification: response(n)}, nil } func (s *Server) Get(ctx context.Context, r *pb.GetRequest) (*pb.GetResponse, error) { if r == nil { return nil, status.Error(codes.InvalidArgument, "missing request") } n, err := s.service.Get(ctx, "product", r.Id) if err != nil { return nil, rpcError(err) } return &pb.GetResponse{Notification: response(n)}, nil } func rpcError(err error) error { if errors.Is(err, context.Canceled) { return status.Error(codes.Canceled, "notification operation canceled") } if errors.Is(err, context.DeadlineExceeded) { return status.Error(codes.DeadlineExceeded, "notification operation deadline exceeded") } for _, pair := range []struct { err error code codes.Code message string }{ {merrors.ErrInvalidArg, codes.InvalidArgument, "invalid notification request"}, {merrors.ErrNoData, codes.NotFound, "notification or template not found"}, {merrors.ErrDataConflict, codes.AlreadyExists, "idempotency key already used"}, {merrors.ErrUnauthorized, codes.Unauthenticated, "missing service credentials"}, {merrors.ErrAccessDenied, codes.PermissionDenied, "access denied"}, {merrors.ErrNotImplemented, codes.Unimplemented, "channel is not implemented"}, {merrors.ErrServiceUnavailable, codes.Unavailable, "notification storage unavailable"}, } { if errors.Is(err, pair.err) { return status.Error(pair.code, pair.message) } } return status.Error(codes.Internal, "notification operation failed") }