diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index c89c65b..6c35dc2 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -204,7 +204,7 @@ Update notification status ### Hierarchy (highest to lowest priority) 1. Environment variables (prefixed with `NOTIFIER_`) -2. Configuration file (notifier.config) +2. Configuration file (config.yaml) 3. Default values ### Example Environment Variables @@ -296,7 +296,7 @@ NOTIFIER_NOTIFIERS_SLACK_WEBHOOK_URL=https://hooks.slack.com/... 3. Add configuration struct to `internal/config/` 4. Register in factory during initialization 5. Update protobuf and REST API types -6. Add configuration example to `notifier.config` +6. Add configuration example to `config.yaml` ### Adding a New Queue Implementation diff --git a/Dockerfile b/Dockerfile index 2205728..fc83196 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,11 @@ # Build stage FROM golang:1.24-alpine AS builder +# Build arguments +ARG VERSION=dev +ARG GIT_COMMIT=unknown +ARG BUILD_TIME=unknown + # Install build dependencies RUN apk add --no-cache git make @@ -16,8 +21,10 @@ RUN go mod download # Copy source code COPY . . -# Build binary -RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o server ./cmd/server +# Build binary with version information +RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo \ + -ldflags "-X main.Version=${VERSION} -X main.GitCommit=${GIT_COMMIT} -X main.BuildTime=${BUILD_TIME}" \ + -o server ./cmd/server # Runtime stage FROM alpine:latest @@ -36,7 +43,7 @@ WORKDIR /app COPY --from=builder /build/server /app/ # Copy default config (can be overridden with volume mount) -COPY notifier.config /app/notifier.config +COPY config.yaml /app/config.yaml # Create directory for queue persistence RUN mkdir -p /var/lib/notifier && \ diff --git a/Makefile b/Makefile index 51452ea..b92597f 100644 --- a/Makefile +++ b/Makefile @@ -7,12 +7,18 @@ PROTO_OUT=$(PROTO_DIR)/pb GO_MODULE=$(shell head -n 1 go.mod | awk '{print $$2}') GO_FILES=$(shell find . -type f -name '*.go' -not -path "./vendor/*" -not -path "./api/grpc/pb/*") +# Build information +VERSION ?= dev +GIT_COMMIT := $(shell git rev-parse --short HEAD 2>/dev/null || echo "unknown") +BUILD_TIME := $(shell date -u '+%Y-%m-%d_%H:%M:%S_UTC') +LDFLAGS := -X main.Version=$(VERSION) -X main.GitCommit=$(GIT_COMMIT) -X main.BuildTime=$(BUILD_TIME) + # Generate protobuf code proto-gen: @echo "Generating protobuf code..." @mkdir -p $(PROTO_OUT) - protoc --go_out=$(PROTO_OUT) --go_opt=paths=source_relative \ - --go-grpc_out=$(PROTO_OUT) --go-grpc_opt=paths=source_relative \ + protoc -I. --go_out=. --go_opt=module=$(GO_MODULE) \ + --go-grpc_out=. --go-grpc_opt=module=$(GO_MODULE) \ $(PROTO_FILE) @echo "Protobuf code generated successfully" @@ -39,8 +45,11 @@ proto-deps: # Build binary build: @echo "Building binary..." + @echo "Version: $(VERSION)" + @echo "Git Commit: $(GIT_COMMIT)" + @echo "Build Time: $(BUILD_TIME)" @mkdir -p bin - go build -o bin/server ./cmd/server + go build -ldflags "$(LDFLAGS)" -o bin/server ./cmd/server @echo "Binary built successfully" # Run server (default: both REST and gRPC) @@ -112,13 +121,20 @@ qa: fmt vet lint test # Build Docker image docker-build: @echo "Building Docker image..." - docker build -t notifier:latest . + @echo "Version: $(VERSION)" + @echo "Git Commit: $(GIT_COMMIT)" + @echo "Build Time: $(BUILD_TIME)" + docker build \ + --build-arg VERSION=$(VERSION) \ + --build-arg GIT_COMMIT=$(GIT_COMMIT) \ + --build-arg BUILD_TIME=$(BUILD_TIME) \ + -t notifier:latest . @echo "Docker image built successfully" # Run Docker container docker-run: @echo "Running Docker container..." - docker run -p 8080:8080 -p 50051:50051 -v $(PWD)/notifier.config:/app/notifier.config notifier:latest + docker run -p 8080:8080 -p 50051:50051 -v $(PWD)/config.yaml:/app/config.yaml notifier:latest # Clean build artifacts clean: diff --git a/QUICKSTART.md b/QUICKSTART.md index d7fd56b..4d20df1 100644 --- a/QUICKSTART.md +++ b/QUICKSTART.md @@ -149,7 +149,7 @@ curl http://localhost:8080/api/v1/notifications/{notification-id} ## Testing with Other Notifiers ### SMTP (Email) -Update `notifier.config` with named accounts: +Update `config.yaml` with named accounts: ```yaml notifiers: smtp: @@ -195,7 +195,7 @@ curl -X POST http://localhost:8080/api/v1/notifications \ ``` ### Slack -Update `notifier.config` with named workspaces: +Update `config.yaml` with named workspaces: ```yaml notifiers: slack: @@ -235,7 +235,7 @@ curl -X POST http://localhost:8080/api/v1/notifications \ ``` ### Ntfy -Update `notifier.config` with named servers: +Update `config.yaml` with named servers: ```yaml notifiers: ntfy: @@ -287,8 +287,8 @@ export NOTIFIER_NOTIFIERS_SMTP_PASSWORD=secret ./bin/restserver ``` -### Using notifier.config -Create or modify `notifier.config` in the project root: +### Using config.yaml +Create or modify `config.yaml` in the project root: ```yaml server: rest_port: 8080 @@ -312,7 +312,7 @@ docker build -t notifier:latest . ### Run with Docker ```bash docker run -p 8080:8080 \ - -v $(pwd)/notifier.config:/app/notifier.config \ + -v $(pwd)/config.yaml:/app/config.yaml \ notifier:latest ``` @@ -353,18 +353,18 @@ kubectl port-forward svc/notifier-rest 8080:8080 ### Server won't start - Check if port 8080 is already in use: `lsof -i :8080` -- Check notifier.config syntax +- Check config.yaml syntax - Verify all dependencies are installed: `go mod tidy` ### Notifications not sending - Check server logs for errors -- Verify the notifier is enabled in notifier.config +- Verify the notifier is enabled in config.yaml - For SMTP: Verify credentials and allow less secure apps - For Slack: Verify webhook URL is correct - For Ntfy: Ensure topic name is valid ### Queue filling up -- Increase worker count in notifier.config +- Increase worker count in config.yaml - Check if notifiers are failing - Review retry configuration diff --git a/README.md b/README.md index 9a144e8..4c608b3 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ curl http://localhost:8080/api/v1/stats ### Basic Setup -Create `notifier.config` in the project root: +Create `config.yaml` in the project root: ```yaml server: @@ -380,7 +380,7 @@ docker run -d \ --name notifier \ -p 8080:8080 \ -p 50051:50051 \ - -v $(pwd)/notifier.config:/app/notifier.config:ro \ + -v $(pwd)/config.yaml:/app/config.yaml:ro \ notifier:latest ``` @@ -515,7 +515,7 @@ notifier/ │ └── kustomization.yaml ├── docs/ │ └── NTFY_GUIDE.md # Ntfy integration guide -├── notifier.config # Default configuration +├── config.yaml # Default configuration ├── docker-compose.yaml ├── Dockerfile ├── Makefile @@ -552,7 +552,7 @@ make help # Show all available targets 2. Implement `domain.Notifier` interface 3. Add config struct to `internal/config/config.go` 4. Register in `cmd/server/main.go` -5. Update `notifier.config` with example config +5. Update `config.yaml` with example config 6. Add tests Example: diff --git a/api/grpc/handler.go b/api/grpc/handler.go new file mode 100644 index 0000000..8993d43 --- /dev/null +++ b/api/grpc/handler.go @@ -0,0 +1,351 @@ +package grpc + +import ( + "context" + "fmt" + + pb "github.com/igodwin/notifier/api/grpc/pb" + "github.com/igodwin/notifier/internal/domain" + "google.golang.org/protobuf/types/known/timestamppb" +) + +// NotifierHandler implements the gRPC NotifierService +type NotifierHandler struct { + pb.UnimplementedNotifierServiceServer + service domain.NotificationService +} + +// NewNotifierHandler creates a new gRPC handler +func NewNotifierHandler(svc domain.NotificationService) *NotifierHandler { + return &NotifierHandler{ + service: svc, + } +} + +// HealthCheck verifies the service is operational +func (h *NotifierHandler) HealthCheck(ctx context.Context, req *pb.HealthCheckRequest) (*pb.HealthCheckResponse, error) { + // TODO: Implement proper health check logic + return &pb.HealthCheckResponse{ + Healthy: true, + Status: "ok", + Components: map[string]string{ + "service": "running", + }, + }, nil +} + +// SendNotification sends a single notification +func (h *NotifierHandler) SendNotification(ctx context.Context, req *pb.SendNotificationRequest) (*pb.SendNotificationResponse, error) { + // Convert proto notification type to domain type + notifType := convertProtoTypeToDomain(req.Type) + + // Build notification + notification := &domain.Notification{ + Type: notifType, + Account: req.Account, + Priority: domain.Priority(req.Priority), + Subject: req.Subject, + Body: req.Body, + Recipients: req.Recipients, + Metadata: convertStringMapToInterface(req.Metadata), + MaxRetries: int(req.MaxRetries), + } + + if req.ScheduledFor != nil { + scheduledTime := req.ScheduledFor.AsTime() + notification.ScheduledFor = &scheduledTime + } + + // Send notification + result, err := h.service.Send(ctx, notification) + if err != nil { + return &pb.SendNotificationResponse{ + Result: &pb.NotificationResult{ + Success: false, + Error: err.Error(), + }, + }, nil + } + + // Convert result to proto + return &pb.SendNotificationResponse{ + Result: &pb.NotificationResult{ + NotificationId: result.NotificationID, + Success: result.Success, + Message: result.Message, + SentAt: timestamppb.New(result.SentAt), + }, + }, nil +} + +// SendBatchNotifications sends multiple notifications +func (h *NotifierHandler) SendBatchNotifications(ctx context.Context, req *pb.SendBatchNotificationsRequest) (*pb.SendBatchNotificationsResponse, error) { + var results []*pb.NotificationResult + + for _, notifReq := range req.Notifications { + resp, err := h.SendNotification(ctx, notifReq) + if err != nil { + results = append(results, &pb.NotificationResult{ + Success: false, + Error: err.Error(), + }) + } else { + results = append(results, resp.Result) + } + } + + return &pb.SendBatchNotificationsResponse{ + Results: results, + }, nil +} + +// GetNotification retrieves a notification by ID +func (h *NotifierHandler) GetNotification(ctx context.Context, req *pb.GetNotificationRequest) (*pb.GetNotificationResponse, error) { + notification, err := h.service.GetNotification(ctx, req.Id) + if err != nil { + return nil, err + } + + return &pb.GetNotificationResponse{ + Notification: convertDomainToProtoNotification(notification), + }, nil +} + +// ListNotifications retrieves notifications matching a filter +func (h *NotifierHandler) ListNotifications(ctx context.Context, req *pb.ListNotificationsRequest) (*pb.ListNotificationsResponse, error) { + // Convert proto filter to domain filter + filter := convertProtoFilterToDomain(req.Filter) + + notifications, err := h.service.ListNotifications(ctx, filter) + if err != nil { + return nil, err + } + + protoNotifications := make([]*pb.Notification, len(notifications)) + for i, notif := range notifications { + protoNotifications[i] = convertDomainToProtoNotification(notif) + } + + return &pb.ListNotificationsResponse{ + Notifications: protoNotifications, + Total: int64(len(notifications)), + }, nil +} + +// CancelNotification cancels a pending notification +func (h *NotifierHandler) CancelNotification(ctx context.Context, req *pb.CancelNotificationRequest) (*pb.CancelNotificationResponse, error) { + err := h.service.CancelNotification(ctx, req.Id) + if err != nil { + return &pb.CancelNotificationResponse{ + Success: false, + Message: err.Error(), + }, nil + } + + return &pb.CancelNotificationResponse{ + Success: true, + Message: "notification cancelled successfully", + }, nil +} + +// RetryNotification retries a failed notification +func (h *NotifierHandler) RetryNotification(ctx context.Context, req *pb.RetryNotificationRequest) (*pb.RetryNotificationResponse, error) { + result, err := h.service.RetryNotification(ctx, req.Id) + if err != nil { + return &pb.RetryNotificationResponse{ + Result: &pb.NotificationResult{ + Success: false, + Error: err.Error(), + }, + }, nil + } + + return &pb.RetryNotificationResponse{ + Result: &pb.NotificationResult{ + NotificationId: result.NotificationID, + Success: result.Success, + Message: result.Message, + SentAt: timestamppb.New(result.SentAt), + }, + }, nil +} + +// GetStats returns notification statistics +func (h *NotifierHandler) GetStats(ctx context.Context, req *pb.GetStatsRequest) (*pb.GetStatsResponse, error) { + stats, err := h.service.GetStats(ctx) + if err != nil { + return nil, err + } + + return &pb.GetStatsResponse{ + TotalSent: stats.TotalSent, + TotalFailed: stats.TotalFailed, + TotalPending: stats.TotalPending, + TotalQueued: stats.TotalQueued, + ByType: stats.ByType, + ByStatus: stats.ByStatus, + }, nil +} + +// Helper functions to convert between proto and domain types + +// convertStringMapToInterface converts proto's map[string]string to domain's map[string]interface{} +func convertStringMapToInterface(m map[string]string) map[string]interface{} { + if m == nil { + return nil + } + result := make(map[string]interface{}, len(m)) + for k, v := range m { + result[k] = v + } + return result +} + +// convertInterfaceMapToString converts domain's map[string]interface{} to proto's map[string]string +func convertInterfaceMapToString(m map[string]interface{}) map[string]string { + if m == nil { + return nil + } + result := make(map[string]string, len(m)) + for k, v := range m { + if v != nil { + result[k] = fmt.Sprint(v) + } + } + return result +} + +func convertProtoTypeToDomain(protoType pb.NotificationType) domain.NotificationType { + switch protoType { + case pb.NotificationType_NOTIFICATION_TYPE_EMAIL: + return domain.TypeEmail + case pb.NotificationType_NOTIFICATION_TYPE_SLACK: + return domain.TypeSlack + case pb.NotificationType_NOTIFICATION_TYPE_NTFY: + return domain.TypeNtfy + case pb.NotificationType_NOTIFICATION_TYPE_STDOUT: + return domain.TypeStdout + default: + return domain.TypeStdout + } +} + +func convertDomainToProtoType(domainType domain.NotificationType) pb.NotificationType { + switch domainType { + case domain.TypeEmail: + return pb.NotificationType_NOTIFICATION_TYPE_EMAIL + case domain.TypeSlack: + return pb.NotificationType_NOTIFICATION_TYPE_SLACK + case domain.TypeNtfy: + return pb.NotificationType_NOTIFICATION_TYPE_NTFY + case domain.TypeStdout: + return pb.NotificationType_NOTIFICATION_TYPE_STDOUT + default: + return pb.NotificationType_NOTIFICATION_TYPE_UNSPECIFIED + } +} + +func convertDomainToProtoStatus(status domain.NotificationStatus) pb.NotificationStatus { + switch status { + case domain.StatusPending: + return pb.NotificationStatus_NOTIFICATION_STATUS_PENDING + case domain.StatusQueued: + return pb.NotificationStatus_NOTIFICATION_STATUS_QUEUED + case domain.StatusProcessing: + return pb.NotificationStatus_NOTIFICATION_STATUS_PROCESSING + case domain.StatusSent: + return pb.NotificationStatus_NOTIFICATION_STATUS_SENT + case domain.StatusFailed: + return pb.NotificationStatus_NOTIFICATION_STATUS_FAILED + case domain.StatusRetrying: + return pb.NotificationStatus_NOTIFICATION_STATUS_RETRYING + default: + return pb.NotificationStatus_NOTIFICATION_STATUS_UNSPECIFIED + } +} + +func convertDomainToProtoNotification(notif *domain.Notification) *pb.Notification { + protoNotif := &pb.Notification{ + Id: notif.ID, + Type: convertDomainToProtoType(notif.Type), + Account: notif.Account, + Priority: pb.Priority(notif.Priority), + Status: convertDomainToProtoStatus(notif.Status), + Subject: notif.Subject, + Body: notif.Body, + Recipients: notif.Recipients, + Metadata: convertInterfaceMapToString(notif.Metadata), + CreatedAt: timestamppb.New(notif.CreatedAt), + RetryCount: int32(notif.RetryCount), + MaxRetries: int32(notif.MaxRetries), + LastError: notif.LastError, + } + + // Handle optional timestamp fields + if notif.ScheduledFor != nil { + protoNotif.ScheduledFor = timestamppb.New(*notif.ScheduledFor) + } + if notif.SentAt != nil { + protoNotif.SentAt = timestamppb.New(*notif.SentAt) + } + + return protoNotif +} + +func convertProtoFilterToDomain(filter *pb.NotificationFilter) *domain.NotificationFilter { + if filter == nil { + return &domain.NotificationFilter{} + } + + // Convert proto types to domain types + var types []domain.NotificationType + for _, protoType := range filter.Types { + types = append(types, convertProtoTypeToDomain(protoType)) + } + + // Convert proto statuses to domain statuses + var statuses []domain.NotificationStatus + for _, protoStatus := range filter.Statuses { + statuses = append(statuses, convertProtoStatusToDomain(protoStatus)) + } + + domainFilter := &domain.NotificationFilter{ + IDs: filter.Ids, + Types: types, + Statuses: statuses, + Recipients: filter.Recipients, + Limit: int(filter.Limit), + Offset: int(filter.Offset), + } + + if filter.CreatedAfter != nil { + createdAfter := filter.CreatedAfter.AsTime() + domainFilter.CreatedAfter = &createdAfter + } + + if filter.CreatedBefore != nil { + createdBefore := filter.CreatedBefore.AsTime() + domainFilter.CreatedBefore = &createdBefore + } + + return domainFilter +} + +func convertProtoStatusToDomain(protoStatus pb.NotificationStatus) domain.NotificationStatus { + switch protoStatus { + case pb.NotificationStatus_NOTIFICATION_STATUS_PENDING: + return domain.StatusPending + case pb.NotificationStatus_NOTIFICATION_STATUS_QUEUED: + return domain.StatusQueued + case pb.NotificationStatus_NOTIFICATION_STATUS_PROCESSING: + return domain.StatusProcessing + case pb.NotificationStatus_NOTIFICATION_STATUS_SENT: + return domain.StatusSent + case pb.NotificationStatus_NOTIFICATION_STATUS_FAILED: + return domain.StatusFailed + case pb.NotificationStatus_NOTIFICATION_STATUS_RETRYING: + return domain.StatusRetrying + default: + return domain.StatusPending + } +} diff --git a/api/grpc/pb/api/grpc/notifier.pb.go b/api/grpc/pb/api/grpc/notifier.pb.go deleted file mode 100644 index 610fcae..0000000 --- a/api/grpc/pb/api/grpc/notifier.pb.go +++ /dev/null @@ -1,1657 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.36.10 -// protoc v6.33.0 -// source: api/grpc/notifier.proto - -package pb - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - timestamppb "google.golang.org/protobuf/types/known/timestamppb" - reflect "reflect" - sync "sync" - unsafe "unsafe" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// NotificationType defines the channel for notification delivery -type NotificationType int32 - -const ( - NotificationType_NOTIFICATION_TYPE_UNSPECIFIED NotificationType = 0 - NotificationType_NOTIFICATION_TYPE_EMAIL NotificationType = 1 - NotificationType_NOTIFICATION_TYPE_SLACK NotificationType = 2 - NotificationType_NOTIFICATION_TYPE_NTFY NotificationType = 3 - NotificationType_NOTIFICATION_TYPE_STDOUT NotificationType = 4 -) - -// Enum value maps for NotificationType. -var ( - NotificationType_name = map[int32]string{ - 0: "NOTIFICATION_TYPE_UNSPECIFIED", - 1: "NOTIFICATION_TYPE_EMAIL", - 2: "NOTIFICATION_TYPE_SLACK", - 3: "NOTIFICATION_TYPE_NTFY", - 4: "NOTIFICATION_TYPE_STDOUT", - } - NotificationType_value = map[string]int32{ - "NOTIFICATION_TYPE_UNSPECIFIED": 0, - "NOTIFICATION_TYPE_EMAIL": 1, - "NOTIFICATION_TYPE_SLACK": 2, - "NOTIFICATION_TYPE_NTFY": 3, - "NOTIFICATION_TYPE_STDOUT": 4, - } -) - -func (x NotificationType) Enum() *NotificationType { - p := new(NotificationType) - *p = x - return p -} - -func (x NotificationType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (NotificationType) Descriptor() protoreflect.EnumDescriptor { - return file_api_grpc_notifier_proto_enumTypes[0].Descriptor() -} - -func (NotificationType) Type() protoreflect.EnumType { - return &file_api_grpc_notifier_proto_enumTypes[0] -} - -func (x NotificationType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use NotificationType.Descriptor instead. -func (NotificationType) EnumDescriptor() ([]byte, []int) { - return file_api_grpc_notifier_proto_rawDescGZIP(), []int{0} -} - -// Priority defines the urgency level -type Priority int32 - -const ( - Priority_PRIORITY_UNSPECIFIED Priority = 0 - Priority_PRIORITY_LOW Priority = 1 - Priority_PRIORITY_NORMAL Priority = 2 - Priority_PRIORITY_HIGH Priority = 3 - Priority_PRIORITY_CRITICAL Priority = 4 -) - -// Enum value maps for Priority. -var ( - Priority_name = map[int32]string{ - 0: "PRIORITY_UNSPECIFIED", - 1: "PRIORITY_LOW", - 2: "PRIORITY_NORMAL", - 3: "PRIORITY_HIGH", - 4: "PRIORITY_CRITICAL", - } - Priority_value = map[string]int32{ - "PRIORITY_UNSPECIFIED": 0, - "PRIORITY_LOW": 1, - "PRIORITY_NORMAL": 2, - "PRIORITY_HIGH": 3, - "PRIORITY_CRITICAL": 4, - } -) - -func (x Priority) Enum() *Priority { - p := new(Priority) - *p = x - return p -} - -func (x Priority) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (Priority) Descriptor() protoreflect.EnumDescriptor { - return file_api_grpc_notifier_proto_enumTypes[1].Descriptor() -} - -func (Priority) Type() protoreflect.EnumType { - return &file_api_grpc_notifier_proto_enumTypes[1] -} - -func (x Priority) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use Priority.Descriptor instead. -func (Priority) EnumDescriptor() ([]byte, []int) { - return file_api_grpc_notifier_proto_rawDescGZIP(), []int{1} -} - -// NotificationStatus represents the state of a notification -type NotificationStatus int32 - -const ( - NotificationStatus_NOTIFICATION_STATUS_UNSPECIFIED NotificationStatus = 0 - NotificationStatus_NOTIFICATION_STATUS_PENDING NotificationStatus = 1 - NotificationStatus_NOTIFICATION_STATUS_QUEUED NotificationStatus = 2 - NotificationStatus_NOTIFICATION_STATUS_PROCESSING NotificationStatus = 3 - NotificationStatus_NOTIFICATION_STATUS_SENT NotificationStatus = 4 - NotificationStatus_NOTIFICATION_STATUS_FAILED NotificationStatus = 5 - NotificationStatus_NOTIFICATION_STATUS_RETRYING NotificationStatus = 6 -) - -// Enum value maps for NotificationStatus. -var ( - NotificationStatus_name = map[int32]string{ - 0: "NOTIFICATION_STATUS_UNSPECIFIED", - 1: "NOTIFICATION_STATUS_PENDING", - 2: "NOTIFICATION_STATUS_QUEUED", - 3: "NOTIFICATION_STATUS_PROCESSING", - 4: "NOTIFICATION_STATUS_SENT", - 5: "NOTIFICATION_STATUS_FAILED", - 6: "NOTIFICATION_STATUS_RETRYING", - } - NotificationStatus_value = map[string]int32{ - "NOTIFICATION_STATUS_UNSPECIFIED": 0, - "NOTIFICATION_STATUS_PENDING": 1, - "NOTIFICATION_STATUS_QUEUED": 2, - "NOTIFICATION_STATUS_PROCESSING": 3, - "NOTIFICATION_STATUS_SENT": 4, - "NOTIFICATION_STATUS_FAILED": 5, - "NOTIFICATION_STATUS_RETRYING": 6, - } -) - -func (x NotificationStatus) Enum() *NotificationStatus { - p := new(NotificationStatus) - *p = x - return p -} - -func (x NotificationStatus) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (NotificationStatus) Descriptor() protoreflect.EnumDescriptor { - return file_api_grpc_notifier_proto_enumTypes[2].Descriptor() -} - -func (NotificationStatus) Type() protoreflect.EnumType { - return &file_api_grpc_notifier_proto_enumTypes[2] -} - -func (x NotificationStatus) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use NotificationStatus.Descriptor instead. -func (NotificationStatus) EnumDescriptor() ([]byte, []int) { - return file_api_grpc_notifier_proto_rawDescGZIP(), []int{2} -} - -// Notification represents a notification message -type Notification struct { - state protoimpl.MessageState `protogen:"open.v1"` - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Type NotificationType `protobuf:"varint,2,opt,name=type,proto3,enum=notifier.v1.NotificationType" json:"type,omitempty"` - Account string `protobuf:"bytes,3,opt,name=account,proto3" json:"account,omitempty"` // Optional account name for multi-account configs - Priority Priority `protobuf:"varint,4,opt,name=priority,proto3,enum=notifier.v1.Priority" json:"priority,omitempty"` - Status NotificationStatus `protobuf:"varint,5,opt,name=status,proto3,enum=notifier.v1.NotificationStatus" json:"status,omitempty"` - Subject string `protobuf:"bytes,6,opt,name=subject,proto3" json:"subject,omitempty"` - Body string `protobuf:"bytes,7,opt,name=body,proto3" json:"body,omitempty"` - Recipients []string `protobuf:"bytes,8,rep,name=recipients,proto3" json:"recipients,omitempty"` - Metadata map[string]string `protobuf:"bytes,9,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - CreatedAt *timestamppb.Timestamp `protobuf:"bytes,10,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` - ScheduledFor *timestamppb.Timestamp `protobuf:"bytes,11,opt,name=scheduled_for,json=scheduledFor,proto3" json:"scheduled_for,omitempty"` - SentAt *timestamppb.Timestamp `protobuf:"bytes,12,opt,name=sent_at,json=sentAt,proto3" json:"sent_at,omitempty"` - RetryCount int32 `protobuf:"varint,13,opt,name=retry_count,json=retryCount,proto3" json:"retry_count,omitempty"` - MaxRetries int32 `protobuf:"varint,14,opt,name=max_retries,json=maxRetries,proto3" json:"max_retries,omitempty"` - LastError string `protobuf:"bytes,15,opt,name=last_error,json=lastError,proto3" json:"last_error,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *Notification) Reset() { - *x = Notification{} - mi := &file_api_grpc_notifier_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *Notification) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Notification) ProtoMessage() {} - -func (x *Notification) ProtoReflect() protoreflect.Message { - mi := &file_api_grpc_notifier_proto_msgTypes[0] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Notification.ProtoReflect.Descriptor instead. -func (*Notification) Descriptor() ([]byte, []int) { - return file_api_grpc_notifier_proto_rawDescGZIP(), []int{0} -} - -func (x *Notification) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *Notification) GetType() NotificationType { - if x != nil { - return x.Type - } - return NotificationType_NOTIFICATION_TYPE_UNSPECIFIED -} - -func (x *Notification) GetAccount() string { - if x != nil { - return x.Account - } - return "" -} - -func (x *Notification) GetPriority() Priority { - if x != nil { - return x.Priority - } - return Priority_PRIORITY_UNSPECIFIED -} - -func (x *Notification) GetStatus() NotificationStatus { - if x != nil { - return x.Status - } - return NotificationStatus_NOTIFICATION_STATUS_UNSPECIFIED -} - -func (x *Notification) GetSubject() string { - if x != nil { - return x.Subject - } - return "" -} - -func (x *Notification) GetBody() string { - if x != nil { - return x.Body - } - return "" -} - -func (x *Notification) GetRecipients() []string { - if x != nil { - return x.Recipients - } - return nil -} - -func (x *Notification) GetMetadata() map[string]string { - if x != nil { - return x.Metadata - } - return nil -} - -func (x *Notification) GetCreatedAt() *timestamppb.Timestamp { - if x != nil { - return x.CreatedAt - } - return nil -} - -func (x *Notification) GetScheduledFor() *timestamppb.Timestamp { - if x != nil { - return x.ScheduledFor - } - return nil -} - -func (x *Notification) GetSentAt() *timestamppb.Timestamp { - if x != nil { - return x.SentAt - } - return nil -} - -func (x *Notification) GetRetryCount() int32 { - if x != nil { - return x.RetryCount - } - return 0 -} - -func (x *Notification) GetMaxRetries() int32 { - if x != nil { - return x.MaxRetries - } - return 0 -} - -func (x *Notification) GetLastError() string { - if x != nil { - return x.LastError - } - return "" -} - -// NotificationResult represents the outcome of sending a notification -type NotificationResult struct { - state protoimpl.MessageState `protogen:"open.v1"` - NotificationId string `protobuf:"bytes,1,opt,name=notification_id,json=notificationId,proto3" json:"notification_id,omitempty"` - Success bool `protobuf:"varint,2,opt,name=success,proto3" json:"success,omitempty"` - Message string `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"` - Error string `protobuf:"bytes,4,opt,name=error,proto3" json:"error,omitempty"` - SentAt *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=sent_at,json=sentAt,proto3" json:"sent_at,omitempty"` - ProviderResponse map[string]string `protobuf:"bytes,6,rep,name=provider_response,json=providerResponse,proto3" json:"provider_response,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *NotificationResult) Reset() { - *x = NotificationResult{} - mi := &file_api_grpc_notifier_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *NotificationResult) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*NotificationResult) ProtoMessage() {} - -func (x *NotificationResult) ProtoReflect() protoreflect.Message { - mi := &file_api_grpc_notifier_proto_msgTypes[1] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use NotificationResult.ProtoReflect.Descriptor instead. -func (*NotificationResult) Descriptor() ([]byte, []int) { - return file_api_grpc_notifier_proto_rawDescGZIP(), []int{1} -} - -func (x *NotificationResult) GetNotificationId() string { - if x != nil { - return x.NotificationId - } - return "" -} - -func (x *NotificationResult) GetSuccess() bool { - if x != nil { - return x.Success - } - return false -} - -func (x *NotificationResult) GetMessage() string { - if x != nil { - return x.Message - } - return "" -} - -func (x *NotificationResult) GetError() string { - if x != nil { - return x.Error - } - return "" -} - -func (x *NotificationResult) GetSentAt() *timestamppb.Timestamp { - if x != nil { - return x.SentAt - } - return nil -} - -func (x *NotificationResult) GetProviderResponse() map[string]string { - if x != nil { - return x.ProviderResponse - } - return nil -} - -// SendNotificationRequest sends a single notification -type SendNotificationRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Type NotificationType `protobuf:"varint,1,opt,name=type,proto3,enum=notifier.v1.NotificationType" json:"type,omitempty"` - Account string `protobuf:"bytes,2,opt,name=account,proto3" json:"account,omitempty"` // Optional account name for multi-account configs - Priority Priority `protobuf:"varint,3,opt,name=priority,proto3,enum=notifier.v1.Priority" json:"priority,omitempty"` - Subject string `protobuf:"bytes,4,opt,name=subject,proto3" json:"subject,omitempty"` - Body string `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"` - Recipients []string `protobuf:"bytes,6,rep,name=recipients,proto3" json:"recipients,omitempty"` - Metadata map[string]string `protobuf:"bytes,7,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - ScheduledFor *timestamppb.Timestamp `protobuf:"bytes,8,opt,name=scheduled_for,json=scheduledFor,proto3" json:"scheduled_for,omitempty"` - MaxRetries int32 `protobuf:"varint,9,opt,name=max_retries,json=maxRetries,proto3" json:"max_retries,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SendNotificationRequest) Reset() { - *x = SendNotificationRequest{} - mi := &file_api_grpc_notifier_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SendNotificationRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SendNotificationRequest) ProtoMessage() {} - -func (x *SendNotificationRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_grpc_notifier_proto_msgTypes[2] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SendNotificationRequest.ProtoReflect.Descriptor instead. -func (*SendNotificationRequest) Descriptor() ([]byte, []int) { - return file_api_grpc_notifier_proto_rawDescGZIP(), []int{2} -} - -func (x *SendNotificationRequest) GetType() NotificationType { - if x != nil { - return x.Type - } - return NotificationType_NOTIFICATION_TYPE_UNSPECIFIED -} - -func (x *SendNotificationRequest) GetAccount() string { - if x != nil { - return x.Account - } - return "" -} - -func (x *SendNotificationRequest) GetPriority() Priority { - if x != nil { - return x.Priority - } - return Priority_PRIORITY_UNSPECIFIED -} - -func (x *SendNotificationRequest) GetSubject() string { - if x != nil { - return x.Subject - } - return "" -} - -func (x *SendNotificationRequest) GetBody() string { - if x != nil { - return x.Body - } - return "" -} - -func (x *SendNotificationRequest) GetRecipients() []string { - if x != nil { - return x.Recipients - } - return nil -} - -func (x *SendNotificationRequest) GetMetadata() map[string]string { - if x != nil { - return x.Metadata - } - return nil -} - -func (x *SendNotificationRequest) GetScheduledFor() *timestamppb.Timestamp { - if x != nil { - return x.ScheduledFor - } - return nil -} - -func (x *SendNotificationRequest) GetMaxRetries() int32 { - if x != nil { - return x.MaxRetries - } - return 0 -} - -// SendNotificationResponse returns the result of sending a notification -type SendNotificationResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Result *NotificationResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SendNotificationResponse) Reset() { - *x = SendNotificationResponse{} - mi := &file_api_grpc_notifier_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SendNotificationResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SendNotificationResponse) ProtoMessage() {} - -func (x *SendNotificationResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_grpc_notifier_proto_msgTypes[3] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SendNotificationResponse.ProtoReflect.Descriptor instead. -func (*SendNotificationResponse) Descriptor() ([]byte, []int) { - return file_api_grpc_notifier_proto_rawDescGZIP(), []int{3} -} - -func (x *SendNotificationResponse) GetResult() *NotificationResult { - if x != nil { - return x.Result - } - return nil -} - -// SendBatchNotificationsRequest sends multiple notifications -type SendBatchNotificationsRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Notifications []*SendNotificationRequest `protobuf:"bytes,1,rep,name=notifications,proto3" json:"notifications,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SendBatchNotificationsRequest) Reset() { - *x = SendBatchNotificationsRequest{} - mi := &file_api_grpc_notifier_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SendBatchNotificationsRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SendBatchNotificationsRequest) ProtoMessage() {} - -func (x *SendBatchNotificationsRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_grpc_notifier_proto_msgTypes[4] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SendBatchNotificationsRequest.ProtoReflect.Descriptor instead. -func (*SendBatchNotificationsRequest) Descriptor() ([]byte, []int) { - return file_api_grpc_notifier_proto_rawDescGZIP(), []int{4} -} - -func (x *SendBatchNotificationsRequest) GetNotifications() []*SendNotificationRequest { - if x != nil { - return x.Notifications - } - return nil -} - -// SendBatchNotificationsResponse returns the results of sending multiple notifications -type SendBatchNotificationsResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Results []*NotificationResult `protobuf:"bytes,1,rep,name=results,proto3" json:"results,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SendBatchNotificationsResponse) Reset() { - *x = SendBatchNotificationsResponse{} - mi := &file_api_grpc_notifier_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SendBatchNotificationsResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SendBatchNotificationsResponse) ProtoMessage() {} - -func (x *SendBatchNotificationsResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_grpc_notifier_proto_msgTypes[5] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SendBatchNotificationsResponse.ProtoReflect.Descriptor instead. -func (*SendBatchNotificationsResponse) Descriptor() ([]byte, []int) { - return file_api_grpc_notifier_proto_rawDescGZIP(), []int{5} -} - -func (x *SendBatchNotificationsResponse) GetResults() []*NotificationResult { - if x != nil { - return x.Results - } - return nil -} - -// GetNotificationRequest retrieves a notification by ID -type GetNotificationRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetNotificationRequest) Reset() { - *x = GetNotificationRequest{} - mi := &file_api_grpc_notifier_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetNotificationRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetNotificationRequest) ProtoMessage() {} - -func (x *GetNotificationRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_grpc_notifier_proto_msgTypes[6] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetNotificationRequest.ProtoReflect.Descriptor instead. -func (*GetNotificationRequest) Descriptor() ([]byte, []int) { - return file_api_grpc_notifier_proto_rawDescGZIP(), []int{6} -} - -func (x *GetNotificationRequest) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -// GetNotificationResponse returns a notification -type GetNotificationResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Notification *Notification `protobuf:"bytes,1,opt,name=notification,proto3" json:"notification,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetNotificationResponse) Reset() { - *x = GetNotificationResponse{} - mi := &file_api_grpc_notifier_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetNotificationResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetNotificationResponse) ProtoMessage() {} - -func (x *GetNotificationResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_grpc_notifier_proto_msgTypes[7] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetNotificationResponse.ProtoReflect.Descriptor instead. -func (*GetNotificationResponse) Descriptor() ([]byte, []int) { - return file_api_grpc_notifier_proto_rawDescGZIP(), []int{7} -} - -func (x *GetNotificationResponse) GetNotification() *Notification { - if x != nil { - return x.Notification - } - return nil -} - -// NotificationFilter is used for querying notifications -type NotificationFilter struct { - state protoimpl.MessageState `protogen:"open.v1"` - Ids []string `protobuf:"bytes,1,rep,name=ids,proto3" json:"ids,omitempty"` - Types []NotificationType `protobuf:"varint,2,rep,packed,name=types,proto3,enum=notifier.v1.NotificationType" json:"types,omitempty"` - Statuses []NotificationStatus `protobuf:"varint,3,rep,packed,name=statuses,proto3,enum=notifier.v1.NotificationStatus" json:"statuses,omitempty"` - Recipients []string `protobuf:"bytes,4,rep,name=recipients,proto3" json:"recipients,omitempty"` - CreatedAfter *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=created_after,json=createdAfter,proto3" json:"created_after,omitempty"` - CreatedBefore *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=created_before,json=createdBefore,proto3" json:"created_before,omitempty"` - Limit int32 `protobuf:"varint,7,opt,name=limit,proto3" json:"limit,omitempty"` - Offset int32 `protobuf:"varint,8,opt,name=offset,proto3" json:"offset,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *NotificationFilter) Reset() { - *x = NotificationFilter{} - mi := &file_api_grpc_notifier_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *NotificationFilter) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*NotificationFilter) ProtoMessage() {} - -func (x *NotificationFilter) ProtoReflect() protoreflect.Message { - mi := &file_api_grpc_notifier_proto_msgTypes[8] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use NotificationFilter.ProtoReflect.Descriptor instead. -func (*NotificationFilter) Descriptor() ([]byte, []int) { - return file_api_grpc_notifier_proto_rawDescGZIP(), []int{8} -} - -func (x *NotificationFilter) GetIds() []string { - if x != nil { - return x.Ids - } - return nil -} - -func (x *NotificationFilter) GetTypes() []NotificationType { - if x != nil { - return x.Types - } - return nil -} - -func (x *NotificationFilter) GetStatuses() []NotificationStatus { - if x != nil { - return x.Statuses - } - return nil -} - -func (x *NotificationFilter) GetRecipients() []string { - if x != nil { - return x.Recipients - } - return nil -} - -func (x *NotificationFilter) GetCreatedAfter() *timestamppb.Timestamp { - if x != nil { - return x.CreatedAfter - } - return nil -} - -func (x *NotificationFilter) GetCreatedBefore() *timestamppb.Timestamp { - if x != nil { - return x.CreatedBefore - } - return nil -} - -func (x *NotificationFilter) GetLimit() int32 { - if x != nil { - return x.Limit - } - return 0 -} - -func (x *NotificationFilter) GetOffset() int32 { - if x != nil { - return x.Offset - } - return 0 -} - -// ListNotificationsRequest retrieves notifications matching a filter -type ListNotificationsRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Filter *NotificationFilter `protobuf:"bytes,1,opt,name=filter,proto3" json:"filter,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ListNotificationsRequest) Reset() { - *x = ListNotificationsRequest{} - mi := &file_api_grpc_notifier_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ListNotificationsRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListNotificationsRequest) ProtoMessage() {} - -func (x *ListNotificationsRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_grpc_notifier_proto_msgTypes[9] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListNotificationsRequest.ProtoReflect.Descriptor instead. -func (*ListNotificationsRequest) Descriptor() ([]byte, []int) { - return file_api_grpc_notifier_proto_rawDescGZIP(), []int{9} -} - -func (x *ListNotificationsRequest) GetFilter() *NotificationFilter { - if x != nil { - return x.Filter - } - return nil -} - -// ListNotificationsResponse returns a list of notifications -type ListNotificationsResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Notifications []*Notification `protobuf:"bytes,1,rep,name=notifications,proto3" json:"notifications,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ListNotificationsResponse) Reset() { - *x = ListNotificationsResponse{} - mi := &file_api_grpc_notifier_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ListNotificationsResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListNotificationsResponse) ProtoMessage() {} - -func (x *ListNotificationsResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_grpc_notifier_proto_msgTypes[10] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListNotificationsResponse.ProtoReflect.Descriptor instead. -func (*ListNotificationsResponse) Descriptor() ([]byte, []int) { - return file_api_grpc_notifier_proto_rawDescGZIP(), []int{10} -} - -func (x *ListNotificationsResponse) GetNotifications() []*Notification { - if x != nil { - return x.Notifications - } - return nil -} - -func (x *ListNotificationsResponse) GetTotal() int64 { - if x != nil { - return x.Total - } - return 0 -} - -// CancelNotificationRequest cancels a pending notification -type CancelNotificationRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *CancelNotificationRequest) Reset() { - *x = CancelNotificationRequest{} - mi := &file_api_grpc_notifier_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *CancelNotificationRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CancelNotificationRequest) ProtoMessage() {} - -func (x *CancelNotificationRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_grpc_notifier_proto_msgTypes[11] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CancelNotificationRequest.ProtoReflect.Descriptor instead. -func (*CancelNotificationRequest) Descriptor() ([]byte, []int) { - return file_api_grpc_notifier_proto_rawDescGZIP(), []int{11} -} - -func (x *CancelNotificationRequest) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -// CancelNotificationResponse returns the result of canceling a notification -type CancelNotificationResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` - Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *CancelNotificationResponse) Reset() { - *x = CancelNotificationResponse{} - mi := &file_api_grpc_notifier_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *CancelNotificationResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CancelNotificationResponse) ProtoMessage() {} - -func (x *CancelNotificationResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_grpc_notifier_proto_msgTypes[12] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CancelNotificationResponse.ProtoReflect.Descriptor instead. -func (*CancelNotificationResponse) Descriptor() ([]byte, []int) { - return file_api_grpc_notifier_proto_rawDescGZIP(), []int{12} -} - -func (x *CancelNotificationResponse) GetSuccess() bool { - if x != nil { - return x.Success - } - return false -} - -func (x *CancelNotificationResponse) GetMessage() string { - if x != nil { - return x.Message - } - return "" -} - -// RetryNotificationRequest retries a failed notification -type RetryNotificationRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *RetryNotificationRequest) Reset() { - *x = RetryNotificationRequest{} - mi := &file_api_grpc_notifier_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *RetryNotificationRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RetryNotificationRequest) ProtoMessage() {} - -func (x *RetryNotificationRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_grpc_notifier_proto_msgTypes[13] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RetryNotificationRequest.ProtoReflect.Descriptor instead. -func (*RetryNotificationRequest) Descriptor() ([]byte, []int) { - return file_api_grpc_notifier_proto_rawDescGZIP(), []int{13} -} - -func (x *RetryNotificationRequest) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -// RetryNotificationResponse returns the result of retrying a notification -type RetryNotificationResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Result *NotificationResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *RetryNotificationResponse) Reset() { - *x = RetryNotificationResponse{} - mi := &file_api_grpc_notifier_proto_msgTypes[14] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *RetryNotificationResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RetryNotificationResponse) ProtoMessage() {} - -func (x *RetryNotificationResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_grpc_notifier_proto_msgTypes[14] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RetryNotificationResponse.ProtoReflect.Descriptor instead. -func (*RetryNotificationResponse) Descriptor() ([]byte, []int) { - return file_api_grpc_notifier_proto_rawDescGZIP(), []int{14} -} - -func (x *RetryNotificationResponse) GetResult() *NotificationResult { - if x != nil { - return x.Result - } - return nil -} - -// GetStatsRequest requests notification statistics -type GetStatsRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetStatsRequest) Reset() { - *x = GetStatsRequest{} - mi := &file_api_grpc_notifier_proto_msgTypes[15] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetStatsRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetStatsRequest) ProtoMessage() {} - -func (x *GetStatsRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_grpc_notifier_proto_msgTypes[15] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetStatsRequest.ProtoReflect.Descriptor instead. -func (*GetStatsRequest) Descriptor() ([]byte, []int) { - return file_api_grpc_notifier_proto_rawDescGZIP(), []int{15} -} - -// GetStatsResponse returns notification statistics -type GetStatsResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - TotalSent int64 `protobuf:"varint,1,opt,name=total_sent,json=totalSent,proto3" json:"total_sent,omitempty"` - TotalFailed int64 `protobuf:"varint,2,opt,name=total_failed,json=totalFailed,proto3" json:"total_failed,omitempty"` - TotalPending int64 `protobuf:"varint,3,opt,name=total_pending,json=totalPending,proto3" json:"total_pending,omitempty"` - TotalQueued int64 `protobuf:"varint,4,opt,name=total_queued,json=totalQueued,proto3" json:"total_queued,omitempty"` - ByType map[string]int64 `protobuf:"bytes,5,rep,name=by_type,json=byType,proto3" json:"by_type,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"varint,2,opt,name=value"` - ByStatus map[string]int64 `protobuf:"bytes,6,rep,name=by_status,json=byStatus,proto3" json:"by_status,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"varint,2,opt,name=value"` - AverageLatencyMs float64 `protobuf:"fixed64,7,opt,name=average_latency_ms,json=averageLatencyMs,proto3" json:"average_latency_ms,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetStatsResponse) Reset() { - *x = GetStatsResponse{} - mi := &file_api_grpc_notifier_proto_msgTypes[16] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetStatsResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetStatsResponse) ProtoMessage() {} - -func (x *GetStatsResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_grpc_notifier_proto_msgTypes[16] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetStatsResponse.ProtoReflect.Descriptor instead. -func (*GetStatsResponse) Descriptor() ([]byte, []int) { - return file_api_grpc_notifier_proto_rawDescGZIP(), []int{16} -} - -func (x *GetStatsResponse) GetTotalSent() int64 { - if x != nil { - return x.TotalSent - } - return 0 -} - -func (x *GetStatsResponse) GetTotalFailed() int64 { - if x != nil { - return x.TotalFailed - } - return 0 -} - -func (x *GetStatsResponse) GetTotalPending() int64 { - if x != nil { - return x.TotalPending - } - return 0 -} - -func (x *GetStatsResponse) GetTotalQueued() int64 { - if x != nil { - return x.TotalQueued - } - return 0 -} - -func (x *GetStatsResponse) GetByType() map[string]int64 { - if x != nil { - return x.ByType - } - return nil -} - -func (x *GetStatsResponse) GetByStatus() map[string]int64 { - if x != nil { - return x.ByStatus - } - return nil -} - -func (x *GetStatsResponse) GetAverageLatencyMs() float64 { - if x != nil { - return x.AverageLatencyMs - } - return 0 -} - -// HealthCheckRequest requests health status -type HealthCheckRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *HealthCheckRequest) Reset() { - *x = HealthCheckRequest{} - mi := &file_api_grpc_notifier_proto_msgTypes[17] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *HealthCheckRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HealthCheckRequest) ProtoMessage() {} - -func (x *HealthCheckRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_grpc_notifier_proto_msgTypes[17] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HealthCheckRequest.ProtoReflect.Descriptor instead. -func (*HealthCheckRequest) Descriptor() ([]byte, []int) { - return file_api_grpc_notifier_proto_rawDescGZIP(), []int{17} -} - -// HealthCheckResponse returns health status -type HealthCheckResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Healthy bool `protobuf:"varint,1,opt,name=healthy,proto3" json:"healthy,omitempty"` - Status string `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"` - Components map[string]string `protobuf:"bytes,3,rep,name=components,proto3" json:"components,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *HealthCheckResponse) Reset() { - *x = HealthCheckResponse{} - mi := &file_api_grpc_notifier_proto_msgTypes[18] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *HealthCheckResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HealthCheckResponse) ProtoMessage() {} - -func (x *HealthCheckResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_grpc_notifier_proto_msgTypes[18] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HealthCheckResponse.ProtoReflect.Descriptor instead. -func (*HealthCheckResponse) Descriptor() ([]byte, []int) { - return file_api_grpc_notifier_proto_rawDescGZIP(), []int{18} -} - -func (x *HealthCheckResponse) GetHealthy() bool { - if x != nil { - return x.Healthy - } - return false -} - -func (x *HealthCheckResponse) GetStatus() string { - if x != nil { - return x.Status - } - return "" -} - -func (x *HealthCheckResponse) GetComponents() map[string]string { - if x != nil { - return x.Components - } - return nil -} - -var File_api_grpc_notifier_proto protoreflect.FileDescriptor - -const file_api_grpc_notifier_proto_rawDesc = "" + - "\n" + - "\x17api/grpc/notifier.proto\x12\vnotifier.v1\x1a\x1fgoogle/protobuf/timestamp.proto\"\xb9\x05\n" + - "\fNotification\x12\x0e\n" + - "\x02id\x18\x01 \x01(\tR\x02id\x121\n" + - "\x04type\x18\x02 \x01(\x0e2\x1d.notifier.v1.NotificationTypeR\x04type\x12\x18\n" + - "\aaccount\x18\x03 \x01(\tR\aaccount\x121\n" + - "\bpriority\x18\x04 \x01(\x0e2\x15.notifier.v1.PriorityR\bpriority\x127\n" + - "\x06status\x18\x05 \x01(\x0e2\x1f.notifier.v1.NotificationStatusR\x06status\x12\x18\n" + - "\asubject\x18\x06 \x01(\tR\asubject\x12\x12\n" + - "\x04body\x18\a \x01(\tR\x04body\x12\x1e\n" + - "\n" + - "recipients\x18\b \x03(\tR\n" + - "recipients\x12C\n" + - "\bmetadata\x18\t \x03(\v2'.notifier.v1.Notification.MetadataEntryR\bmetadata\x129\n" + - "\n" + - "created_at\x18\n" + - " \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAt\x12?\n" + - "\rscheduled_for\x18\v \x01(\v2\x1a.google.protobuf.TimestampR\fscheduledFor\x123\n" + - "\asent_at\x18\f \x01(\v2\x1a.google.protobuf.TimestampR\x06sentAt\x12\x1f\n" + - "\vretry_count\x18\r \x01(\x05R\n" + - "retryCount\x12\x1f\n" + - "\vmax_retries\x18\x0e \x01(\x05R\n" + - "maxRetries\x12\x1d\n" + - "\n" + - "last_error\x18\x0f \x01(\tR\tlastError\x1a;\n" + - "\rMetadataEntry\x12\x10\n" + - "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + - "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"\xe5\x02\n" + - "\x12NotificationResult\x12'\n" + - "\x0fnotification_id\x18\x01 \x01(\tR\x0enotificationId\x12\x18\n" + - "\asuccess\x18\x02 \x01(\bR\asuccess\x12\x18\n" + - "\amessage\x18\x03 \x01(\tR\amessage\x12\x14\n" + - "\x05error\x18\x04 \x01(\tR\x05error\x123\n" + - "\asent_at\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampR\x06sentAt\x12b\n" + - "\x11provider_response\x18\x06 \x03(\v25.notifier.v1.NotificationResult.ProviderResponseEntryR\x10providerResponse\x1aC\n" + - "\x15ProviderResponseEntry\x12\x10\n" + - "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + - "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"\xd6\x03\n" + - "\x17SendNotificationRequest\x121\n" + - "\x04type\x18\x01 \x01(\x0e2\x1d.notifier.v1.NotificationTypeR\x04type\x12\x18\n" + - "\aaccount\x18\x02 \x01(\tR\aaccount\x121\n" + - "\bpriority\x18\x03 \x01(\x0e2\x15.notifier.v1.PriorityR\bpriority\x12\x18\n" + - "\asubject\x18\x04 \x01(\tR\asubject\x12\x12\n" + - "\x04body\x18\x05 \x01(\tR\x04body\x12\x1e\n" + - "\n" + - "recipients\x18\x06 \x03(\tR\n" + - "recipients\x12N\n" + - "\bmetadata\x18\a \x03(\v22.notifier.v1.SendNotificationRequest.MetadataEntryR\bmetadata\x12?\n" + - "\rscheduled_for\x18\b \x01(\v2\x1a.google.protobuf.TimestampR\fscheduledFor\x12\x1f\n" + - "\vmax_retries\x18\t \x01(\x05R\n" + - "maxRetries\x1a;\n" + - "\rMetadataEntry\x12\x10\n" + - "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + - "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"S\n" + - "\x18SendNotificationResponse\x127\n" + - "\x06result\x18\x01 \x01(\v2\x1f.notifier.v1.NotificationResultR\x06result\"k\n" + - "\x1dSendBatchNotificationsRequest\x12J\n" + - "\rnotifications\x18\x01 \x03(\v2$.notifier.v1.SendNotificationRequestR\rnotifications\"[\n" + - "\x1eSendBatchNotificationsResponse\x129\n" + - "\aresults\x18\x01 \x03(\v2\x1f.notifier.v1.NotificationResultR\aresults\"(\n" + - "\x16GetNotificationRequest\x12\x0e\n" + - "\x02id\x18\x01 \x01(\tR\x02id\"X\n" + - "\x17GetNotificationResponse\x12=\n" + - "\fnotification\x18\x01 \x01(\v2\x19.notifier.v1.NotificationR\fnotification\"\xea\x02\n" + - "\x12NotificationFilter\x12\x10\n" + - "\x03ids\x18\x01 \x03(\tR\x03ids\x123\n" + - "\x05types\x18\x02 \x03(\x0e2\x1d.notifier.v1.NotificationTypeR\x05types\x12;\n" + - "\bstatuses\x18\x03 \x03(\x0e2\x1f.notifier.v1.NotificationStatusR\bstatuses\x12\x1e\n" + - "\n" + - "recipients\x18\x04 \x03(\tR\n" + - "recipients\x12?\n" + - "\rcreated_after\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampR\fcreatedAfter\x12A\n" + - "\x0ecreated_before\x18\x06 \x01(\v2\x1a.google.protobuf.TimestampR\rcreatedBefore\x12\x14\n" + - "\x05limit\x18\a \x01(\x05R\x05limit\x12\x16\n" + - "\x06offset\x18\b \x01(\x05R\x06offset\"S\n" + - "\x18ListNotificationsRequest\x127\n" + - "\x06filter\x18\x01 \x01(\v2\x1f.notifier.v1.NotificationFilterR\x06filter\"r\n" + - "\x19ListNotificationsResponse\x12?\n" + - "\rnotifications\x18\x01 \x03(\v2\x19.notifier.v1.NotificationR\rnotifications\x12\x14\n" + - "\x05total\x18\x02 \x01(\x03R\x05total\"+\n" + - "\x19CancelNotificationRequest\x12\x0e\n" + - "\x02id\x18\x01 \x01(\tR\x02id\"P\n" + - "\x1aCancelNotificationResponse\x12\x18\n" + - "\asuccess\x18\x01 \x01(\bR\asuccess\x12\x18\n" + - "\amessage\x18\x02 \x01(\tR\amessage\"*\n" + - "\x18RetryNotificationRequest\x12\x0e\n" + - "\x02id\x18\x01 \x01(\tR\x02id\"T\n" + - "\x19RetryNotificationResponse\x127\n" + - "\x06result\x18\x01 \x01(\v2\x1f.notifier.v1.NotificationResultR\x06result\"\x11\n" + - "\x0fGetStatsRequest\"\xd0\x03\n" + - "\x10GetStatsResponse\x12\x1d\n" + - "\n" + - "total_sent\x18\x01 \x01(\x03R\ttotalSent\x12!\n" + - "\ftotal_failed\x18\x02 \x01(\x03R\vtotalFailed\x12#\n" + - "\rtotal_pending\x18\x03 \x01(\x03R\ftotalPending\x12!\n" + - "\ftotal_queued\x18\x04 \x01(\x03R\vtotalQueued\x12B\n" + - "\aby_type\x18\x05 \x03(\v2).notifier.v1.GetStatsResponse.ByTypeEntryR\x06byType\x12H\n" + - "\tby_status\x18\x06 \x03(\v2+.notifier.v1.GetStatsResponse.ByStatusEntryR\bbyStatus\x12,\n" + - "\x12average_latency_ms\x18\a \x01(\x01R\x10averageLatencyMs\x1a9\n" + - "\vByTypeEntry\x12\x10\n" + - "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + - "\x05value\x18\x02 \x01(\x03R\x05value:\x028\x01\x1a;\n" + - "\rByStatusEntry\x12\x10\n" + - "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + - "\x05value\x18\x02 \x01(\x03R\x05value:\x028\x01\"\x14\n" + - "\x12HealthCheckRequest\"\xd8\x01\n" + - "\x13HealthCheckResponse\x12\x18\n" + - "\ahealthy\x18\x01 \x01(\bR\ahealthy\x12\x16\n" + - "\x06status\x18\x02 \x01(\tR\x06status\x12P\n" + - "\n" + - "components\x18\x03 \x03(\v20.notifier.v1.HealthCheckResponse.ComponentsEntryR\n" + - "components\x1a=\n" + - "\x0fComponentsEntry\x12\x10\n" + - "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + - "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01*\xa9\x01\n" + - "\x10NotificationType\x12!\n" + - "\x1dNOTIFICATION_TYPE_UNSPECIFIED\x10\x00\x12\x1b\n" + - "\x17NOTIFICATION_TYPE_EMAIL\x10\x01\x12\x1b\n" + - "\x17NOTIFICATION_TYPE_SLACK\x10\x02\x12\x1a\n" + - "\x16NOTIFICATION_TYPE_NTFY\x10\x03\x12\x1c\n" + - "\x18NOTIFICATION_TYPE_STDOUT\x10\x04*u\n" + - "\bPriority\x12\x18\n" + - "\x14PRIORITY_UNSPECIFIED\x10\x00\x12\x10\n" + - "\fPRIORITY_LOW\x10\x01\x12\x13\n" + - "\x0fPRIORITY_NORMAL\x10\x02\x12\x11\n" + - "\rPRIORITY_HIGH\x10\x03\x12\x15\n" + - "\x11PRIORITY_CRITICAL\x10\x04*\xfe\x01\n" + - "\x12NotificationStatus\x12#\n" + - "\x1fNOTIFICATION_STATUS_UNSPECIFIED\x10\x00\x12\x1f\n" + - "\x1bNOTIFICATION_STATUS_PENDING\x10\x01\x12\x1e\n" + - "\x1aNOTIFICATION_STATUS_QUEUED\x10\x02\x12\"\n" + - "\x1eNOTIFICATION_STATUS_PROCESSING\x10\x03\x12\x1c\n" + - "\x18NOTIFICATION_STATUS_SENT\x10\x04\x12\x1e\n" + - "\x1aNOTIFICATION_STATUS_FAILED\x10\x05\x12 \n" + - "\x1cNOTIFICATION_STATUS_RETRYING\x10\x062\x8d\x06\n" + - "\x0fNotifierService\x12_\n" + - "\x10SendNotification\x12$.notifier.v1.SendNotificationRequest\x1a%.notifier.v1.SendNotificationResponse\x12q\n" + - "\x16SendBatchNotifications\x12*.notifier.v1.SendBatchNotificationsRequest\x1a+.notifier.v1.SendBatchNotificationsResponse\x12\\\n" + - "\x0fGetNotification\x12#.notifier.v1.GetNotificationRequest\x1a$.notifier.v1.GetNotificationResponse\x12b\n" + - "\x11ListNotifications\x12%.notifier.v1.ListNotificationsRequest\x1a&.notifier.v1.ListNotificationsResponse\x12e\n" + - "\x12CancelNotification\x12&.notifier.v1.CancelNotificationRequest\x1a'.notifier.v1.CancelNotificationResponse\x12b\n" + - "\x11RetryNotification\x12%.notifier.v1.RetryNotificationRequest\x1a&.notifier.v1.RetryNotificationResponse\x12G\n" + - "\bGetStats\x12\x1c.notifier.v1.GetStatsRequest\x1a\x1d.notifier.v1.GetStatsResponse\x12P\n" + - "\vHealthCheck\x12\x1f.notifier.v1.HealthCheckRequest\x1a .notifier.v1.HealthCheckResponseB)Z'github.com/igodwin/notifier/api/grpc/pbb\x06proto3" - -var ( - file_api_grpc_notifier_proto_rawDescOnce sync.Once - file_api_grpc_notifier_proto_rawDescData []byte -) - -func file_api_grpc_notifier_proto_rawDescGZIP() []byte { - file_api_grpc_notifier_proto_rawDescOnce.Do(func() { - file_api_grpc_notifier_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_api_grpc_notifier_proto_rawDesc), len(file_api_grpc_notifier_proto_rawDesc))) - }) - return file_api_grpc_notifier_proto_rawDescData -} - -var file_api_grpc_notifier_proto_enumTypes = make([]protoimpl.EnumInfo, 3) -var file_api_grpc_notifier_proto_msgTypes = make([]protoimpl.MessageInfo, 25) -var file_api_grpc_notifier_proto_goTypes = []any{ - (NotificationType)(0), // 0: notifier.v1.NotificationType - (Priority)(0), // 1: notifier.v1.Priority - (NotificationStatus)(0), // 2: notifier.v1.NotificationStatus - (*Notification)(nil), // 3: notifier.v1.Notification - (*NotificationResult)(nil), // 4: notifier.v1.NotificationResult - (*SendNotificationRequest)(nil), // 5: notifier.v1.SendNotificationRequest - (*SendNotificationResponse)(nil), // 6: notifier.v1.SendNotificationResponse - (*SendBatchNotificationsRequest)(nil), // 7: notifier.v1.SendBatchNotificationsRequest - (*SendBatchNotificationsResponse)(nil), // 8: notifier.v1.SendBatchNotificationsResponse - (*GetNotificationRequest)(nil), // 9: notifier.v1.GetNotificationRequest - (*GetNotificationResponse)(nil), // 10: notifier.v1.GetNotificationResponse - (*NotificationFilter)(nil), // 11: notifier.v1.NotificationFilter - (*ListNotificationsRequest)(nil), // 12: notifier.v1.ListNotificationsRequest - (*ListNotificationsResponse)(nil), // 13: notifier.v1.ListNotificationsResponse - (*CancelNotificationRequest)(nil), // 14: notifier.v1.CancelNotificationRequest - (*CancelNotificationResponse)(nil), // 15: notifier.v1.CancelNotificationResponse - (*RetryNotificationRequest)(nil), // 16: notifier.v1.RetryNotificationRequest - (*RetryNotificationResponse)(nil), // 17: notifier.v1.RetryNotificationResponse - (*GetStatsRequest)(nil), // 18: notifier.v1.GetStatsRequest - (*GetStatsResponse)(nil), // 19: notifier.v1.GetStatsResponse - (*HealthCheckRequest)(nil), // 20: notifier.v1.HealthCheckRequest - (*HealthCheckResponse)(nil), // 21: notifier.v1.HealthCheckResponse - nil, // 22: notifier.v1.Notification.MetadataEntry - nil, // 23: notifier.v1.NotificationResult.ProviderResponseEntry - nil, // 24: notifier.v1.SendNotificationRequest.MetadataEntry - nil, // 25: notifier.v1.GetStatsResponse.ByTypeEntry - nil, // 26: notifier.v1.GetStatsResponse.ByStatusEntry - nil, // 27: notifier.v1.HealthCheckResponse.ComponentsEntry - (*timestamppb.Timestamp)(nil), // 28: google.protobuf.Timestamp -} -var file_api_grpc_notifier_proto_depIdxs = []int32{ - 0, // 0: notifier.v1.Notification.type:type_name -> notifier.v1.NotificationType - 1, // 1: notifier.v1.Notification.priority:type_name -> notifier.v1.Priority - 2, // 2: notifier.v1.Notification.status:type_name -> notifier.v1.NotificationStatus - 22, // 3: notifier.v1.Notification.metadata:type_name -> notifier.v1.Notification.MetadataEntry - 28, // 4: notifier.v1.Notification.created_at:type_name -> google.protobuf.Timestamp - 28, // 5: notifier.v1.Notification.scheduled_for:type_name -> google.protobuf.Timestamp - 28, // 6: notifier.v1.Notification.sent_at:type_name -> google.protobuf.Timestamp - 28, // 7: notifier.v1.NotificationResult.sent_at:type_name -> google.protobuf.Timestamp - 23, // 8: notifier.v1.NotificationResult.provider_response:type_name -> notifier.v1.NotificationResult.ProviderResponseEntry - 0, // 9: notifier.v1.SendNotificationRequest.type:type_name -> notifier.v1.NotificationType - 1, // 10: notifier.v1.SendNotificationRequest.priority:type_name -> notifier.v1.Priority - 24, // 11: notifier.v1.SendNotificationRequest.metadata:type_name -> notifier.v1.SendNotificationRequest.MetadataEntry - 28, // 12: notifier.v1.SendNotificationRequest.scheduled_for:type_name -> google.protobuf.Timestamp - 4, // 13: notifier.v1.SendNotificationResponse.result:type_name -> notifier.v1.NotificationResult - 5, // 14: notifier.v1.SendBatchNotificationsRequest.notifications:type_name -> notifier.v1.SendNotificationRequest - 4, // 15: notifier.v1.SendBatchNotificationsResponse.results:type_name -> notifier.v1.NotificationResult - 3, // 16: notifier.v1.GetNotificationResponse.notification:type_name -> notifier.v1.Notification - 0, // 17: notifier.v1.NotificationFilter.types:type_name -> notifier.v1.NotificationType - 2, // 18: notifier.v1.NotificationFilter.statuses:type_name -> notifier.v1.NotificationStatus - 28, // 19: notifier.v1.NotificationFilter.created_after:type_name -> google.protobuf.Timestamp - 28, // 20: notifier.v1.NotificationFilter.created_before:type_name -> google.protobuf.Timestamp - 11, // 21: notifier.v1.ListNotificationsRequest.filter:type_name -> notifier.v1.NotificationFilter - 3, // 22: notifier.v1.ListNotificationsResponse.notifications:type_name -> notifier.v1.Notification - 4, // 23: notifier.v1.RetryNotificationResponse.result:type_name -> notifier.v1.NotificationResult - 25, // 24: notifier.v1.GetStatsResponse.by_type:type_name -> notifier.v1.GetStatsResponse.ByTypeEntry - 26, // 25: notifier.v1.GetStatsResponse.by_status:type_name -> notifier.v1.GetStatsResponse.ByStatusEntry - 27, // 26: notifier.v1.HealthCheckResponse.components:type_name -> notifier.v1.HealthCheckResponse.ComponentsEntry - 5, // 27: notifier.v1.NotifierService.SendNotification:input_type -> notifier.v1.SendNotificationRequest - 7, // 28: notifier.v1.NotifierService.SendBatchNotifications:input_type -> notifier.v1.SendBatchNotificationsRequest - 9, // 29: notifier.v1.NotifierService.GetNotification:input_type -> notifier.v1.GetNotificationRequest - 12, // 30: notifier.v1.NotifierService.ListNotifications:input_type -> notifier.v1.ListNotificationsRequest - 14, // 31: notifier.v1.NotifierService.CancelNotification:input_type -> notifier.v1.CancelNotificationRequest - 16, // 32: notifier.v1.NotifierService.RetryNotification:input_type -> notifier.v1.RetryNotificationRequest - 18, // 33: notifier.v1.NotifierService.GetStats:input_type -> notifier.v1.GetStatsRequest - 20, // 34: notifier.v1.NotifierService.HealthCheck:input_type -> notifier.v1.HealthCheckRequest - 6, // 35: notifier.v1.NotifierService.SendNotification:output_type -> notifier.v1.SendNotificationResponse - 8, // 36: notifier.v1.NotifierService.SendBatchNotifications:output_type -> notifier.v1.SendBatchNotificationsResponse - 10, // 37: notifier.v1.NotifierService.GetNotification:output_type -> notifier.v1.GetNotificationResponse - 13, // 38: notifier.v1.NotifierService.ListNotifications:output_type -> notifier.v1.ListNotificationsResponse - 15, // 39: notifier.v1.NotifierService.CancelNotification:output_type -> notifier.v1.CancelNotificationResponse - 17, // 40: notifier.v1.NotifierService.RetryNotification:output_type -> notifier.v1.RetryNotificationResponse - 19, // 41: notifier.v1.NotifierService.GetStats:output_type -> notifier.v1.GetStatsResponse - 21, // 42: notifier.v1.NotifierService.HealthCheck:output_type -> notifier.v1.HealthCheckResponse - 35, // [35:43] is the sub-list for method output_type - 27, // [27:35] is the sub-list for method input_type - 27, // [27:27] is the sub-list for extension type_name - 27, // [27:27] is the sub-list for extension extendee - 0, // [0:27] is the sub-list for field type_name -} - -func init() { file_api_grpc_notifier_proto_init() } -func file_api_grpc_notifier_proto_init() { - if File_api_grpc_notifier_proto != nil { - return - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: unsafe.Slice(unsafe.StringData(file_api_grpc_notifier_proto_rawDesc), len(file_api_grpc_notifier_proto_rawDesc)), - NumEnums: 3, - NumMessages: 25, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_api_grpc_notifier_proto_goTypes, - DependencyIndexes: file_api_grpc_notifier_proto_depIdxs, - EnumInfos: file_api_grpc_notifier_proto_enumTypes, - MessageInfos: file_api_grpc_notifier_proto_msgTypes, - }.Build() - File_api_grpc_notifier_proto = out.File - file_api_grpc_notifier_proto_goTypes = nil - file_api_grpc_notifier_proto_depIdxs = nil -} diff --git a/api/grpc/pb/api/grpc/notifier_grpc.pb.go b/api/grpc/pb/api/grpc/notifier_grpc.pb.go deleted file mode 100644 index d386292..0000000 --- a/api/grpc/pb/api/grpc/notifier_grpc.pb.go +++ /dev/null @@ -1,407 +0,0 @@ -// Code generated by protoc-gen-go-grpc. DO NOT EDIT. -// versions: -// - protoc-gen-go-grpc v1.5.1 -// - protoc v6.33.0 -// source: api/grpc/notifier.proto - -package pb - -import ( - context "context" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.64.0 or later. -const _ = grpc.SupportPackageIsVersion9 - -const ( - NotifierService_SendNotification_FullMethodName = "/notifier.v1.NotifierService/SendNotification" - NotifierService_SendBatchNotifications_FullMethodName = "/notifier.v1.NotifierService/SendBatchNotifications" - NotifierService_GetNotification_FullMethodName = "/notifier.v1.NotifierService/GetNotification" - NotifierService_ListNotifications_FullMethodName = "/notifier.v1.NotifierService/ListNotifications" - NotifierService_CancelNotification_FullMethodName = "/notifier.v1.NotifierService/CancelNotification" - NotifierService_RetryNotification_FullMethodName = "/notifier.v1.NotifierService/RetryNotification" - NotifierService_GetStats_FullMethodName = "/notifier.v1.NotifierService/GetStats" - NotifierService_HealthCheck_FullMethodName = "/notifier.v1.NotifierService/HealthCheck" -) - -// NotifierServiceClient is the client API for NotifierService service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -// -// NotifierService handles notification operations -type NotifierServiceClient interface { - // SendNotification sends a single notification - SendNotification(ctx context.Context, in *SendNotificationRequest, opts ...grpc.CallOption) (*SendNotificationResponse, error) - // SendBatchNotifications sends multiple notifications - SendBatchNotifications(ctx context.Context, in *SendBatchNotificationsRequest, opts ...grpc.CallOption) (*SendBatchNotificationsResponse, error) - // GetNotification retrieves a notification by ID - GetNotification(ctx context.Context, in *GetNotificationRequest, opts ...grpc.CallOption) (*GetNotificationResponse, error) - // ListNotifications retrieves notifications matching a filter - ListNotifications(ctx context.Context, in *ListNotificationsRequest, opts ...grpc.CallOption) (*ListNotificationsResponse, error) - // CancelNotification cancels a pending notification - CancelNotification(ctx context.Context, in *CancelNotificationRequest, opts ...grpc.CallOption) (*CancelNotificationResponse, error) - // RetryNotification retries a failed notification - RetryNotification(ctx context.Context, in *RetryNotificationRequest, opts ...grpc.CallOption) (*RetryNotificationResponse, error) - // GetStats returns notification statistics - GetStats(ctx context.Context, in *GetStatsRequest, opts ...grpc.CallOption) (*GetStatsResponse, error) - // HealthCheck verifies the service is operational - HealthCheck(ctx context.Context, in *HealthCheckRequest, opts ...grpc.CallOption) (*HealthCheckResponse, error) -} - -type notifierServiceClient struct { - cc grpc.ClientConnInterface -} - -func NewNotifierServiceClient(cc grpc.ClientConnInterface) NotifierServiceClient { - return ¬ifierServiceClient{cc} -} - -func (c *notifierServiceClient) SendNotification(ctx context.Context, in *SendNotificationRequest, opts ...grpc.CallOption) (*SendNotificationResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(SendNotificationResponse) - err := c.cc.Invoke(ctx, NotifierService_SendNotification_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *notifierServiceClient) SendBatchNotifications(ctx context.Context, in *SendBatchNotificationsRequest, opts ...grpc.CallOption) (*SendBatchNotificationsResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(SendBatchNotificationsResponse) - err := c.cc.Invoke(ctx, NotifierService_SendBatchNotifications_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *notifierServiceClient) GetNotification(ctx context.Context, in *GetNotificationRequest, opts ...grpc.CallOption) (*GetNotificationResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(GetNotificationResponse) - err := c.cc.Invoke(ctx, NotifierService_GetNotification_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *notifierServiceClient) ListNotifications(ctx context.Context, in *ListNotificationsRequest, opts ...grpc.CallOption) (*ListNotificationsResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(ListNotificationsResponse) - err := c.cc.Invoke(ctx, NotifierService_ListNotifications_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *notifierServiceClient) CancelNotification(ctx context.Context, in *CancelNotificationRequest, opts ...grpc.CallOption) (*CancelNotificationResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(CancelNotificationResponse) - err := c.cc.Invoke(ctx, NotifierService_CancelNotification_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *notifierServiceClient) RetryNotification(ctx context.Context, in *RetryNotificationRequest, opts ...grpc.CallOption) (*RetryNotificationResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(RetryNotificationResponse) - err := c.cc.Invoke(ctx, NotifierService_RetryNotification_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *notifierServiceClient) GetStats(ctx context.Context, in *GetStatsRequest, opts ...grpc.CallOption) (*GetStatsResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(GetStatsResponse) - err := c.cc.Invoke(ctx, NotifierService_GetStats_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *notifierServiceClient) HealthCheck(ctx context.Context, in *HealthCheckRequest, opts ...grpc.CallOption) (*HealthCheckResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(HealthCheckResponse) - err := c.cc.Invoke(ctx, NotifierService_HealthCheck_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -// NotifierServiceServer is the server API for NotifierService service. -// All implementations must embed UnimplementedNotifierServiceServer -// for forward compatibility. -// -// NotifierService handles notification operations -type NotifierServiceServer interface { - // SendNotification sends a single notification - SendNotification(context.Context, *SendNotificationRequest) (*SendNotificationResponse, error) - // SendBatchNotifications sends multiple notifications - SendBatchNotifications(context.Context, *SendBatchNotificationsRequest) (*SendBatchNotificationsResponse, error) - // GetNotification retrieves a notification by ID - GetNotification(context.Context, *GetNotificationRequest) (*GetNotificationResponse, error) - // ListNotifications retrieves notifications matching a filter - ListNotifications(context.Context, *ListNotificationsRequest) (*ListNotificationsResponse, error) - // CancelNotification cancels a pending notification - CancelNotification(context.Context, *CancelNotificationRequest) (*CancelNotificationResponse, error) - // RetryNotification retries a failed notification - RetryNotification(context.Context, *RetryNotificationRequest) (*RetryNotificationResponse, error) - // GetStats returns notification statistics - GetStats(context.Context, *GetStatsRequest) (*GetStatsResponse, error) - // HealthCheck verifies the service is operational - HealthCheck(context.Context, *HealthCheckRequest) (*HealthCheckResponse, error) - mustEmbedUnimplementedNotifierServiceServer() -} - -// UnimplementedNotifierServiceServer must be embedded to have -// forward compatible implementations. -// -// NOTE: this should be embedded by value instead of pointer to avoid a nil -// pointer dereference when methods are called. -type UnimplementedNotifierServiceServer struct{} - -func (UnimplementedNotifierServiceServer) SendNotification(context.Context, *SendNotificationRequest) (*SendNotificationResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method SendNotification not implemented") -} -func (UnimplementedNotifierServiceServer) SendBatchNotifications(context.Context, *SendBatchNotificationsRequest) (*SendBatchNotificationsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method SendBatchNotifications not implemented") -} -func (UnimplementedNotifierServiceServer) GetNotification(context.Context, *GetNotificationRequest) (*GetNotificationResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetNotification not implemented") -} -func (UnimplementedNotifierServiceServer) ListNotifications(context.Context, *ListNotificationsRequest) (*ListNotificationsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListNotifications not implemented") -} -func (UnimplementedNotifierServiceServer) CancelNotification(context.Context, *CancelNotificationRequest) (*CancelNotificationResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method CancelNotification not implemented") -} -func (UnimplementedNotifierServiceServer) RetryNotification(context.Context, *RetryNotificationRequest) (*RetryNotificationResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method RetryNotification not implemented") -} -func (UnimplementedNotifierServiceServer) GetStats(context.Context, *GetStatsRequest) (*GetStatsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetStats not implemented") -} -func (UnimplementedNotifierServiceServer) HealthCheck(context.Context, *HealthCheckRequest) (*HealthCheckResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method HealthCheck not implemented") -} -func (UnimplementedNotifierServiceServer) mustEmbedUnimplementedNotifierServiceServer() {} -func (UnimplementedNotifierServiceServer) testEmbeddedByValue() {} - -// UnsafeNotifierServiceServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to NotifierServiceServer will -// result in compilation errors. -type UnsafeNotifierServiceServer interface { - mustEmbedUnimplementedNotifierServiceServer() -} - -func RegisterNotifierServiceServer(s grpc.ServiceRegistrar, srv NotifierServiceServer) { - // If the following call pancis, it indicates UnimplementedNotifierServiceServer was - // embedded by pointer and is nil. This will cause panics if an - // unimplemented method is ever invoked, so we test this at initialization - // time to prevent it from happening at runtime later due to I/O. - if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { - t.testEmbeddedByValue() - } - s.RegisterService(&NotifierService_ServiceDesc, srv) -} - -func _NotifierService_SendNotification_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(SendNotificationRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(NotifierServiceServer).SendNotification(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: NotifierService_SendNotification_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NotifierServiceServer).SendNotification(ctx, req.(*SendNotificationRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _NotifierService_SendBatchNotifications_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(SendBatchNotificationsRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(NotifierServiceServer).SendBatchNotifications(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: NotifierService_SendBatchNotifications_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NotifierServiceServer).SendBatchNotifications(ctx, req.(*SendBatchNotificationsRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _NotifierService_GetNotification_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetNotificationRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(NotifierServiceServer).GetNotification(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: NotifierService_GetNotification_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NotifierServiceServer).GetNotification(ctx, req.(*GetNotificationRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _NotifierService_ListNotifications_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ListNotificationsRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(NotifierServiceServer).ListNotifications(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: NotifierService_ListNotifications_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NotifierServiceServer).ListNotifications(ctx, req.(*ListNotificationsRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _NotifierService_CancelNotification_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(CancelNotificationRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(NotifierServiceServer).CancelNotification(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: NotifierService_CancelNotification_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NotifierServiceServer).CancelNotification(ctx, req.(*CancelNotificationRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _NotifierService_RetryNotification_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RetryNotificationRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(NotifierServiceServer).RetryNotification(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: NotifierService_RetryNotification_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NotifierServiceServer).RetryNotification(ctx, req.(*RetryNotificationRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _NotifierService_GetStats_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetStatsRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(NotifierServiceServer).GetStats(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: NotifierService_GetStats_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NotifierServiceServer).GetStats(ctx, req.(*GetStatsRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _NotifierService_HealthCheck_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(HealthCheckRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(NotifierServiceServer).HealthCheck(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: NotifierService_HealthCheck_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NotifierServiceServer).HealthCheck(ctx, req.(*HealthCheckRequest)) - } - return interceptor(ctx, in, info, handler) -} - -// NotifierService_ServiceDesc is the grpc.ServiceDesc for NotifierService service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var NotifierService_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "notifier.v1.NotifierService", - HandlerType: (*NotifierServiceServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "SendNotification", - Handler: _NotifierService_SendNotification_Handler, - }, - { - MethodName: "SendBatchNotifications", - Handler: _NotifierService_SendBatchNotifications_Handler, - }, - { - MethodName: "GetNotification", - Handler: _NotifierService_GetNotification_Handler, - }, - { - MethodName: "ListNotifications", - Handler: _NotifierService_ListNotifications_Handler, - }, - { - MethodName: "CancelNotification", - Handler: _NotifierService_CancelNotification_Handler, - }, - { - MethodName: "RetryNotification", - Handler: _NotifierService_RetryNotification_Handler, - }, - { - MethodName: "GetStats", - Handler: _NotifierService_GetStats_Handler, - }, - { - MethodName: "HealthCheck", - Handler: _NotifierService_HealthCheck_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "api/grpc/notifier.proto", -} diff --git a/cmd/server/main.go b/cmd/server/main.go index 118d090..1fbed3d 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -2,6 +2,7 @@ package main import ( "context" + "encoding/json" "fmt" "net" "net/http" @@ -11,6 +12,8 @@ import ( "syscall" "time" + grpcapi "github.com/igodwin/notifier/api/grpc" + pb "github.com/igodwin/notifier/api/grpc/pb" "github.com/igodwin/notifier/api/rest" "github.com/igodwin/notifier/internal/config" "github.com/igodwin/notifier/internal/domain" @@ -22,7 +25,23 @@ import ( "google.golang.org/grpc/reflection" ) +var ( + // Build information - set via ldflags during build + // Example: go build -ldflags "-X main.Version=1.0.0 -X main.GitCommit=$(git rev-parse HEAD)" + Version = "dev" + GitCommit = "unknown" + BuildTime = "unknown" +) + func main() { + // Print service identifier and build info + fmt.Printf("====================================\n") + fmt.Printf("Notifier Service\n") + fmt.Printf("Version: %s\n", Version) + fmt.Printf("Git Commit: %s\n", GitCommit) + fmt.Printf("Build Time: %s\n", BuildTime) + fmt.Printf("====================================\n") + // Load configuration cfg, err := config.Load("") if err != nil { @@ -40,6 +59,14 @@ func main() { logger.Warnf("Failed to open log file, using stdout: %v", err) } + // Log which config file was loaded + logger.Infof("Loaded configuration from: %s", cfg.ConfigFile) + + // Log sanitized config (with sensitive data redacted) + if sanitized, err := json.MarshalIndent(cfg.Sanitize(), "", " "); err == nil { + logger.Infof("Configuration:\n%s", string(sanitized)) + } + logger.Infof("Starting Notifier Service in mode: %s", cfg.Server.Mode) // Create context @@ -200,12 +227,15 @@ func startGRPCServer(ctx context.Context, wg *sync.WaitGroup, cfg *config.Config grpcServer := grpc.NewServer() - // TODO: Register gRPC service implementation when protobuf is generated - // pb.RegisterNotifierServiceServer(grpcServer, grpcHandler) + // Create and register gRPC handler + grpcHandler := grpcapi.NewNotifierHandler(svc) + pb.RegisterNotifierServiceServer(grpcServer, grpcHandler) // Enable reflection for tools like grpcurl reflection.Register(grpcServer) + logger.Info("Registered gRPC NotifierService") + go func() { defer wg.Done() logger.Infof("gRPC server listening on %s", addr) diff --git a/notifier.config b/config.yaml similarity index 100% rename from notifier.config rename to config.yaml diff --git a/docker-compose.yaml b/docker-compose.yaml index 7c591e4..f0f6961 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -12,7 +12,7 @@ services: - "9090:9090" # Metrics (future) - "8081:8081" # Health check (future) volumes: - - ./notifier.config:/app/notifier.config:ro + - ./config.yaml:/app/config.yaml:ro - notifier-data:/var/lib/notifier environment: - NOTIFIER_SERVER_MODE=both diff --git a/internal/config/config.go b/internal/config/config.go index c0ff777..862136d 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -2,6 +2,8 @@ package config import ( "fmt" + "os" + "path/filepath" "strings" "github.com/igodwin/notifier/internal/domain" @@ -17,6 +19,7 @@ type Config struct { Logging LoggingConfig `mapstructure:"logging"` Metrics MetricsConfig `mapstructure:"metrics"` HealthCheck HealthCheckConfig `mapstructure:"health_check"` + ConfigFile string `mapstructure:"-"` // Path to config file used (not from config) } // ServerConfig contains server configuration @@ -59,25 +62,30 @@ type HealthCheckConfig struct { } // Load loads configuration from file and environment variables +// Returns the loaded config and the path to the config file that was used func Load(configPath string) (*Config, error) { v := viper.New() // Set default values setDefaults(v) - // Configure viper - v.SetConfigName("notifier") + // Configure viper to look for config.yaml + v.SetConfigName("config") v.SetConfigType("yaml") + // Add config search paths if configPath != "" { v.AddConfigPath(configPath) } - // Also look in common locations v.AddConfigPath(".") v.AddConfigPath("./config") v.AddConfigPath("/etc/notifier") - v.AddConfigPath("$HOME/.notifier") + + // Add $HOME/.notifier if HOME is set + if home := os.Getenv("HOME"); home != "" { + v.AddConfigPath(filepath.Join(home, ".notifier")) + } // Environment variable support v.SetEnvPrefix("NOTIFIER") @@ -85,11 +93,13 @@ func Load(configPath string) (*Config, error) { v.AutomaticEnv() // Read config file + var configErr error if err := v.ReadInConfig(); err != nil { // Config file is optional if environment variables are set if _, ok := err.(viper.ConfigFileNotFoundError); !ok { return nil, fmt.Errorf("failed to read config file: %w", err) } + configErr = err } var config Config @@ -97,6 +107,16 @@ func Load(configPath string) (*Config, error) { return nil, fmt.Errorf("failed to unmarshal config: %w", err) } + // Store which config file was used + config.ConfigFile = v.ConfigFileUsed() + if config.ConfigFile == "" { + if configErr != nil { + config.ConfigFile = "no config file found (using defaults and environment variables)" + } else { + config.ConfigFile = "using defaults and environment variables" + } + } + // Validate configuration if err := config.Validate(); err != nil { return nil, fmt.Errorf("invalid configuration: %w", err) @@ -143,9 +163,8 @@ func setDefaults(v *viper.Viper) { // Notifier defaults v.SetDefault("notifiers.stdout", true) - v.SetDefault("notifiers.smtp.port", 587) - v.SetDefault("notifiers.smtp.use_tls", true) - v.SetDefault("notifiers.ntfy.server_url", "https://ntfy.sh") + // Note: SMTP, Slack, and Ntfy now use named instances (maps) + // so we don't set defaults at the type level } // Validate validates the configuration @@ -210,6 +229,92 @@ func (c *Config) GetEnabledNotifiers() []domain.NotificationType { return enabled } +// Sanitize returns a sanitized copy of the config with sensitive data redacted +func (c *Config) Sanitize() map[string]interface{} { + sanitized := map[string]interface{}{ + "config_file": c.ConfigFile, + "server": map[string]interface{}{ + "grpc_port": c.Server.GRPCPort, + "rest_port": c.Server.RESTPort, + "host": c.Server.Host, + "mode": c.Server.Mode, + }, + "queue": map[string]interface{}{ + "type": c.Queue.Type, + "worker_count": c.Queue.WorkerCount, + "retry_attempts": c.Queue.RetryAttempts, + }, + "logging": map[string]interface{}{ + "level": c.Logging.Level, + "format": c.Logging.Format, + }, + "metrics": map[string]interface{}{ + "enabled": c.Metrics.Enabled, + "port": c.Metrics.Port, + }, + "health_check": map[string]interface{}{ + "enabled": c.HealthCheck.Enabled, + "port": c.HealthCheck.Port, + }, + } + + // Sanitize notifiers + notifiers := map[string]interface{}{ + "stdout": c.Notifiers.Stdout, + } + + // Sanitize SMTP configs + if len(c.Notifiers.SMTP) > 0 { + smtpAccounts := make(map[string]interface{}) + for name, cfg := range c.Notifiers.SMTP { + smtpAccounts[name] = map[string]interface{}{ + "host": cfg.Host, + "port": cfg.Port, + "username": cfg.Username, + "password": "***REDACTED***", + "from": cfg.From, + "use_tls": cfg.UseTLS, + "default": cfg.Default, + } + } + notifiers["smtp"] = smtpAccounts + } + + // Sanitize Slack configs + if len(c.Notifiers.Slack) > 0 { + slackAccounts := make(map[string]interface{}) + for name, cfg := range c.Notifiers.Slack { + slackAccounts[name] = map[string]interface{}{ + "webhook_url": "***REDACTED***", + "token": "***REDACTED***", + "username": cfg.Username, + "icon_emoji": cfg.IconEmoji, + "default": cfg.Default, + } + } + notifiers["slack"] = slackAccounts + } + + // Sanitize Ntfy configs + if len(c.Notifiers.Ntfy) > 0 { + ntfyAccounts := make(map[string]interface{}) + for name, cfg := range c.Notifiers.Ntfy { + ntfyAccounts[name] = map[string]interface{}{ + "server_url": cfg.ServerURL, + "token": "***REDACTED***", + "username": cfg.Username, + "password": "***REDACTED***", + "default_topic": cfg.DefaultTopic, + "default": cfg.Default, + } + } + notifiers["ntfy"] = ntfyAccounts + } + + sanitized["notifiers"] = notifiers + return sanitized +} + // GetDefaultAccount returns the default account name for a notifier type, or the first account if no default is set func (c *Config) GetDefaultAccount(notifierType domain.NotificationType) string { switch notifierType { diff --git a/k8s/configmap.yaml b/k8s/configmap.yaml index 8800b5d..3fe1d54 100644 --- a/k8s/configmap.yaml +++ b/k8s/configmap.yaml @@ -5,7 +5,7 @@ metadata: labels: app: notifier data: - notifier.config: | + config.yaml: | server: grpc_port: 50051 rest_port: 8080 diff --git a/k8s/deployment.yaml b/k8s/deployment.yaml index db9b763..3dc534e 100644 --- a/k8s/deployment.yaml +++ b/k8s/deployment.yaml @@ -45,8 +45,8 @@ spec: value: "local" volumeMounts: - name: config - mountPath: /app/notifier.config - subPath: notifier.config + mountPath: /app/config.yaml + subPath: config.yaml readOnly: true - name: queue-storage mountPath: /var/lib/notifier