notification

package
v0.0.14 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 4, 2026 License: Apache-2.0 Imports: 21 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// Template errors
	CodeTemplateNotFound      = "TEMPLATE_NOT_FOUND"
	CodeTemplateAlreadyExists = "TEMPLATE_ALREADY_EXISTS"
	CodeInvalidTemplate       = "INVALID_TEMPLATE"
	CodeTemplateInactive      = "TEMPLATE_INACTIVE"
	CodeTemplateRenderFailed  = "TEMPLATE_RENDER_FAILED"

	// Notification errors
	CodeNotificationNotFound   = "NOTIFICATION_NOT_FOUND"
	CodeNotificationFailed     = "NOTIFICATION_FAILED"
	CodeNotificationSendFailed = "NOTIFICATION_SEND_FAILED"

	// Provider errors
	CodeProviderNotConfigured    = "PROVIDER_NOT_CONFIGURED"
	CodeProviderNotFound         = "PROVIDER_NOT_FOUND"
	CodeProviderValidationFailed = "PROVIDER_VALIDATION_FAILED"

	// Version errors
	CodeVersionNotFound      = "VERSION_NOT_FOUND"
	CodeVersionRestoreFailed = "VERSION_RESTORE_FAILED"

	// Test errors
	CodeTestNotFound = "TEST_NOT_FOUND"
	CodeTestFailed   = "TEST_FAILED"

	// Validation errors
	CodeInvalidNotificationType = "INVALID_NOTIFICATION_TYPE"
	CodeInvalidRecipient        = "INVALID_RECIPIENT"
	CodeMissingTemplateVariable = "MISSING_TEMPLATE_VARIABLE"
)
View Source
const (
	// Authentication templates
	TemplateKeyWelcome       = "auth.welcome"
	TemplateKeyVerifyEmail   = "auth.verify_email"
	TemplateKeyPasswordReset = "auth.password_reset"
	TemplateKeyMFACode       = "auth.mfa_code"
	TemplateKeyMagicLink     = "auth.magic_link"
	TemplateKeyEmailOTP      = "auth.email_otp"
	TemplateKeyPhoneOTP      = "auth.phone_otp"
	TemplateKeySecurityAlert = "auth.security_alert"

	// Organization templates
	TemplateKeyOrgInvite        = "org.invite"
	TemplateKeyOrgMemberAdded   = "org.member_added"
	TemplateKeyOrgMemberRemoved = "org.member_removed"
	TemplateKeyOrgRoleChanged   = "org.role_changed"
	TemplateKeyOrgTransfer      = "org.transfer"
	TemplateKeyOrgDeleted       = "org.deleted"
	TemplateKeyOrgMemberLeft    = "org.member_left"

	// Account management templates
	TemplateKeyEmailChangeRequest = "account.email_change_request"
	TemplateKeyEmailChanged       = "account.email_changed"
	TemplateKeyPasswordChanged    = "account.password_changed"
	TemplateKeyUsernameChanged    = "account.username_changed"
	TemplateKeyAccountDeleted     = "account.deleted"
	TemplateKeyAccountSuspended   = "account.suspended"
	TemplateKeyAccountReactivated = "account.reactivated"
	TemplateKeyDataExportReady    = "account.data_export_ready"

	// Session/device templates
	TemplateKeyNewDeviceLogin     = "session.new_device"
	TemplateKeyNewLocationLogin   = "session.new_location"
	TemplateKeySuspiciousLogin    = "session.suspicious_login"
	TemplateKeyDeviceRemoved      = "session.device_removed"
	TemplateKeyAllSessionsRevoked = "session.all_revoked"

	// Reminder templates
	TemplateKeyVerificationReminder = "reminder.verification"
	TemplateKeyInactiveAccount      = "reminder.inactive"
	TemplateKeyTrialExpiring        = "reminder.trial_expiring"
	TemplateKeySubscriptionExpiring = "reminder.subscription_expiring"
	TemplateKeyPasswordExpiring     = "reminder.password_expiring"

	// Admin/moderation templates
	TemplateKeyAccountLocked        = "admin.account_locked"
	TemplateKeyAccountUnlocked      = "admin.account_unlocked"
	TemplateKeyTermsUpdate          = "admin.terms_update"
	TemplateKeyPrivacyUpdate        = "admin.privacy_update"
	TemplateKeyMaintenanceScheduled = "admin.maintenance"
	TemplateKeySecurityBreach       = "admin.security_breach"
)

Template key constants for predefined notification templates

Variables

View Source
var (
	ErrTemplateNotFound         = &errs.AuthsomeError{Code: CodeTemplateNotFound}
	ErrTemplateAlreadyExists    = &errs.AuthsomeError{Code: CodeTemplateAlreadyExists}
	ErrInvalidTemplate          = &errs.AuthsomeError{Code: CodeInvalidTemplate}
	ErrTemplateInactive         = &errs.AuthsomeError{Code: CodeTemplateInactive}
	ErrTemplateRenderFailed     = &errs.AuthsomeError{Code: CodeTemplateRenderFailed}
	ErrNotificationNotFound     = &errs.AuthsomeError{Code: CodeNotificationNotFound}
	ErrNotificationFailed       = &errs.AuthsomeError{Code: CodeNotificationFailed}
	ErrNotificationSendFailed   = &errs.AuthsomeError{Code: CodeNotificationSendFailed}
	ErrProviderNotConfigured    = &errs.AuthsomeError{Code: CodeProviderNotConfigured}
	ErrProviderNotFound         = &errs.AuthsomeError{Code: CodeProviderNotFound}
	ErrProviderValidationFailed = &errs.AuthsomeError{Code: CodeProviderValidationFailed}
	ErrVersionNotFound          = &errs.AuthsomeError{Code: CodeVersionNotFound}
	ErrVersionRestoreFailed     = &errs.AuthsomeError{Code: CodeVersionRestoreFailed}
	ErrTestNotFound             = &errs.AuthsomeError{Code: CodeTestNotFound}
	ErrTestFailed               = &errs.AuthsomeError{Code: CodeTestFailed}
	ErrInvalidNotificationType  = &errs.AuthsomeError{Code: CodeInvalidNotificationType}
	ErrInvalidRecipient         = &errs.AuthsomeError{Code: CodeInvalidRecipient}
	ErrMissingTemplateVariable  = &errs.AuthsomeError{Code: CodeMissingTemplateVariable}
)

