Help us shape the future of Go! Take the 2026 Go Developer Survey

pushservice

package
v0.2.2 Latest Latest
Warning

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

Go to latest
Published: Oct 29, 2026 License: MIT Imports: 15 Imported by: 0

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

Constants

This section is empty.

Variables

View Source
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")
)
View Source
var ErrLeaseLost = errors.New("push notification lease lost")

ErrLeaseLost reports a claim another worker has since replaced.

Functions

func Topic

func Topic(streamID string) string

Topic collapses undelivered notifications of one stream at the push service.

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 Options

type Options struct {
	// PublicURL enables push when it is https, or http on a loopback host for
	// development. Its origin is the VAPID subject.
	PublicURL string
	Now       func() time.Time
}

type RateLimitedError

type RateLimitedError struct{ RetryAfter time.Duration }

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

func New(ctx context.Context, store Store, options Options) (*Service, error)

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

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

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

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

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) Settings

func (s *Service) Settings(ctx context.Context, ownerID string) (Settings, error)

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.

func (*Service) Test

func (s *Service) Test(ctx context.Context, ownerID, id string) error

Test sends a test notification to one of the account's devices and waits for the push service. A device the push service reports gone is removed and reported as ErrNotFound.

func (*Service) Unsubscribe

func (s *Service) Unsubscribe(ctx context.Context, ownerID, id string) error

Unsubscribe removes one of the account's devices.

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.

type Subscription

type Subscription struct {
	ID            string
	OwnerID       string
	Endpoint      string
	P256dh        string
	Auth          string
	Label         string
	CreatedAt     int64
	LastSuccessAt *int64
}

Subscription is one browser's push subscription for an account.

type SubscriptionInput

type SubscriptionInput struct {
	Endpoint string
	P256dh   string
	Auth     string
	Label    string
}

SubscriptionInput is a browser's PushSubscription and a device label.

Jump to

Keyboard shortcuts

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