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

postgres

package
v1.39.1 Latest Latest
Warning

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

Go to latest
Published: Oct 25, 2026 License: MIT Imports: 16 Imported by: 0

Documentation

Overview

Package postgres implements notify's durable inbox on a host-owned PostgreSQL pool. Hosts explicitly migrate before use and authorize every recipient. It starts no workers, sends no messages and never owns the host's pool.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Migrate

func Migrate(ctx context.Context, pool *pgxpool.Pool, schema string) error

Migrate applies this library's versioned migrations in a transaction. The host creates the schema and supplies a pool with DDL permission.

func MigrateDB

func MigrateDB(ctx context.Context, db *sql.DB, schema string) error

MigrateDB is Migrate for a host's database/sql DDL connection.

func Validate

func Validate(ctx context.Context, pool *pgxpool.Pool, schema string) error

Validate verifies the notification ledger and required columns using reads only. It neither creates the schema nor runs pending migrations. Newer additive migrations are accepted when every migration this reader needs is present; an incomplete older ledger is not accepted.

Types

type Config

type Config struct {
	Schema, Scope string
	// Origins, when non-nil, restricts reads and receipt mutations to exact
	// producer namespaces. nil retains the unrestricted legacy behavior.
	// Publication and account erasure cover the whole shared store.
	Origins []notify.OriginScope
	// AppView is the trusted application presentation boundary. It is distinct
	// from producer provenance. Do not combine with the legacy Origins filter.
	AppView *notify.AppView
}

Config binds a store to one local application/tenant scope in a migrated schema.

type LegacyScope

type LegacyScope struct {
	Schema string
	Scope  string
}

LegacyScope identifies an existing, migrated inbox in the same database.

type LegacyVisibility

type LegacyVisibility struct {
	Origin     notify.OriginScope
	Visibility notify.Visibility
	AppID      string
}

LegacyVisibility is an explicit migration claim about one producer scope. It does not alter the producer identity or relabel already classified rows.

type Store

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

Store retains notices and actionable items. Scope and recipients are data isolation boundaries; authorization remains with the host.

func New

func New(pool *pgxpool.Pool, cfg Config) (*Store, error)

New binds an existing pool; it neither migrates nor opens connections.

func (*Store) AppErasedRecipients

func (s *Store) AppErasedRecipients(ctx context.Context, audience notify.Audience, appID string, legacy notify.OriginScope, after string, limit int) ([]notify.Recipient, error)

AppErasedRecipients pages permanent account/app fences for trusted restore reconciliation. Only this app's explicit and native legacy fences join the whole-account tombstones. The caller must finish replay before serving.

func (*Store) Apply

func (s *Store) Apply(ctx context.Context, mutations []notify.Mutation) error

Apply atomically applies up to notify.MaxMutations exact identities.

func (*Store) ApplyTx

func (s *Store) ApplyTx(ctx context.Context, tx pgx.Tx, mutations []notify.Mutation) error

ApplyTx joins the caller's transaction. Its savepoint makes the whole batch atomic even if the caller handles an error and commits other work in tx.

func (*Store) ClassifyLegacyOrigins

func (s *Store) ClassifyLegacyOrigins(ctx context.Context, mappings []LegacyVisibility) (int64, error)

ClassifyLegacyOrigins labels only currently unclassified receipts. Run with writers stopped after verifying each producer scope's ownership. A conflicting explicit classification aborts the whole operation; read/archive state and IDs survive. Versioned unclassified rows require exact source-state adoption; relabeling them would invalidate producer replay. Normal Publish replay never performs this migration implicitly.

func (*Store) EraseAppRecipient

func (s *Store) EraseAppRecipient(ctx context.Context, r notify.Recipient, appID string, legacy notify.OriginScope) error

EraseAppRecipient permanently erases one app's receipts, including its explicitly identified legacy native origin. Tenant-wide notices and other apps survive. This is an erasure boundary, not an inbox dismiss/reset action. IDs and origin come from trusted deployment configuration, never a request.

func (*Store) EraseRecipient

func (s *Store) EraseRecipient(ctx context.Context, r notify.Recipient) error