Functions

func GetTemplateKeysByType

func GetTemplateKeysByType(notifType NotificationType) []string

GetTemplateKeysByType returns all template keys for a specific notification type

func InvalidNotificationType

func InvalidNotificationType(notifType string) *errs.AuthsomeError

Validation errors

func InvalidRecipient

func InvalidRecipient(recipient string) *errs.AuthsomeError

func InvalidTemplate

func InvalidTemplate(reason string) *errs.AuthsomeError

func IsTemplateNotFoundError

func IsTemplateNotFoundError(err error) bool

IsTemplateNotFoundError checks if an error is a template not found error

func MissingTemplateVariable

func MissingTemplateVariable(variable string) *errs.AuthsomeError

func NotificationFailed

func NotificationFailed(reason string) *errs.AuthsomeError

func NotificationNotFound

func NotificationNotFound() *errs.AuthsomeError

Notification errors

func NotificationSendFailed

func NotificationSendFailed(err error) *errs.AuthsomeError

func ProviderNotConfigured

func ProviderNotConfigured(notificationType NotificationType) *errs.AuthsomeError

Provider errors

func ProviderNotFound

func ProviderNotFound(providerID string) *errs.AuthsomeError

func ProviderValidationFailed

func ProviderValidationFailed(err error) *errs.AuthsomeError

func SerializeRetryItem added in v0.0.7

func SerializeRetryItem(item *RetryItem) ([]byte, error)

SerializeRetryItem serializes a retry item to JSON

func TemplateAlreadyExists

func TemplateAlreadyExists(key string) *errs.AuthsomeError

func TemplateInactive

func TemplateInactive(key string) *errs.AuthsomeError

func TemplateNotFound

func TemplateNotFound() *errs.AuthsomeError

Template errors

func TemplateRenderFailed

func TemplateRenderFailed(err error) *errs.AuthsomeError

func TestFailed

func TestFailed(reason string) *errs.AuthsomeError

func TestNotFound

func TestNotFound() *errs.AuthsomeError

Test errors

func ValidateTemplateKey

func ValidateTemplateKey(key string) bool

ValidateTemplateKey checks if a template key is a valid default template key

func VersionNotFound

func VersionNotFound() *errs.AuthsomeError

Version errors

func VersionRestoreFailed

func VersionRestoreFailed(err error) *errs.AuthsomeError

Types

type ABTestResults

type ABTestResults struct {
	ABTestGroup  string                   `json:"abTestGroup"`
	Variants     []VariantPerformance     `json:"variants"`
	Winner       *xid.ID                  `json:"winner,omitempty"`
	Significance *StatisticalSignificance `json:"significance,omitempty"`
}

ABTestResults represents the results of an A/B test

type ABTestService

type ABTestService struct {
	// contains filtered or unexported fields
}

ABTestService handles A/B testing operations

func NewABTestService

func NewABTestService(repo Repository) *ABTestService

NewABTestService creates a new A/B test service

func (*ABTestService) CalculateStatisticalSignificance

func (s *ABTestService) CalculateStatisticalSignificance(variant1, variant2 VariantPerformance) *StatisticalSignificance

CalculateStatisticalSignificance calculates if one variant is statistically better than another

func (*ABTestService) CreateVariant

func (s *ABTestService) CreateVariant(ctx context.Context, baseTemplateID xid.ID, variantName string, weight int, subject, body string) (*schema.NotificationTemplate, error)

CreateVariant creates a new A/B test variant for a template

func (*ABTestService) DeclareWinner

func (s *ABTestService) DeclareWinner(ctx context.Context, winnerID xid.ID, abTestGroup string) error

DeclareWinner declares a winning variant and deactivates others

func (*ABTestService) GetABTestResults

func (s *ABTestService) GetABTestResults(ctx context.Context, abTestGroup string) (*ABTestResults, error)

GetABTestResults gets the performance results for all variants in an AB test

func (*ABTestService) SelectVariant

func (s *ABTestService) SelectVariant(ctx context.Context, appID xid.ID, orgID *xid.ID, templateKey, notifType, language string) (*schema.NotificationTemplate, error)

SelectVariant selects a variant based on weighted distribution

type AnalyticsService

type AnalyticsService struct {
	// contains filtered or unexported fields
}

AnalyticsService handles notification analytics operations

func NewAnalyticsService

func NewAnalyticsService(repo Repository) *AnalyticsService

NewAnalyticsService creates a new analytics service

func (*AnalyticsService) GetAppAnalytics

func (s *AnalyticsService) GetAppAnalytics(ctx context.Context, appID xid.ID, startDate, endDate time.Time) (*AppAnalyticsReport, error)

GetAppAnalytics retrieves aggregate analytics for an app

func (*AnalyticsService) GetEventsByNotification

func (s *AnalyticsService) GetEventsByNotification(ctx context.Context, notificationID xid.ID) ([]*schema.NotificationAnalytics, error)

GetEventsByNotification retrieves all analytics events for a notification

func (*AnalyticsService) GetOrgAnalytics

func (s *AnalyticsService) GetOrgAnalytics(ctx context.Context, orgID xid.ID, startDate, endDate time.Time) (*OrgAnalyticsReport, error)

GetOrgAnalytics retrieves aggregate analytics for an organization

func (*AnalyticsService) GetTemplateAnalytics

func (s *AnalyticsService) GetTemplateAnalytics(ctx context.Context, templateID xid.ID, startDate, endDate time.Time) (*TemplateAnalyticsReport, error)

GetTemplateAnalytics retrieves analytics for a specific template

func (*AnalyticsService) TrackClick

func (s *AnalyticsService) TrackClick(ctx context.Context, notificationID xid.ID, linkURL, userAgent, ipAddress string) error

TrackClick tracks when a recipient clicks a link

