settings

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Oct 31, 2026 License: MIT Imports: 23 Imported by: 0

Documentation

Overview

Package settings persists values through registered, typed key declarations. Form presentation is separate from the value codec and grants no access rights.

Index

Constants

View Source
const (
	MigrationOrigin          migrate.Origin  = "foundry.settings"
	CreateSettings           migrate.ID      = "000001_create_settings"
	AddPresentationOwnership migrate.ID      = "000002_add_presentation_ownership"
	Introduced               migrate.Version = "v0.1.0"
)
View Source
const (
	DefaultPageSize = 100
	// MaxLoadBytes bounds the stored JSON retained by one List, Load or LoadGroup.
	// ListPage never fails on aggregate size: it ends a page early instead.
	MaxLoadBytes = 64 << 20
)
View Source
const MaxCacheTTL = time.Hour

MaxCacheTTL bounds how long a process may serve a cached setting. It is also the upper bound on staleness after a write made by another process.

Variables

This section is empty.

Functions

func Migrations

func Migrations() []migrate.Definition

Migrations returns the settings table history. Rows existing before presentation ownership keep their stored presentation (declared=false); ResetPresentation hands a row back to its declaration explicitly.

Types

type Batch

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

Batch is an immutable snapshot of selected settings. Values decode afresh on each access. Later writes do not change an existing Batch.

func Load

func Load(ctx context.Context, m *Manager, keys ...Selection) (Batch, error)

Load reads the selected registered keys with at most one query. Cached keys are served from the manager's cache; the others are read in one snapshot and may populate it. The retained JSON is bounded by MaxLoadBytes.

func LoadGroup

func LoadGroup(ctx context.Context, m *Manager, group Group) (Batch, error)

LoadGroup loads every registered key whose declared presentation group is group, including keys without a stored row, which read as absent. Membership follows declarations so typed code sees a stable set of keys.

func (Batch) Format

func (Batch) Format(s fmt.State, _ rune)

type Cursor

type Cursor struct {
	Group Group
	Order int32
	Name  Name
}

Cursor is the position after which ListPage continues: the group, sort order and name of the last record already returned. The zero Cursor starts at the beginning. It is a position, not a capability or a consistent snapshot.

func After

func After(r Record) Cursor

After returns the cursor that continues after record r.

func (Cursor) IsZero

func (c Cursor) IsZero() bool

type Filter

type Filter struct {
	Group      Group
	Prefix     string
	PublicOnly bool
}

type Group

type Group string

func Groups

func Groups(ctx context.Context, m *Manager) ([]Group, error)

Groups lists the stored presentation groups of registered settings, ordered as List orders them. It reads presentation columns only, never values.

type Key

type Key[V any] struct {
	// contains filtered or unexported fields
}

func Define

func Define[V any](name Name, version Version, codec contract.JSON[V], presentation Presentation) Key[V]

func (Key[V]) Configure

func (k Key[V]) Configure(ctx context.Context, m *Manager, p Presentation) error

Configure explicitly takes ownership of the persisted presentation. Later declaration changes no longer replace it until ResetPresentation is called.

func (Key[V]) Create

func (k Key[V]) Create(ctx context.Context, m *Manager, input V) error

func (Key[V]) Decode

func (k Key[V]) Decode(ctx context.Context, r Record) (V, error)

func (Key[V]) Ensure

func (k Key[V]) Ensure(ctx context.Context, m *Manager, input V) error

Ensure creates a missing setting using its descriptor's presentation. An existing value remains unchanged, including its version. A presentation still owned by the declaration is refreshed from it; one changed by Configure stays.

func (Key[V]) EnsureIn

func (k Key[V]) EnsureIn(ctx context.Context, tx *database.Tx, m *Manager, input V) error

EnsureIn applies Ensure within the caller's transaction through a savepoint. Parent rollback includes initialization and declaration-owned presentation changes.

func (Key[V]) Find

func (k Key[V]) Find(ctx context.Context, m *Manager) (value.Optional[Record], error)

Find reads one setting. With Options.Cache it is served from the manager's cache until the entry expires or a write through this manager invalidates it.