EraseRecipient deletes an inbox and permanently fences delayed publications. This is account erasure, not the operation for dismissing one item.

func (*Store) EraseRecipientTx

func (s *Store) EraseRecipientTx(ctx context.Context, tx pgx.Tx, r notify.Recipient) error

EraseRecipientTx joins account erasure in the host's transaction.

func (*Store) Get

func (s *Store) Get(ctx context.Context, r notify.Recipient, id string) (notify.Item, error)

Get reads a named receipt, including an archived one, for its recipient.

func (*Store) GetRecipients

func (s *Store) GetRecipients(ctx context.Context, rs []notify.Recipient, id string) (notify.Item, error)

GetRecipients reads a receipt only when its recipient is in the host's fresh authorized set. An absent or newly unlinked recipient reads as not found.

func (*Store) List

List reads one authorized recipient's inbox, newest first. Restart scans from an empty cursor to discover late commits; cursors are not delivery watermarks.

func (*Store) ListRecipients

func (s *Store) ListRecipients(ctx context.Context, recipients []notify.Recipient, o notify.ListOptions) (notify.Page, error)

ListRecipients reads only the recipients the host authorized for this request. Filtering happens in SQL before pagination, so an unlinked recipient consumes no page slots. Empty recipients returns an empty page. Cursors bind the normalized recipient set and filters; restart paging after access changes.

func (*Store) MergeFrom

func (s *Store) MergeFrom(ctx context.Context, sources []LegacyScope) error

MergeFrom consolidates legacy inboxes into this store without changing the sources. Run this maintenance operation with source and destination writers stopped, then switch all writers to the destination. It is not a boot hook.

Duplicate origins retain one receipt, read/archive timestamps from either copy, and the most recently updated workflow state. Erasure wins over every copy. The destination's existing ID survives; otherwise the first source ID survives. A conflicting ID for a different origin aborts the transaction. Reads and receipt changes use this store's origin filter after the merge; the merge itself copies every origin in the explicitly named scopes.

func (*Store) Publish

func (s *Store) Publish(ctx context.Context, in notify.Input) (notify.Item, error)

Publish inserts once per origin and recipient. Retries preserve content and every local read/workflow transition, including after a crash before an ack.

func (*Store) PublishTx

func (s *Store) PublishTx(ctx context.Context, tx pgx.Tx, in notify.Input) (notify.Item, error)

PublishTx joins the domain change's transaction. The transaction must reach the same database as the store; the caller commits or rolls it back.

func (*Store) SetDismissed

func (s *Store) SetDismissed(ctx context.Context, r notify.Recipient, id string, dismissed bool) (notify.Item, error)

SetDismissed archives or restores a recipient's receipt, independently of read state and domain/workflow resolution.

func (*Store) SetDismissedRecipients

func (s *Store) SetDismissedRecipients(ctx context.Context, rs []notify.Recipient, id string, dismissed bool) (notify.Item, error)

SetDismissedRecipients changes only a receipt in the host's currently authorized set. Retried dismissal preserves its original timestamp.

func (*Store) SetRead

func (s *Store) SetRead(ctx context.Context, r notify.Recipient, id string, read bool) (notify.Item, error)

SetRead changes only local read state. It never resolves an actionable item.

func (*Store) SetReadRecipients

func (s *Store) SetReadRecipients(ctx context.Context, rs []notify.Recipient, id string, read bool) (notify.Item, error)

SetReadRecipients updates authorized receipt state and returns the canonical item/revision. Reading does not dismiss the receipt or resolve a workflow.

func (*Store) Transition

func (s *Store) Transition(ctx context.Context, r notify.Recipient, id string, revision int64, status notify.Status) (notify.Item, error)

Transition changes workflow state under optimistic concurrency. The caller must perform/authorize any domain action first, or use TransitionTx in the same transaction as that action. General notices cannot become work items.

func (*Store) TransitionTx

func (s *Store) TransitionTx(ctx context.Context, tx pgx.Tx, r notify.Recipient, id string, revision int64, status notify.Status) (notify.Item, error)

TransitionTx joins a host's transaction; reading and resolving remain separate.

Jump to

Keyboard shortcuts

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