func (*AnalyticsService) TrackConversion

func (s *AnalyticsService) TrackConversion(ctx context.Context, notificationID xid.ID, conversionType string, conversionValue float64) error

TrackConversion tracks when a recipient completes a desired action

func (*AnalyticsService) TrackEvent

func (s *AnalyticsService) TrackEvent(ctx context.Context, notificationID, templateID, appID xid.ID, orgID *xid.ID, eventType string, eventData map[string]interface{}) error

TrackEvent tracks a notification event

func (*AnalyticsService) TrackOpen

func (s *AnalyticsService) TrackOpen(ctx context.Context, notificationID xid.ID, userAgent, ipAddress string) error

TrackOpen tracks when a recipient opens an email (via tracking pixel)

type AppAnalyticsReport

type AppAnalyticsReport struct {
	AppID           xid.ID    `json:"appId"`
	TotalSent       int64     `json:"totalSent"`
	TotalDelivered  int64     `json:"totalDelivered"`
	TotalOpened     int64     `json:"totalOpened"`
	TotalClicked    int64     `json:"totalClicked"`
	TotalConverted  int64     `json:"totalConverted"`
	TotalBounced    int64     `json:"totalBounced"`
	TotalComplained int64     `json:"totalComplained"`
	TotalFailed     int64     `json:"totalFailed"`
	DeliveryRate    float64   `json:"deliveryRate"`
	OpenRate        float64   `json:"openRate"`
	ClickRate       float64   `json:"clickRate"`
	ConversionRate  float64   `json:"conversionRate"`
	BounceRate      float64   `json:"bounceRate"`
	ComplaintRate   float64   `json:"complaintRate"`
	StartDate       time.Time `json:"startDate"`
	EndDate         time.Time `json:"endDate"`
}

AppAnalyticsReport represents aggregate analytics data for an app

type Config

type Config struct {
	DefaultProvider map[NotificationType]string `json:"defaultProvider"`
	RetryAttempts   int                         `json:"retryAttempts"`
	RetryDelay      time.Duration               `json:"retryDelay"`
	CleanupAfter    time.Duration               `json:"cleanupAfter"`

	// Async processing configuration
	AsyncEnabled   bool `json:"asyncEnabled"`   // Enable async processing for non-critical notifications
	WorkerPoolSize int  `json:"workerPoolSize"` // Number of workers per priority level
	QueueSize      int  `json:"queueSize"`      // Buffer size for async queues

	// Retry configuration
	RetryEnabled    bool     `json:"retryEnabled"`    // Enable retry for failed notifications
	MaxRetries      int      `json:"maxRetries"`      // Maximum retry attempts (default: 3)
	RetryBackoff    []string `json:"retryBackoff"`    // Backoff durations (default: ["1m", "5m", "15m"])
	PersistFailures bool     `json:"persistFailures"` // Persist permanently failed notifications to DB
}

Config holds the notification service configuration

type CreateTemplateRequest

type CreateTemplateRequest struct {
	AppID       xid.ID                 `json:"appId" validate:"required"`
	TemplateKey string                 `json:"templateKey" validate:"required"`
	Name        string                 `json:"name" validate:"required"`
	Type        NotificationType       `json:"type" validate:"required"`
	Language    string                 `json:"language,omitempty"`
	Subject     string                 `json:"subject,omitempty"`
	Body        string                 `json:"body" validate:"required"`
	Variables   []string               `json:"variables,omitempty"`
	Metadata    map[string]interface{} `json:"metadata,omitempty"`
}

CreateTemplateRequest represents a request to create a template

type DispatchRequest added in v0.0.7

type DispatchRequest struct {
	AppID       xid.ID
	Type        NotificationType
	Priority    NotificationPriority
	Recipient   string
	Subject     string
	Body        string
	TemplateKey string
	Variables   map[string]interface{}
	Metadata    map[string]interface{}
}

DispatchRequest represents a notification dispatch request

type DispatchResult added in v0.0.7

type DispatchResult struct {
	NotificationID xid.ID
	Status         NotificationStatus
	Error          error
	Queued         bool // true if queued for async processing
}

DispatchResult represents the result of a dispatch operation

type Dispatcher added in v0.0.7

type Dispatcher struct {
	// contains filtered or unexported fields
}

Dispatcher handles async notification dispatching with priority-based queuing

func NewDispatcher added in v0.0.7

func NewDispatcher(config DispatcherConfig, sender NotificationSender, retry *RetryService) *Dispatcher

NewDispatcher creates a new notification dispatcher

func (*Dispatcher) Dispatch added in v0.0.7

func (d *Dispatcher) Dispatch(ctx context.Context, req *DispatchRequest) *DispatchResult

Dispatch dispatches a notification with the specified priority Critical notifications are processed synchronously Non-critical notifications are queued for async processing

func (*Dispatcher) DispatchWithPriority added in v0.0.7

func (d *Dispatcher) DispatchWithPriority(ctx context.Context, req *SendRequest, priority NotificationPriority) *DispatchResult

DispatchWithPriority is a convenience method for dispatching with a specific priority

func (*Dispatcher) IsRunning added in v0.0.7

func (d *Dispatcher) IsRunning() bool

IsRunning returns whether the dispatcher is running

func (*Dispatcher) QueueLength added in v0.0.7

func (d *Dispatcher) QueueLength(priority NotificationPriority) int

QueueLength returns the current queue length for a priority

func (*Dispatcher) Start added in v0.0.7

func (d *Dispatcher) Start()

Start starts the dispatcher workers

func (*Dispatcher) Stop added in v0.0.7

func (d *Dispatcher) Stop()

Stop gracefully stops the dispatcher

type DispatcherConfig added in v0.0.7

type DispatcherConfig struct {
	// AsyncEnabled enables async processing for non-critical notifications
	AsyncEnabled bool `json:"asyncEnabled"`
	// WorkerPoolSize is the number of workers per priority level
	WorkerPoolSize int `json:"workerPoolSize"`
	// QueueSize is the buffer size for each priority queue
	QueueSize int `json:"queueSize"`
	// ShutdownTimeout is the max time to wait for graceful shutdown
	ShutdownTimeout time.Duration `json:"shutdownTimeout"`
}