func (Key[V]) Format

func (Key[V]) Format(s fmt.State, _ rune)

func (Key[V]) From

func (k Key[V]) From(ctx context.Context, b Batch) (value.Optional[V], error)

From decodes this key from a Batch without I/O. A key that was not selected for the batch is an error rather than a silently missing value.

func (Key[V]) FromOr

func (k Key[V]) FromOr(ctx context.Context, b Batch, fallback V) (V, error)

FromOr applies GetOr's fallback rules to a Batch value.

func (Key[V]) Get

func (k Key[V]) Get(ctx context.Context, m *Manager) (value.Optional[V], error)

func (Key[V]) GetOr

func (k Key[V]) GetOr(ctx context.Context, m *Manager, fallback V) (V, error)

GetOr uses a validated, independently decoded fallback only when no row exists. Invalid stored values or versions never silently become defaults. With Options.Cache, repeated calls are served from the manager's cache.

func (Key[V]) Name

func (k Key[V]) Name() Name

func (Key[V]) Registration

func (k Key[V]) Registration() Registration

func (Key[V]) RegistrationWith

func (k Key[V]) RegistrationWith(options Options[V]) Registration

func (Key[V]) Remove

func (k Key[V]) Remove(ctx context.Context, m *Manager) (bool, error)

func (Key[V]) ResetPresentation

func (k Key[V]) ResetPresentation(ctx context.Context, m *Manager) error

ResetPresentation restores the declared presentation and returns its ownership to the declaration, so Ensure and Reconcile keep it current.

func (Key[V]) Set

func (k Key[V]) Set(ctx context.Context, m *Manager, input V) error

func (Key[V]) SetIn

func (k Key[V]) SetIn(ctx context.Context, tx *database.Tx, m *Manager, input V) error

func (Key[V]) Upsert

func (k Key[V]) Upsert(ctx context.Context, m *Manager, input V) error

Upsert atomically creates or replaces the value/version. Existing presentation is preserved; Configure changes presentation explicitly.

func (Key[V]) UpsertIn

func (k Key[V]) UpsertIn(ctx context.Context, tx *database.Tx, m *Manager, input V) error

func (Key[V]) Validate

func (k Key[V]) Validate() error

func (Key[V]) Version

func (k Key[V]) Version() Version

type Kind

type Kind string
const (
	Text          Kind = "text"
	Textarea      Kind = "textarea"
	Number        Kind = "number"
	Boolean       Kind = "boolean"
	Select        Kind = "select"
	Multiselect   Kind = "multiselect"
	Email         Kind = "email"
	URL           Kind = "url"
	Color         Kind = "color"
	Date          Kind = "date"
	Datetime      Kind = "datetime"
	File          Kind = "file"
	Image         Kind = "image"
	JSON          Kind = "json"
	Password      Kind = "password"
	Code          Kind = "code"
	MaxKeys            = 1000
	MaxValueBytes      = extensionvalue.MaxBytes
	MaxBatchBytes      = extensionvalue.MaxBatchBytes
)

func (Kind) Validate

func (k Kind) Validate() error

type Manager

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

Manager borrows the extension Store, which owns admission and shutdown. Its optional read cache is owned by this manager instance only.

func New

func New(store *extensions.Store, keys ...Registration) (*Manager, error)

func (*Manager) Invalidate

func (m *Manager) Invalidate(keys ...Selection) error

Invalidate drops cached reads for the given keys in this manager. Writes made through the manager do this automatically; call it after changing a setting by other means, such as a migration or another process's notification.

func (*Manager) Validate

func (m *Manager) Validate() error

type Name

type Name string

type Options

type Options[V any] struct {
	Cache    time.Duration
	Upgrades []Upgrade[V]
}

Options adds optional registration behavior. The zero value is Registration().

Cache enables the manager's per-process read cache for this key: Get, GetOr, Find and Load serve a validated snapshot for at most Cache, then read again. Writes through the same manager invalidate the entry immediately and again after commit. Other processes observe a write after at most Cache. Zero disables caching; the maximum is MaxCacheTTL.

Upgrades declare conversions for values stored by earlier versions.

type Page

