Skip to content

Commit

Permalink
add options to delay broadcast notifications (#27)
Browse files Browse the repository at this point in the history
  • Loading branch information
ice-cronus authored Jan 17, 2024
1 parent e127881 commit b604fe2
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 0 deletions.
16 changes: 16 additions & 0 deletions notifications/push/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,17 @@ type (
Body string `json:"body,omitempty"`
ImageURL string `json:"imageUrl,omitempty"`
}
DelayedNotification struct {
*Notification[SubscriptionTopic]
MinDelaySec uint `json:"minDelaySec"`
MaxDelaySec uint `json:"maxDelaySec"`
}
Client interface {
io.Closer

Send(context.Context, *Notification[DeviceToken], chan<- error)
Broadcast(context.Context, *Notification[SubscriptionTopic]) error
BroadcastDelayed(context.Context, *DelayedNotification) error
}
)

Expand All @@ -47,6 +53,16 @@ const (
requestDeadline = 25 * stdlibtime.Second
fcmSendAllBufferingDeadline = 1 * stdlibtime.Second
fcmSendAllSlowProcessingMonitoringTickerDeadline = 3 * fcmSendAllBufferingDeadline

dataOnlyTitle = "title"
dataOnlyBody = "body"
dataOnlyImageURL = "imageUrl"
dataOnlyMinDelay = "minDelaySec"
dataOnlyMaxDelay = "maxDelaySec"
dataOnlyType = "type"

typeDelayedNotification = "delayed"
priorityHigh = "high"
)

type (
Expand Down
49 changes: 49 additions & 0 deletions notifications/push/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"os"
"runtime"
"strconv"
"strings"
"sync"
stdlibtime "time"
Expand Down Expand Up @@ -137,6 +138,54 @@ func (p *push) Broadcast(ctx context.Context, notification *Notification[Subscri
}), "[%v] permanently failed to broadcast %#v", p.applicationYAMLKey, notification)
}

func (p *push) BroadcastDelayed(ctx context.Context, notification *DelayedNotification) error {
return errors.Wrapf(retry(ctx, func() error {
_, err := p.client.Send(ctx, &fcm.Message{
Data: notification.Data,
Android: buildAndroidDataOnlyNotification(notification),
APNS: buildAppleNotification(notification),
Topic: string(notification.Target),
})

return err //nolint:wrapcheck // No need to do that, it's wrapped outside.
}), "[%v] permanently failed to broadcast delayed notification %#v", p.applicationYAMLKey, notification)
}

func buildAndroidDataOnlyNotification(notification *DelayedNotification) *fcm.AndroidConfig {
dataOnlyNotification := make(map[string]string, len(notification.Data)+3)
for k, v := range notification.Data {
dataOnlyNotification[k] = v
}
dataOnlyNotification[dataOnlyTitle] = notification.Title
dataOnlyNotification[dataOnlyBody] = notification.Body
dataOnlyNotification[dataOnlyImageURL] = notification.ImageURL
dataOnlyNotification[dataOnlyType] = typeDelayedNotification
dataOnlyNotification[dataOnlyMinDelay] = strconv.FormatUint(uint64(notification.MinDelay), 10)

Check failure on line 163 in notifications/push/push.go

View workflow job for this annotation

GitHub Actions / Build

notification.MinDelay undefined (type *DelayedNotification has no field or method MinDelay)
dataOnlyNotification[dataOnlyMaxDelay] = strconv.FormatUint(uint64(notification.MaxDelay), 10)

Check failure on line 164 in notifications/push/push.go

View workflow job for this annotation

GitHub Actions / Build

notification.MaxDelay undefined (type *DelayedNotification has no field or method MaxDelay)

return &fcm.AndroidConfig{
Data: dataOnlyNotification,
Priority: priorityHigh,
}
}

func buildAppleNotification(notification *DelayedNotification) *fcm.APNSConfig {
return &fcm.APNSConfig{
Payload: &fcm.APNSPayload{
Aps: &fcm.Aps{
AlertString: "",
Alert: &fcm.ApsAlert{
Title: notification.Title,
Body: notification.Body,
},
},
},
FCMOptions: &fcm.APNSFCMOptions{
ImageURL: notification.ImageURL,
},
}
}

func retry(ctx context.Context, op func() error) error {
//nolint:wrapcheck // No need, its just a proxy.
return backoff.RetryNotify(
Expand Down

0 comments on commit b604fe2

Please sign in to comment.