DispatcherConfig holds configuration for the notification dispatcher

func DefaultDispatcherConfig added in v0.0.7

func DefaultDispatcherConfig() DispatcherConfig

DefaultDispatcherConfig returns sensible defaults

type InMemoryRetryStorage added in v0.0.7

type InMemoryRetryStorage struct {
	// contains filtered or unexported fields
}

InMemoryRetryStorage provides an in-memory implementation of RetryStorage Used when Redis is not available

func NewInMemoryRetryStorage added in v0.0.7

func NewInMemoryRetryStorage() *InMemoryRetryStorage

NewInMemoryRetryStorage creates a new in-memory retry storage

func (*InMemoryRetryStorage) Delete added in v0.0.7

func (s *InMemoryRetryStorage) Delete(ctx context.Context, id xid.ID) error

func (*InMemoryRetryStorage) Dequeue added in v0.0.7

func (s *InMemoryRetryStorage) Dequeue(ctx context.Context, limit int) ([]*RetryItem, error)

func (*InMemoryRetryStorage) Enqueue added in v0.0.7

func (s *InMemoryRetryStorage) Enqueue(ctx context.Context, item *RetryItem) error

func (*InMemoryRetryStorage) GetStats added in v0.0.7

func (s *InMemoryRetryStorage) GetStats(ctx context.Context) (*RetryStats, error)

func (*InMemoryRetryStorage) MarkFailed added in v0.0.7

func (s *InMemoryRetryStorage) MarkFailed(ctx context.Context, item *RetryItem) error

func (*InMemoryRetryStorage) Update added in v0.0.7

func (s *InMemoryRetryStorage) Update(ctx context.Context, item *RetryItem) error

type ListNotificationsFilter

type ListNotificationsFilter struct {
	pagination.PaginationParams
	AppID     xid.ID              `json:"appId" query:"app_id"`
	Type      *NotificationType   `json:"type,omitempty" query:"type"`
	Status    *NotificationStatus `json:"status,omitempty" query:"status"`
	Recipient *string             `json:"recipient,omitempty" query:"recipient"`
}

ListNotificationsFilter represents filter parameters for listing notifications

type ListNotificationsResponse

type ListNotificationsResponse = pagination.PageResponse[*Notification]

ListNotificationsResponse represents a paginated response for notifications

type ListTemplatesFilter

type ListTemplatesFilter struct {
	pagination.PaginationParams
	AppID    xid.ID            `json:"appId" query:"app_id"`
	Type     *NotificationType `json:"type,omitempty" query:"type"`
	Language *string           `json:"language,omitempty" query:"language"`
	Active   *bool             `json:"active,omitempty" query:"active"`
}

ListTemplatesFilter represents filter parameters for listing notification templates

type ListTemplatesResponse

type ListTemplatesResponse = pagination.PageResponse[*Template]

ListTemplatesResponse represents a paginated response for templates

type Notification

type Notification struct {
	ID          xid.ID                 `json:"id"`
	AppID       xid.ID                 `json:"appId"`
	TemplateID  *xid.ID                `json:"templateId,omitempty"`
	Type        NotificationType       `json:"type"`
	Recipient   string                 `json:"recipient"` // Email address or phone number
	Subject     string                 `json:"subject,omitempty"`
	Body        string                 `json:"body"`
	Status      NotificationStatus     `json:"status"`
	Error       string                 `json:"error,omitempty"`
	ProviderID  string                 `json:"providerId,omitempty"` // External provider message ID
	Metadata    map[string]interface{} `json:"metadata,omitempty"`
	SentAt      *time.Time             `json:"sentAt,omitempty"`
	DeliveredAt *time.Time             `json:"deliveredAt,omitempty"`
	// Audit fields
	CreatedAt time.Time `json:"createdAt"`
	UpdatedAt time.Time `json:"updatedAt"`
}

Notification represents a notification instance DTO This is separate from schema.Notification to maintain proper separation of concerns

func FromSchemaNotification

func FromSchemaNotification(sn *schema.Notification) *Notification

FromSchemaNotification converts a schema.Notification model to Notification DTO

func FromSchemaNotifications

func FromSchemaNotifications(notifications []*schema.Notification) []*Notification

FromSchemaNotifications converts a slice of schema.Notification to Notification DTOs

func (*Notification) ToSchema

func (n *Notification) ToSchema() *schema.Notification

ToSchema converts the Notification DTO to a schema.Notification model

type NotificationPriority added in v0.0.7

type NotificationPriority string

NotificationPriority represents the priority/criticality of a notification

const (
	// PriorityCritical - MFA codes, password reset - must succeed, blocks auth if fails
	PriorityCritical NotificationPriority = "critical"
	// PriorityHigh - Email verification - important but can retry async
	PriorityHigh NotificationPriority = "high"
	// PriorityNormal - Welcome emails - best effort with limited retries
	PriorityNormal NotificationPriority = "normal"
	// PriorityLow - New device alerts - fire and forget, no retries
	PriorityLow NotificationPriority = "low"
)

func GetTemplatePriority added in v0.0.7

func GetTemplatePriority(key string) NotificationPriority

GetTemplatePriority returns the default priority for a template key Returns PriorityNormal if template not found

type NotificationSender added in v0.0.7

type NotificationSender interface {
	Send(ctx context.Context, req *SendRequest) (*Notification, error)
}

NotificationSender is the interface for sending notifications

type NotificationStatus

type NotificationStatus string

NotificationStatus represents the status of a notification

const (
	NotificationStatusPending   NotificationStatus = "pending"
	NotificationStatusSent      NotificationStatus = "sent"
	NotificationStatusFailed    NotificationStatus = "failed"
	NotificationStatusDelivered NotificationStatus = "delivered"
	NotificationStatusBounced   NotificationStatus = "bounced"
)

type NotificationType

type NotificationType string

NotificationType represents the type of notification