type Page struct {
	Records []Record
	Next    Cursor
}

Page is one bounded ListPage result. Next is zero after the last page.

func ListPage

func ListPage(ctx context.Context, m *Manager, filter Filter, after Cursor, limit int) (Page, error)

ListPage returns up to limit registered settings (DefaultPageSize when zero, at most MaxKeys) ordered by group, sort order and name, after the cursor. A page also ends early rather than retain more than MaxBatchBytes of JSON, so large settings never make the listing fail; continue with Page.Next. Each page is one bounded query in its own read snapshot.

type Presentation

type Presentation struct {
	Kind        Kind
	Group       Group
	Label       string
	Description string
	Order       int32
	Public      bool
	Parameters  value.JSON[json.RawMessage]
}

Presentation describes an administrative form. Password is only a masked widget; settings storage does not encrypt values. Parameters are explicitly dynamic JSON object data for the application's chosen widget.

func (Presentation) Validate

func (p Presentation) Validate() error

type Reconciliation

type Reconciliation struct {
	// Upgraded values were rewritten from an earlier version by a declared upgrade.
	Upgraded []Name
	// Presented presentations still owned by their declaration were refreshed.
	Presented []Name
	// Incompatible rows have a newer version, or an older version without a
	// declared upgrade. Their presence fails Reconcile without any write.
	Incompatible []Name
}

Reconciliation reports what Reconcile changed, or which stored settings it could not accept. Names are registered setting names only, never values.

func Reconcile

func Reconcile(ctx context.Context, m *Manager) (Reconciliation, error)

Reconcile brings stored settings in line with their registrations in one transaction: declared upgrades are applied and declaration-owned presentations are refreshed. Run it after migrations whenever a deployment changes setting versions or presentation, for example while starting serve and worker processes, and treat an error as a startup failure. An incompatible version fails with fault.Conflict, lists the settings in Incompatible and writes nothing, instead of letting every later Get fail. It reads presentation columns first and loads one value at a time for upgrades.

type Record

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

Record's explicit dynamic export prevents accidental serialization of a private setting when an administrative record is logged or returned by HTTP.

func List

func List(ctx context.Context, m *Manager, filter Filter) ([]Record, error)

List returns this manager's registered settings ordered by group, sort order and name by reading consecutive ListPage pages; pages are separate snapshots. Prefix is a literal string, not SQL LIKE syntax. PublicOnly is explicit; callers still own endpoint authorization. The complete result retains at most MaxLoadBytes of JSON; use ListPage for larger administrative listings.

func (Record) Configured

func (r Record) Configured() bool

Configured reports whether Configure took ownership of the presentation, so declaration changes no longer replace it.

func (Record) CreatedAt

func (r Record) CreatedAt() temporal.DateTime

func (Record) DynamicValue

func (r Record) DynamicValue() (json.RawMessage, error)

func (Record) Format

func (Record) Format(s fmt.State, _ rune)

func (Record) MarshalJSON

func (Record) MarshalJSON() ([]byte, error)

func (Record) Name

func (r Record) Name() Name

func (Record) Presentation

func (r Record) Presentation() Presentation

func (Record) UpdatedAt

func (r Record) UpdatedAt() temporal.DateTime

func (Record) Version

func (r Record) Version() Version

type Registration

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

type Selection

type Selection interface {
	// contains filtered or unexported methods
}

Selection names one registered key for a batched read. Key implements it; the declaration identity, not a lookalike name, selects the stored row.

type Upgrade

type Upgrade[V any] struct {
	// contains filtered or unexported fields
}

Upgrade converts a value persisted by an earlier declaration version. It is declared next to the key and applied by reads and by Reconcile.

func UpgradeFrom

func UpgradeFrom[Old, V any](from Version, previous contract.JSON[Old], convert func(context.Context, Old) (V, error)) Upgrade[V]

UpgradeFrom decodes a stored value of an earlier version with that version's codec, then converts it. The result is re-encoded and validated by the current codec. convert is application code: it must be deterministic and must not perform I/O; panics are contained and reported as failures.

type Version

type Version uint32

Jump to

Keyboard shortcuts

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