Add webhook logging, pagination, middleware, migrations, and prod hardening
- Webhook event logging repo and subscription webhook idempotency - Pagination helper (echohelpers) with cursor/offset support - Request ID and structured logging middleware - Push client improvements (FCM HTTP v1, better error handling) - Task model version column, business constraint migrations, targeted indexes - Expanded categorization chain tests - Email service and config hardening - CI workflow updates, .gitignore additions, .env.example updates Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -16,13 +16,14 @@ const (
|
||||
|
||||
// Client provides a unified interface for sending push notifications
|
||||
type Client struct {
|
||||
apns *APNsClient
|
||||
fcm *FCMClient
|
||||
apns *APNsClient
|
||||
fcm *FCMClient
|
||||
enabled bool
|
||||
}
|
||||
|
||||
// NewClient creates a new unified push notification client
|
||||
func NewClient(cfg *config.PushConfig) (*Client, error) {
|
||||
client := &Client{}
|
||||
func NewClient(cfg *config.PushConfig, enabled bool) (*Client, error) {
|
||||
client := &Client{enabled: enabled}
|
||||
|
||||
// Initialize APNs client (iOS)
|
||||
if cfg.APNSKeyPath != "" && cfg.APNSKeyID != "" && cfg.APNSTeamID != "" {
|
||||
@@ -55,6 +56,10 @@ func NewClient(cfg *config.PushConfig) (*Client, error) {
|
||||
|
||||
// SendToIOS sends a push notification to iOS devices
|
||||
func (c *Client) SendToIOS(ctx context.Context, tokens []string, title, message string, data map[string]string) error {
|
||||
if !c.enabled {
|
||||
log.Debug().Msg("Push notifications disabled by feature flag")
|
||||
return nil
|
||||
}
|
||||
if c.apns == nil {
|
||||
log.Warn().Msg("APNs client not initialized, skipping iOS push")
|
||||
return nil
|
||||
@@ -64,6 +69,10 @@ func (c *Client) SendToIOS(ctx context.Context, tokens []string, title, message
|
||||
|
||||
// SendToAndroid sends a push notification to Android devices
|
||||
func (c *Client) SendToAndroid(ctx context.Context, tokens []string, title, message string, data map[string]string) error {
|
||||
if !c.enabled {
|
||||
log.Debug().Msg("Push notifications disabled by feature flag")
|
||||
return nil
|
||||
}
|
||||
if c.fcm == nil {
|
||||
log.Warn().Msg("FCM client not initialized, skipping Android push")
|
||||
return nil
|
||||
@@ -73,6 +82,10 @@ func (c *Client) SendToAndroid(ctx context.Context, tokens []string, title, mess
|
||||
|
||||
// SendToAll sends a push notification to both iOS and Android devices
|
||||
func (c *Client) SendToAll(ctx context.Context, iosTokens, androidTokens []string, title, message string, data map[string]string) error {
|
||||
if !c.enabled {
|
||||
log.Debug().Msg("Push notifications disabled by feature flag")
|
||||
return nil
|
||||
}
|
||||
var lastErr error
|
||||
|
||||
if len(iosTokens) > 0 {
|
||||
@@ -105,6 +118,10 @@ func (c *Client) IsAndroidEnabled() bool {
|
||||
// SendActionableNotification sends notifications with action button support
|
||||
// iOS receives a category for actionable notifications, Android handles actions via data payload
|
||||
func (c *Client) SendActionableNotification(ctx context.Context, iosTokens, androidTokens []string, title, message string, data map[string]string, iosCategoryID string) error {
|
||||
if !c.enabled {
|
||||
log.Debug().Msg("Push notifications disabled by feature flag")
|
||||
return nil
|
||||
}
|
||||
var lastErr error
|
||||
|
||||
if len(iosTokens) > 0 {
|
||||
|
||||
Reference in New Issue
Block a user