const (
	NotificationTypeEmail NotificationType = "email"
	NotificationTypeSMS   NotificationType = "sms"
	NotificationTypePush  NotificationType = "push"
)

type OrgAnalyticsReport

type OrgAnalyticsReport struct {
	OrganizationID  xid.ID    `json:"organizationId"`
	TotalSent       int64     `json:"totalSent"`
	TotalDelivered  int64     `json:"totalDelivered"`
	TotalOpened     int64     `json:"totalOpened"`
	TotalClicked    int64     `json:"totalClicked"`
	TotalConverted  int64     `json:"totalConverted"`
	TotalBounced    int64     `json:"totalBounced"`
	TotalComplained int64     `json:"totalComplained"`
	TotalFailed     int64     `json:"totalFailed"`
	DeliveryRate    float64   `json:"deliveryRate"`
	OpenRate        float64   `json:"openRate"`
	ClickRate       float64   `json:"clickRate"`
	ConversionRate  float64   `json:"conversionRate"`
	BounceRate      float64   `json:"bounceRate"`
	ComplaintRate   float64   `json:"complaintRate"`
	StartDate       time.Time `json:"startDate"`
	EndDate         time.Time `json:"endDate"`
}

OrgAnalyticsReport represents aggregate analytics data for an organization

type Provider

type Provider interface {
	// ID returns the provider identifier
	ID() string

	// Type returns the notification type this provider handles
	Type() NotificationType

	// Send sends a notification
	Send(ctx context.Context, notification *Notification) error

	// GetStatus gets the delivery status of a notification
	GetStatus(ctx context.Context, providerID string) (NotificationStatus, error)

	// ValidateConfig validates the provider configuration
	ValidateConfig() error
}

Provider represents a notification provider interface

type ProviderService

type ProviderService struct {
	// contains filtered or unexported fields
}

ProviderService handles provider management operations

func NewProviderService

func NewProviderService(repo Repository) *ProviderService

NewProviderService creates a new provider service

func (*ProviderService) CreateProvider

func (s *ProviderService) CreateProvider(ctx context.Context, appID xid.ID, orgID *xid.ID, providerType, providerName string, config map[string]interface{}, isDefault bool) (*schema.NotificationProvider, error)

CreateProvider creates a new notification provider

func (*ProviderService) DeleteProvider

func (s *ProviderService) DeleteProvider(ctx context.Context, id xid.ID) error

DeleteProvider deletes a provider

func (*ProviderService) GetProvider

func (s *ProviderService) GetProvider(ctx context.Context, id xid.ID) (*schema.NotificationProvider, error)

GetProvider retrieves a provider by ID

func (*ProviderService) ListProviders

func (s *ProviderService) ListProviders(ctx context.Context, appID xid.ID, orgID *xid.ID) ([]*schema.NotificationProvider, error)

ListProviders lists all providers for an app/org

func (*ProviderService) ResolveProvider

func (s *ProviderService) ResolveProvider(ctx context.Context, appID xid.ID, orgID *xid.ID, providerType string) (*schema.NotificationProvider, error)

ResolveProvider resolves the best provider for a given app/org and type Priority: org-specific default > app-level default

func (*ProviderService) UpdateProvider

func (s *ProviderService) UpdateProvider(ctx context.Context, id xid.ID, config map[string]interface{}, isActive, isDefault bool) error

UpdateProvider updates a provider's configuration

type Repository

type Repository interface {
	// Template operations
	CreateTemplate(ctx context.Context, template *schema.NotificationTemplate) error
	FindTemplateByID(ctx context.Context, id xid.ID) (*schema.NotificationTemplate, error)
	FindTemplateByName(ctx context.Context, appID xid.ID, name string) (*schema.NotificationTemplate, error)
	FindTemplateByKey(ctx context.Context, appID xid.ID, templateKey, notifType, language string) (*schema.NotificationTemplate, error)
	FindTemplateByKeyOrgScoped(ctx context.Context, appID xid.ID, orgID *xid.ID, templateKey, notifType, language string) (*schema.NotificationTemplate, error)
	ListTemplates(ctx context.Context, filter *ListTemplatesFilter) (*pagination.PageResponse[*schema.NotificationTemplate], error)
	UpdateTemplate(ctx context.Context, id xid.ID, req *UpdateTemplateRequest) error
	UpdateTemplateMetadata(ctx context.Context, id xid.ID, isDefault, isModified bool, defaultHash string) error
	UpdateTemplateAnalytics(ctx context.Context, id xid.ID, sendCount, openCount, clickCount, conversionCount int64) error
	DeleteTemplate(ctx context.Context, id xid.ID) error

	// Template versioning operations
	CreateTemplateVersion(ctx context.Context, version *schema.NotificationTemplateVersion) error
	FindTemplateVersionByID(ctx context.Context, id xid.ID) (*schema.NotificationTemplateVersion, error)
	ListTemplateVersions(ctx context.Context, templateID xid.ID) ([]*schema.NotificationTemplateVersion, error)
	GetLatestTemplateVersion(ctx context.Context, templateID xid.ID) (*schema.NotificationTemplateVersion, error)

	// Notification operations
	CreateNotification(ctx context.Context, notification *schema.Notification) error
	FindNotificationByID(ctx context.Context, id xid.ID) (*schema.Notification, error)
	ListNotifications(ctx context.Context, filter *ListNotificationsFilter) (*pagination.PageResponse[*schema.Notification], error)
	UpdateNotificationStatus(ctx context.Context, id xid.ID, status NotificationStatus, error string, providerID string) error
	UpdateNotificationDelivery(ctx context.Context, id xid.ID, deliveredAt time.Time) error

	// Provider operations
	CreateProvider(ctx context.Context, provider *schema.NotificationProvider) error
	FindProviderByID(ctx context.Context, id xid.ID) (*schema.NotificationProvider, error)
	FindProviderByTypeOrgScoped(ctx context.Context, appID xid.ID, orgID *xid.ID, providerType string) (*schema.NotificationProvider, error)
	ListProviders(ctx context.Context, appID xid.ID, orgID *xid.ID) ([]*schema.NotificationProvider, error)
	UpdateProvider(ctx context.Context, id xid.ID, config map[string]interface{}, isActive, isDefault bool) error
	DeleteProvider(ctx context.Context, id xid.ID) error

	// Analytics operations
	CreateAnalyticsEvent(ctx context.Context, event *schema.NotificationAnalytics) error
	FindAnalyticsByNotificationID(ctx context.Context, notificationID xid.ID) ([]*schema.NotificationAnalytics, error)
	GetTemplateAnalytics(ctx context.Context, templateID xid.ID, startDate, endDate time.Time) (*TemplateAnalyticsReport, error)
	GetAppAnalytics(ctx context.Context, appID xid.ID, startDate, endDate time.Time) (*AppAnalyticsReport, error)
	GetOrgAnalytics(ctx context.Context, orgID xid.ID, startDate, endDate time.Time) (*OrgAnalyticsReport, error)

	// Test operations
	CreateTest(ctx context.Context, test *schema.NotificationTest) error
	FindTestByID(ctx context.Context, id xid.ID) (*schema.NotificationTest, error)
	ListTests(ctx context.Context, templateID xid.ID) ([]*schema.NotificationTest, error)
	UpdateTestStatus(ctx context.Context, id xid.ID, status string, results map[string]interface{}, successCount, failureCount int) error

	// Cleanup operations
	CleanupOldNotifications(ctx context.Context, olderThan time.Time) error
	CleanupOldAnalytics(ctx context.Context, olderThan time.Time) error
	CleanupOldTests(ctx context.Context, olderThan time.Time) error
}

