Documentation
¶
Overview ¶
Package appconfig keeps a realm's app configuration: the values admins and functions set over the declared defaults, with optimistic concurrency, an audited history and rollback. It knows the declaration (registry.AppConfig) and a Store, and nothing about HTTP.
Index ¶
- Constants
- Variables
- func Flat(values map[string]any) map[string]any
- func FormatVersion(v int64) string
- func ParseVersion(s string) (int64, bool)
- type Change
- type Entry
- type Input
- type InvalidError
- type MemStore
- func (m *MemStore) AppConfigEntry(_ context.Context, version int64) (Entry, error)
- func (m *MemStore) AppConfigHistory(_ context.Context, limit int) ([]Entry, error)
- func (m *MemStore) AppConfigState(_ context.Context) (State, error)
- func (m *MemStore) SaveAppConfig(_ context.Context, expected int64, next State, e Entry, pruneTo int64, ...) error
- type Problem
- type Result
- type Service
- func (s *Service) Apply(ctx context.Context, expected int64, in Input, actor string) (Result, error)
- func (s *Service) Current(ctx context.Context) (View, error)
- func (s *Service) History(ctx context.Context, limit int) ([]Entry, error)
- func (s *Service) Rollback(ctx context.Context, expected, to int64, actor string) (Result, error)
- type State
- type Store
- type View
Constants ¶
const ( HistoryVersions = 100 HistoryAge = 90 * 24 * time.Hour )
History is kept for the last HistoryVersions versions or HistoryAge, whichever is longer.
const ( KindSet = "set" KindRollback = "rollback" )
Kinds of a history entry.
Variables ¶
var ( // ErrConflict: the version the change was based on isn't the current one. ErrConflict = errors.New("the configuration changed since it was read") // ErrNoVersion: the history has no such version (it may have been pruned). ErrNoVersion = errors.New("no such configuration version") )
Functions ¶
func FormatVersion ¶
FormatVersion writes a version in the form the API uses.
func ParseVersion ¶
ParseVersion reads a version in the form the API uses, "c41" or "41".
Types ¶
type Change ¶
Change is one path whose effective value changed; Old and New are effective values, so a path at its default shows the default.
type Entry ¶
type Entry struct {
Version int64
At time.Time
Actor string // "user:<id>", "key:<name>", "function:<db>/<name>", …
Kind string // KindSet or KindRollback
// RolledBackTo is the version a rollback restored.
RolledBackTo int64
Changes []Change
// Values are the stored values after the change: what a rollback to this version restores.
Values map[string]any
}
Entry is one version of the history.
type InvalidError ¶
type InvalidError struct{ Problems []Problem }
InvalidError is a change that doesn't satisfy the declaration; it applied nothing.
func (*InvalidError) Error ¶
func (e *InvalidError) Error() string
type MemStore ¶
type MemStore struct {
// contains filtered or unexported fields
}
MemStore is a Store in memory, for tests and for embedding in other test stores. Its zero value is ready to use.
func (*MemStore) AppConfigEntry ¶
func (*MemStore) AppConfigHistory ¶
func (*MemStore) AppConfigState ¶
type Problem ¶
type Problem struct{ Path, Reason string }
Problem is one path that can't take a value, and why.
type Result ¶
type Result struct {
Version int64
// Changed is false when the change left every value as it was; no version is made then.
Changed bool
Changes []Change
}
Result is what a change did.
type Service ¶
type Service struct {
Store Store
Config *registry.AppConfig
Now func() time.Time // defaults to time.Now
}
Service reads and changes one realm's configuration.
func (*Service) Apply ¶
func (s *Service) Apply(ctx context.Context, expected int64, in Input, actor string) (Result, error)
Apply validates the change as a whole against the declaration and, when it is valid and based on the current version, stores it as a new version.
type State ¶
State is what is stored: the values that differ from the defaults, nested like the configuration, with the version they have.
type Store ¶
type Store interface {
// AppConfigState returns the current state; version 0 with no values when none was saved.
AppConfigState(ctx context.Context) (State, error)
// SaveAppConfig replaces the state with next when the stored version is expected
// (ErrConflict otherwise), records the entry, and removes entries of versions up to
// pruneTo that are older than pruneBefore.
SaveAppConfig(ctx context.Context, expected int64, next State, entry Entry, pruneTo int64, pruneBefore time.Time) error
// AppConfigHistory returns entries, newest first.
AppConfigHistory(ctx context.Context, limit int) ([]Entry, error)
// AppConfigEntry returns one version's entry, or ErrNoVersion.
AppConfigEntry(ctx context.Context, version int64) (Entry, error)
}
Store is where the state and its history live (a realm's system database).
type View ¶
type View struct {
Version int64
// Values is every key with its effective value: the default, or what was set.
Values map[string]any
// Overrides are the values that differ from their defaults, nested.
Overrides map[string]any
// Invalid are stored values that no longer satisfy the declaration (after a
// deploy): they are ignored, so their keys read as defaults, until fixed or reset.
Invalid []Problem
UpdatedAt time.Time
UpdatedBy string
}
View is the configuration as it is now.