Documentation
¶
Overview ¶
Package pushservice owns Web Push for the remote server: when push is enabled, the server's VAPID identity, each account's device subscriptions, and delivery of notification intent recorded with ingestion admissions. Remote composition only. It holds no transport or SQL.
Index ¶
- Variables
- func Topic(streamID string) string
- type Claim
- type Notification
- type Options
- type RateLimitedError
- type Service
- func (s *Service) DeliverDue(ctx context.Context) error
- func (s *Service) Run(ctx context.Context) error
- func (s *Service) Settings(ctx context.Context, ownerID string) (Settings, error)
- func (s *Service) Subscribe(ctx context.Context, ownerID string, input SubscriptionInput) (Subscription, error)
- func (s *Service) Test(ctx context.Context, ownerID, id string) error
- func (s *Service) Unsubscribe(ctx context.Context, ownerID, id string) error
- type Settings
- type Store
- type Subscription
- type SubscriptionInput
Constants ¶
This section is empty.
Variables ¶
var ( // ErrDisabled reports that push needs an HTTPS public URL. ErrDisabled = errors.New("Push notifications need an HTTPS public URL") // ErrNotFound reports a subscription the account does not have. ErrNotFound = errors.New("push subscription not found") // ErrInvalid reports a malformed subscription. ErrInvalid = errors.New("invalid push subscription") // ErrRejected reports a push service that refused or failed a message. ErrRejected = errors.New("push service did not accept the notification") )
var ErrLeaseLost = errors.New("push notification lease lost")
ErrLeaseLost reports a claim another worker has since replaced.
Functions ¶
Types ¶
type Claim ¶
type Claim struct {
Notification
Token string
}
Claim is a pending notification leased to one delivery worker. Token fences the worker's transitions; a lease that expires is claimable again.
type Notification ¶
type Notification struct {
ID string
OwnerID string
Kind string
// Content holds the JSON title and body; delivery adds the link.
Content []byte
Attempt int
CreatedAt int64
// Available reports that the owning account exists and is enabled.
Available bool
// JobState is the linked ingestion job's state, empty when it is gone;
// ContextID is its published context once succeeded.
JobState string
ContextID string
}
Notification is durable notification intent linked to an ingestion job.
type RateLimitedError ¶
RateLimitedError reports a push service throttling the server.
func (*RateLimitedError) Error ¶
func (err *RateLimitedError) Error() string
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
func New ¶
New loads the server's VAPID keys, creating them on first use when push is enabled. Keys never rotate automatically: subscriptions are bound to them.
func (*Service) DeliverDue ¶
DeliverDue attempts up to batch due notifications once, claiming each just before delivering it so a lease covers one notification's sends. A notification whose lease was lost belongs to another worker and is skipped.
func (*Service) Run ¶
Run delivers due notifications until ctx ends. Storage failures are logged and retried on the next poll, so they never stop the server.
func (*Service) Subscribe ¶
func (s *Service) Subscribe(ctx context.Context, ownerID string, input SubscriptionInput) (Subscription, error)
Subscribe registers the browser for the account, replacing an earlier registration of the same endpoint, including another account's.
type Settings ¶
type Settings struct {
Enabled bool
PublicKey string
Devices []Subscription
}
Settings is push availability and the account's devices.
type Store ¶
type Store interface {
// PushKeys stores generated unless keys exist, and returns the stored keys.
PushKeys(ctx context.Context, generated webpush.Keys, now int64) (webpush.Keys, error)
// PutSubscription registers the endpoint for the subscription's owner. The
// same owner's endpoint keeps its ID and creation time; another account's
// endpoint moves to this owner as a new device.
PutSubscription(ctx context.Context, subscription Subscription) (Subscription, error)
Subscriptions(ctx context.Context, ownerID string) ([]Subscription, error)
// DeleteSubscription returns ErrNotFound unless the owner has the subscription.
DeleteSubscription(ctx context.Context, ownerID, id string) error
RecordSuccess(ctx context.Context, subscriptionID string, now int64) error
// ClaimNotifications leases up to limit pending notifications available and
// unleased at now until leaseUntil, oldest first. Concurrent claims never
// return the same notification.
ClaimNotifications(ctx context.Context, now, leaseUntil int64, limit int) ([]Claim, error)
// Undelivered lists the owner's subscriptions without a recorded outcome
// for the notification.
Undelivered(ctx context.Context, notificationID string) ([]Subscription, error)
// RecordDelivery records one device's first final outcome; accepted also
// records the device's last success.
RecordDelivery(ctx context.Context, claim Claim, subscriptionID string, accepted bool, now int64) error
// RetryNotification releases the claim until availableAt.
RetryNotification(ctx context.Context, claim Claim, attempt int, availableAt int64) error
// FinishNotification ends the claimed notification as sent or dropped.
FinishNotification(ctx context.Context, claim Claim, state string) error
// StreamID resolves the owner's context to its review stream; ErrNotFound
// when it was deleted or expired.
StreamID(ctx context.Context, ownerID, contextID string, now int64) (string, error)
}
Store persists push state atomically per operation.