Repository defines the notification repository interface

type RetryConfig added in v0.0.7

type RetryConfig struct {
	// Enabled enables retry functionality
	Enabled bool `json:"enabled"`
	// MaxRetries is the maximum number of retry attempts
	MaxRetries int `json:"maxRetries"`
	// BackoffDurations are the delays between retries (e.g., 1m, 5m, 15m)
	BackoffDurations []time.Duration `json:"backoffDurations"`
	// PersistFailures persists permanently failed notifications to DB
	PersistFailures bool `json:"persistFailures"`
}

RetryConfig holds configuration for the retry service

func DefaultRetryConfig added in v0.0.7

func DefaultRetryConfig() RetryConfig

DefaultRetryConfig returns sensible defaults

type RetryItem added in v0.0.7

type RetryItem struct {
	ID          xid.ID                 `json:"id"`
	AppID       xid.ID                 `json:"appId"`
	Type        NotificationType       `json:"type"`
	Priority    NotificationPriority   `json:"priority"`
	Recipient   string                 `json:"recipient"`
	Subject     string                 `json:"subject,omitempty"`
	Body        string                 `json:"body,omitempty"`
	TemplateKey string                 `json:"templateKey,omitempty"`
	Variables   map[string]interface{} `json:"variables,omitempty"`
	Metadata    map[string]interface{} `json:"metadata,omitempty"`
	Attempts    int                    `json:"attempts"`
	LastError   string                 `json:"lastError"`
	NextRetry   time.Time              `json:"nextRetry"`
	CreatedAt   time.Time              `json:"createdAt"`
}

RetryItem represents a notification queued for retry

func DeserializeRetryItem added in v0.0.7

func DeserializeRetryItem(data []byte) (*RetryItem, error)

DeserializeRetryItem deserializes a retry item from JSON

type RetryService added in v0.0.7

type RetryService struct {
	// contains filtered or unexported fields
}

RetryService handles notification retry logic

func NewRetryService added in v0.0.7

func NewRetryService(config RetryConfig, storage RetryStorage, sender NotificationSender) *RetryService

NewRetryService creates a new retry service

func (*RetryService) GetStats added in v0.0.7

func (r *RetryService) GetStats(ctx context.Context) (*RetryStats, error)

GetStats returns retry queue statistics

func (*RetryService) QueueForRetry added in v0.0.7

func (r *RetryService) QueueForRetry(ctx context.Context, req *DispatchRequest, originalErr error) error

QueueForRetry queues a failed notification for retry

func (*RetryService) Start added in v0.0.7

func (r *RetryService) Start()

Start starts the retry processor

func (*RetryService) Stop added in v0.0.7

func (r *RetryService) Stop()

Stop stops the retry processor

type RetryStats added in v0.0.7

type RetryStats struct {
	PendingCount   int64 `json:"pendingCount"`
	FailedCount    int64 `json:"failedCount"`
	ProcessedCount int64 `json:"processedCount"`
}

RetryStats holds retry queue statistics

type RetryStorage added in v0.0.7

type RetryStorage interface {
	// Enqueue adds an item to the retry queue
	Enqueue(ctx context.Context, item *RetryItem) error
	// Dequeue retrieves items ready for retry
	Dequeue(ctx context.Context, limit int) ([]*RetryItem, error)
	// Update updates an item's retry state
	Update(ctx context.Context, item *RetryItem) error
	// Delete removes an item from the queue
	Delete(ctx context.Context, id xid.ID) error
	// MarkFailed marks an item as permanently failed
	MarkFailed(ctx context.Context, item *RetryItem) error
	// GetStats returns queue statistics
	GetStats(ctx context.Context) (*RetryStats, error)
}

RetryStorage defines the interface for retry queue storage

type SendRequest

type SendRequest struct {
	AppID        xid.ID                 `json:"appId" validate:"required"`
	TemplateName string                 `json:"templateName,omitempty"` // Use template
	Type         NotificationType       `json:"type" validate:"required"`
	Recipient    string                 `json:"recipient" validate:"required"`
	Subject      string                 `json:"subject,omitempty"`   // For email (overrides template)
	Body         string                 `json:"body,omitempty"`      // Direct body (overrides template)
	Variables    map[string]interface{} `json:"variables,omitempty"` // Template variables
	Metadata     map[string]interface{} `json:"metadata,omitempty"`
}

SendRequest represents a request to send a notification

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service provides notification functionality

func NewService

func NewService(
	repo Repository,
	engine TemplateEngine,
	auditSvc *audit.Service,
	cfg Config,
) *Service

NewService creates a new notification service

