push

package
v0.8.2 Latest Latest
Warning

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

Go to latest
Published: Oct 14, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Overview

Package push holds what backd knows about push notification messages that doesn't depend on the realm's settings or its store: the templates they are written from, the portable message and its validation, and the payloads each provider receives (design: design/push-notifications.md §6).

Index

Constants

View Source
const (
	// MaxDataBytes is the serialized size of Message.Data.
	MaxDataBytes = 2048
	// MaxTTL is the longest time providers keep a push (FCM's four weeks).
	MaxTTL = 28 * 24 * time.Hour
	// DefaultTTL is how long a push is kept when the message doesn't say.
	DefaultTTL = 24 * time.Hour
)

Limits of the portable fields.

View Source
const (
	PriorityNormal = "normal"
	PriorityHigh   = "high"
)

The priorities.

View Source
const (
	ProviderFCM     = "fcm"
	ProviderAPNs    = "apns"
	ProviderWebPush = "webpush"
	ProviderCapture = "capture"
)

The providers a platform's pushes can go through.

View Source
const (
	// FCMLimit and APNsLimit are the 4 KiB of the providers' messages.
	FCMLimit  = 4096
	APNsLimit = 4096
	// WebPushLimit is what RFC 8291 leaves of a 4096-byte record for the plaintext.
	WebPushLimit = 3993
)

Payload limits, in bytes.

View Source
const (
	// StatusSent: the provider accepted the push.
	StatusSent = "sent"
	// StatusInvalid: the token is dead; the device is removed.
	StatusInvalid = "invalid"
	// StatusRetry: throttled or transient; only these devices are sent again.
	StatusRetry = "retry"
	// StatusFailed: permanent for this push; the device is kept.
	StatusFailed = "failed"
)

The result of one device of a delivery unit.

View Source
const DirName = "push"

DirName is the folder of a realm that holds its push templates: <realm>/push/<kind>/<locale>.yaml.

View Source
const RawKind = "raw"

RawKind is the kind of a message whose text the function wrote itself.

Variables

View Source
var ErrUnknownKind = errors.New("unknown push kind")

ErrUnknownKind is a kind the realm has no template for.

Functions

func CheckSize

func CheckSize(targets []Target, m Message) error

CheckSize shapes the message for every target and refuses it when one is over its limit.

func Prepare

func Prepare(tpl *Templates, realm string, locales []string, targets []Target, kind string, in Message) (map[string]Message, error)

Prepare writes the message of a send in every language the realm lists and checks each one, so a send that can't be delivered is refused before anything is queued. kind is a template kind, or "" / RawKind for a message whose title and body the function wrote; in is the message as the function gave it (its Data is also what templates see as .Data). The result has one message per locale; raw messages are the same text in all of them.

func Shape

func Shape(t Target, m Message) ([]byte, error)

Shape returns the JSON body the target's provider receives for the message (without the device token, which is not part of the payload that counts against the limit).

Types

type Data

type Data struct {
	Realm string
	User  struct{ Locale string }
	Data  map[string]any
}

Data is what a template can use: the realm, the recipient's language and the call's data. Templates get no address or profile field: lock screens are seen by others.

type Delivery

type Delivery struct {
	UserID   string
	DeviceID string
	Token    string
	Message  Message
}

Delivery is one push to one device.

type DeviceResult

type DeviceResult struct {
	DeviceID string
	Status   string
	Detail   string
}

DeviceResult is how one device went. Detail is for logs and never contains the token.

type Message

type Message struct {
	// Kind is the template the text came from, or RawKind.
	Kind        string
	Title, Body string
	Link        string
	// Data is delivered to the app as it is: strings only, at most MaxDataBytes serialized.
	Data  map[string]string
	Badge *int
	Sound string
	// Group replaces an earlier push with the same key (collapse key, collapse id, topic).
	Group string
	// TTL is how long providers keep trying; nil is DefaultTTL, zero is now or never.
	TTL      *time.Duration
	Priority string
	// Silent is data only: no visible notification.
	Silent bool
	// Platform holds keys android, ios and web, merged into that platform's payload.
	Platform map[string]map[string]any
}

Message is what is sent to a user's devices, in their language.

func (Message) TTLOrDefault

func (m Message) TTLOrDefault() time.Duration

TTLOrDefault is the message's time to live.

func (Message) Validate

func (m Message) Validate() error

Validate checks the portable fields strictly. It expects the text to be in place (rendered from a template, or written by the function).

type Rendered

type Rendered struct{ Title, Body, Link string }

Rendered is a template's output.

type Request

type Request struct {
	Realm    string
	SendID   string
	Attempt  int // 1 for the first try of the unit
	Platform string
	Provider string
	// Config is the platform's block of realm.yaml with the secrets it names read: credentials
	// (FCM's service-account JSON), key (APNs' .p8 key), private_key and subject (Web Push),
	// and key_id, team_id, topic, sandbox ("true"), public_key and allowed_hosts (comma
	// separated: where a web subscription may point).
	Config map[string]string
	// Parallelism is how many provider requests may be in flight at once.
	Parallelism int
	Deliveries  []Delivery
}

Request is what a sender is asked to do: deliver to the devices of one platform with the realm's configuration for the provider.

type Sender

type Sender interface {
	Send(ctx context.Context, req Request) ([]DeviceResult, error)
}

Sender delivers to one provider. It answers a result per device; an error means the call as a whole failed (the network is down, the credentials were refused) and the unit is tried again. A device with no result counts as failed.

type Target

type Target struct{ Platform, Provider string }

Target is one enabled platform and the provider that delivers to it.

func TargetsOf

func TargetsOf(platforms map[string]string) []Target

TargetsOf lists the targets of the enabled platforms, in a stable order.

func (Target) Limit

func (t Target) Limit() int

Limit is the most a provider accepts for the target.

type Templates

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

Templates are the parsed push templates of a realm, by kind and locale.

func Load

func Load(dir string, locales []string) (*Templates, []error)

Load reads <dir>/<kind>/<locale>.yaml for every kind in the folder and checks that each kind has a file for every locale and that every file parses. A missing folder is no templates.

func (*Templates) Has

func (t *Templates) Has(kind, locale string) bool

Has says whether the kind has a template for the locale.

func (*Templates) HasKind

func (t *Templates) HasKind(kind string) bool

HasKind says whether any template of the kind exists.

func (*Templates) Kinds

func (t *Templates) Kinds() []string

Kinds lists the kinds that have templates, sorted.

func (*Templates) Render

func (t *Templates) Render(kind, locale string, d Data) (Rendered, error)

Render writes a kind's message in a locale.

type TooLargeError

type TooLargeError struct {
	Platform string
	Size     int
	Limit    int
}

TooLargeError says a message doesn't fit a provider.

func (*TooLargeError) Error

func (e *TooLargeError) Error() string

type ValidationError

type ValidationError struct{ Field, Reason string }

ValidationError is a message field that can't be sent.

func (*ValidationError) Error

func (e *ValidationError) Error() string

Jump to

Keyboard shortcuts

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