func (*Service) CleanupOldNotifications

func (s *Service) CleanupOldNotifications(ctx context.Context) error

CleanupOldNotifications removes old notifications

func (*Service) CompareWithDefault

func (s *Service) CompareWithDefault(ctx context.Context, templateID xid.ID) (bool, error)

CompareWithDefault checks if template differs from default

func (*Service) CreateTemplate

func (s *Service) CreateTemplate(ctx context.Context, req *CreateTemplateRequest) (*Template, error)

CreateTemplate creates a new notification template

func (*Service) DeleteTemplate

func (s *Service) DeleteTemplate(ctx context.Context, id xid.ID) error

DeleteTemplate deletes a template

func (*Service) GetDispatcherConfig added in v0.0.7

func (s *Service) GetDispatcherConfig() DispatcherConfig

GetDispatcherConfig returns the dispatcher configuration from service config

func (*Service) GetNotification

func (s *Service) GetNotification(ctx context.Context, id xid.ID) (*Notification, error)

GetNotification gets a notification by ID

func (*Service) GetRepository

func (s *Service) GetRepository() Repository

GetRepository returns the repository for use by sub-services

func (*Service) GetRetryConfig added in v0.0.7

func (s *Service) GetRetryConfig() RetryConfig

GetRetryConfig returns the retry configuration from service config

func (*Service) GetTemplate

func (s *Service) GetTemplate(ctx context.Context, id xid.ID) (*Template, error)

GetTemplate gets a template by ID

func (*Service) GetTemplateEngine added in v0.0.3

func (s *Service) GetTemplateEngine() TemplateEngine

GetTemplateEngine returns the template engine for external rendering

func (*Service) InitializeDefaultTemplates

func (s *Service) InitializeDefaultTemplates(ctx context.Context, appID xid.ID) error

InitializeDefaultTemplates creates default templates for an app

func (*Service) ListNotifications

func (s *Service) ListNotifications(ctx context.Context, filter *ListNotificationsFilter) (*ListNotificationsResponse, error)

ListNotifications lists notifications with pagination

func (*Service) ListTemplates

func (s *Service) ListTemplates(ctx context.Context, filter *ListTemplatesFilter) (*ListTemplatesResponse, error)

ListTemplates lists templates with pagination

func (*Service) RegisterProvider

func (s *Service) RegisterProvider(provider Provider) error

RegisterProvider registers a notification provider

func (*Service) ResetAllTemplates

func (s *Service) ResetAllTemplates(ctx context.Context, appID xid.ID) error

ResetAllTemplates resets all templates for an app to defaults

func (*Service) ResetTemplate

func (s *Service) ResetTemplate(ctx context.Context, templateID xid.ID) error

ResetTemplate resets a template to its default values

func (*Service) Send

func (s *Service) Send(ctx context.Context, req *SendRequest) (*Notification, error)

Send sends a notification

func (*Service) TemplateExists

func (s *Service) TemplateExists(ctx context.Context, appID xid.ID, templateKey string) (bool, error)

TemplateExists checks if a template exists

func (*Service) UpdateDeliveryStatus

func (s *Service) UpdateDeliveryStatus(ctx context.Context, id xid.ID, status NotificationStatus) error

UpdateDeliveryStatus updates the delivery status of a notification

func (*Service) UpdateTemplate

func (s *Service) UpdateTemplate(ctx context.Context, id xid.ID, req *UpdateTemplateRequest) error

UpdateTemplate updates a template

type SimpleTemplateEngine

type SimpleTemplateEngine struct{}

SimpleTemplateEngine implements TemplateEngine using Go's text/template

func NewSimpleTemplateEngine

func NewSimpleTemplateEngine() *SimpleTemplateEngine

NewSimpleTemplateEngine creates a new simple template engine

func (*SimpleTemplateEngine) ExtractVariables

func (e *SimpleTemplateEngine) ExtractVariables(templateStr string) ([]string, error)

ExtractVariables extracts variable names from template

func (*SimpleTemplateEngine) Render

func (e *SimpleTemplateEngine) Render(templateStr string, variables map[string]interface{}) (string, error)

Render renders a template with variables

func (*SimpleTemplateEngine) RenderWithFuncs

func (e *SimpleTemplateEngine) RenderWithFuncs(templateStr string, variables map[string]interface{}) (string, error)

RenderWithFuncs renders a template with variables and custom functions

func (*SimpleTemplateEngine) ValidateTemplate

func (e *SimpleTemplateEngine) ValidateTemplate(templateStr string) error

ValidateTemplate validates template syntax

type StatisticalSignificance

type StatisticalSignificance struct {
	ZScore            float64 `json:"zScore"`
	PValue            float64 `json:"pValue"`
	IsSignificant     bool    `json:"isSignificant"`
	ConfidenceLevel   float64 `json:"confidenceLevel"`
	DifferencePercent float64 `json:"differencePercent"`
}

StatisticalSignificance represents statistical test results

type Template

type Template struct {
	ID          xid.ID                 `json:"id"`
	AppID       xid.ID                 `json:"appId"`
	TemplateKey string                 `json:"templateKey"` // e.g., "auth.welcome", "auth.mfa_code"
	Name        string                 `json:"name"`
	Type        NotificationType       `json:"type"`
	Language    string                 `json:"language"` // e.g., "en", "es", "fr"
	Subject     string                 `json:"subject,omitempty"`
	Body        string                 `json:"body"`
	Variables   []string               `json:"variables"` // Available template variables
	Metadata    map[string]interface{} `json:"metadata,omitempty"`
	Active      bool                   `json:"active"`
	IsDefault   bool                   `json:"isDefault"`   // Is this a default template
	IsModified  bool                   `json:"isModified"`  // Has it been modified from default
	DefaultHash string                 `json:"defaultHash"` // Hash of default content for comparison
	// Audit fields
	CreatedAt time.Time  `json:"createdAt"`
	UpdatedAt time.Time  `json:"updatedAt"`
	DeletedAt *time.Time `json:"deletedAt,omitempty"`
}

Template represents a notification template DTO This is separate from schema.NotificationTemplate to maintain proper separation of concerns

func FromSchemaTemplate

func FromSchemaTemplate(st *schema.NotificationTemplate) *Template

FromSchemaTemplate converts a schema.NotificationTemplate model to Template DTO

func FromSchemaTemplates

func FromSchemaTemplates(templates []*schema.NotificationTemplate) []*Template

FromSchemaTemplates converts a slice of schema.NotificationTemplate to Template DTOs

func (*Template) ToSchema

func (t *Template) ToSchema() *schema.NotificationTemplate

ToSchema converts the Template DTO to a schema.NotificationTemplate model

type TemplateAnalyticsReport

type TemplateAnalyticsReport struct {
	TemplateID      xid.ID    `json:"templateId"`
	TemplateName    string    `json:"templateName"`
	TotalSent       int64     `json:"totalSent"`
	TotalDelivered  int64     `json:"totalDelivered"`
	TotalOpened     int64     `json:"totalOpened"`
	TotalClicked    int64     `json:"totalClicked"`
	TotalConverted  int64     `json:"totalConverted"`
	TotalBounced    int64     `json:"totalBounced"`
	TotalComplained int64     `json:"totalComplained"`
	TotalFailed     int64     `json:"totalFailed"`
	DeliveryRate    float64   `json:"deliveryRate"`   // Percentage of sent that were delivered
	OpenRate        float64   `json:"openRate"`       // Percentage of delivered that were opened
	ClickRate       float64   `json:"clickRate"`      // Percentage of opened that were clicked
	ConversionRate  float64   `json:"conversionRate"` // Percentage of clicked that converted
	BounceRate      float64   `json:"bounceRate"`     // Percentage of sent that bounced
	ComplaintRate   float64   `json:"complaintRate"`  // Percentage of delivered that complained
	StartDate       time.Time `json:"startDate"`
	EndDate         time.Time `json:"endDate"`
}

TemplateAnalyticsReport represents analytics data for a specific template

type TemplateEngine

type TemplateEngine interface {
	// Render renders a template with variables
	Render(template string, variables map[string]interface{}) (string, error)

	// ValidateTemplate validates template syntax
	ValidateTemplate(template string) error

	// ExtractVariables extracts variable names from template
	ExtractVariables(template string) ([]string, error)
}

TemplateEngine defines the template rendering interface

type TemplateMetadata

type TemplateMetadata struct {
	Key             string               `json:"key"`
	Name            string               `json:"name"`
	Description     string               `json:"description"`
	Type            NotificationType     `json:"type"`
	Priority        NotificationPriority `json:"priority"` // Default priority for this template type
	Variables       []string             `json:"variables"`
	DefaultSubject  string               `json:"defaultSubject"`
	DefaultBody     string               `json:"defaultBody"`
	DefaultBodyHTML string               `json:"defaultBodyHTML,omitempty"`
}

TemplateMetadata contains metadata about a template including default content

func GetDefaultTemplate

func GetDefaultTemplate(key string) (*TemplateMetadata, error)

GetDefaultTemplate retrieves default template metadata by key

func GetDefaultTemplateMetadata

func GetDefaultTemplateMetadata() []TemplateMetadata

GetDefaultTemplateMetadata returns metadata for all default templates

type UpdateTemplateRequest

type UpdateTemplateRequest struct {
	Name      *string                `json:"name,omitempty"`
	Subject   *string                `json:"subject,omitempty"`
	Body      *string                `json:"body,omitempty"`
	Variables []string               `json:"variables,omitempty"`
	Metadata  map[string]interface{} `json:"metadata,omitempty"`
	Active    *bool                  `json:"active,omitempty"`
}

UpdateTemplateRequest represents a request to update a template

type VariantPerformance

type VariantPerformance struct {
	TemplateID     xid.ID  `json:"templateId"`
	TemplateName   string  `json:"templateName"`
	TotalSent      int64   `json:"totalSent"`
	TotalOpened    int64   `json:"totalOpened"`
	TotalClicked   int64   `json:"totalClicked"`
	TotalConverted int64   `json:"totalConverted"`
	OpenRate       float64 `json:"openRate"`
	ClickRate      float64 `json:"clickRate"`
	ConversionRate float64 `json:"conversionRate"`
}

VariantPerformance represents performance metrics for a variant

type VersionComparison

type VersionComparison struct {
	Version1       *schema.NotificationTemplateVersion `json:"version1"`
	Version2       *schema.NotificationTemplateVersion `json:"version2"`
	SubjectChanged bool                                `json:"subjectChanged"`
	BodyChanged    bool                                `json:"bodyChanged"`
}

VersionComparison represents a comparison between two versions

type VersionService

type VersionService struct {
	// contains filtered or unexported fields
}

VersionService handles template versioning operations

func NewVersionService

func NewVersionService(repo Repository) *VersionService

NewVersionService creates a new version service

func (*VersionService) CompareVersions

func (s *VersionService) CompareVersions(ctx context.Context, version1ID, version2ID xid.ID) (*VersionComparison, error)

CompareVersions compares two versions and returns the differences

func (*VersionService) CreateVersion

func (s *VersionService) CreateVersion(ctx context.Context, template *schema.NotificationTemplate, changedBy *xid.ID, changes string) (*schema.NotificationTemplateVersion, error)

CreateVersion creates a new version snapshot of a template

func (*VersionService) GetLatestVersion

func (s *VersionService) GetLatestVersion(ctx context.Context, templateID xid.ID) (*schema.NotificationTemplateVersion, error)

GetLatestVersion gets the most recent version for a template

func (*VersionService) GetVersion

GetVersion retrieves a specific version by ID

func (*VersionService) ListVersions

func (s *VersionService) ListVersions(ctx context.Context, templateID xid.ID) ([]*schema.NotificationTemplateVersion, error)

ListVersions lists all versions for a template

func (*VersionService) RestoreVersion

func (s *VersionService) RestoreVersion(ctx context.Context, templateID xid.ID, versionID xid.ID, restoredBy *xid.ID) error

RestoreVersion restores a template to a previous version

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL