Documentation
¶
Overview ¶
Package flags provides browser-visible feature flag and experiment helpers.
The package intentionally evaluates only public, non-secret decisions that are safe to transfer through SSR bootstrap, browser storage, or client state. Server-side policy, entitlement checks, and secret rollout rules remain application-owned.
Index ¶
- type Assignment
- type Experiment
- type ExperimentHandle
- type Flag
- type FlagHandle
- type Registry
- type RemoteFetchFunc
- type RemoteProvider
- func (parseP *RemoteProvider) Age(parseNow time.Time) time.Duration
- func (parseP *RemoteProvider) Current() Set
- func (parseP *RemoteProvider) IsKilled(parseFeature string) bool
- func (parseP *RemoteProvider) IsStale(parseMaxAge time.Duration, parseNow time.Time) bool
- func (parseP *RemoteProvider) LastError() error
- func (parseP *RemoteProvider) Poll(parseCtx context.Context, parseInterval time.Duration, ...) error
- func (parseP *RemoteProvider) Refresh(parseCtx context.Context) error
- func (parseP *RemoteProvider) Subscribe(parseHandler func(Set)) (parseUnsubscribe func())
- type Set
- func (parseSet Set) GetAssignment(parseName string, parseSubject string) Assignment
- func (parseSet Set) GetEnabled(parseName string, parseFallback bool) bool
- func (parseSet Set) GetFlag(parseName string, parseFallback Flag) Flag
- func (parseSet Set) GetValue(parseName string, parseFallback string) string
- type Variant
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Assignment ¶
type Assignment struct {
Experiment string
Variant string
Value string
Enabled bool
Bucket int
Reason string
}
Assignment describes an evaluated experiment outcome.
type Experiment ¶
Experiment describes one deterministic weighted experiment.
type ExperimentHandle ¶
type ExperimentHandle struct {
// contains filtered or unexported fields
}
ExperimentHandle exposes one hook-selected experiment assignment.
func UseExperiment ¶
func UseExperiment(parseName string, parseSubject string) ExperimentHandle
UseExperiment subscribes the current component to one deterministic experiment assignment.
func (ExperimentHandle) Get ¶
func (parseHandle ExperimentHandle) Get() Assignment
Get returns the current experiment assignment.
type FlagHandle ¶
type FlagHandle struct {
// contains filtered or unexported fields
}
FlagHandle exposes one hook-selected flag.
func UseFlag ¶
func UseFlag(parseName string, parseFallback bool) FlagHandle
UseFlag subscribes the current component to one shared feature flag.
func (FlagHandle) Enabled ¶
func (parseHandle FlagHandle) Enabled() bool
Enabled returns whether the current flag is enabled.
func (FlagHandle) Get ¶
func (parseHandle FlagHandle) Get() Flag
Get returns the current flag value.
func (FlagHandle) Value ¶
func (parseHandle FlagHandle) Value(parseFallback string) string
Value returns the current flag value or the fallback when blank.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry exposes the current shared flag set.
func UseRegistry ¶
UseRegistry subscribes the current component to the shared flag registry.
type RemoteFetchFunc ¶
RemoteFetchFunc is the caller-supplied transport hook that retrieves a fresh Set from any source (HTTP poll, SSE stream, file watch, etc.). The package is transport-agnostic; it calls this function and reacts to the result.
type RemoteProvider ¶
type RemoteProvider struct {
// contains filtered or unexported fields
}
RemoteProvider holds a live, mutex-guarded snapshot of a remotely managed flag Set, and notifies subscribers on every successful refresh. A remote payload that sets a flag's Enabled field to false acts as a kill switch: IsKilled returns true and all subscribers are notified without requiring a page reload.
func NewRemoteProvider ¶
func NewRemoteProvider(parseInitial Set, parseFetch RemoteFetchFunc) *RemoteProvider
NewRemoteProvider returns a RemoteProvider seeded with parseInitial as the last-known-good Set. parseFetch supplies updates; it is called once per Refresh and once per Poll interval.
func (*RemoteProvider) Age ¶
func (parseP *RemoteProvider) Age(parseNow time.Time) time.Duration
Age returns the time elapsed since the last successful Refresh, measured relative to parseNow. Inject the same clock you pass to setNow when testing staleness.
func (*RemoteProvider) Current ¶
func (parseP *RemoteProvider) Current() Set
Current returns the current last-known-good Set. It is always valid; even after a failed Refresh it holds the last successfully fetched value.
func (*RemoteProvider) IsKilled ¶
func (parseP *RemoteProvider) IsKilled(parseFeature string) bool
IsKilled reports whether parseFeature is actively killed. A flag is considered killed when the current Set contains it AND its Enabled field is false. A missing flag is not killed — it is simply absent.
Kill-switch pattern: deploy a remote payload with the flag present and Enabled set to false. Components that gate a subtree on IsKilled and react via Subscribe will disable themselves immediately without a reload. Re-enabling the flag (Enabled true) in a subsequent payload un-kills it.
func (*RemoteProvider) IsStale ¶
IsStale reports whether the last successful Refresh is older than parseMaxAge as of parseNow.
func (*RemoteProvider) LastError ¶
func (parseP *RemoteProvider) LastError() error
LastError returns the error from the most recent failed Refresh, or nil if the last Refresh succeeded.
func (*RemoteProvider) Poll ¶
func (parseP *RemoteProvider) Poll( parseCtx context.Context, parseInterval time.Duration, parseSleep func(context.Context, time.Duration) error, ) error
Poll calls Refresh on every parseInterval tick until parseCtx is cancelled. parseSleep is called between iterations; inject a no-op in tests so they run instantly. Errors from individual Refresh calls are recorded in LastError but do not stop the loop (outage resilience). Poll returns parseCtx.Err() when the context is done.
func (*RemoteProvider) Refresh ¶
func (parseP *RemoteProvider) Refresh(parseCtx context.Context) error
Refresh calls the injected fetch function once. On success it replaces the current Set, records the update time, clears the last error, and notifies all subscribers. On failure it preserves the previous Set and last-known-good time, stores the error, and returns it. A failed refresh never clobbers good values.
func (*RemoteProvider) Subscribe ¶
func (parseP *RemoteProvider) Subscribe(parseHandler func(Set)) (parseUnsubscribe func())
Subscribe registers parseHandler to be called after every successful Refresh. It returns an unsubscribe function; calling it removes the handler and is leak-free (the internal registry returns to baseline size). A panicking handler does not interrupt delivery to the remaining ones.
type Set ¶
type Set struct {
Flags map[string]Flag
Experiments map[string]Experiment
}
Set stores browser-visible flags and experiments.
func BuildSet ¶
func BuildSet(parseFlags map[string]Flag, parseExperiments map[string]Experiment) Set
BuildSet builds an immutable copy of flags and experiments.
func ParseRemoteSet ¶
ParseRemoteSet decodes parseRaw from the canonical remote payload shape:
{"flags": {"name": {"enabled": true, "value": "...", "reason": "..."}},
"experiments": {"name": {"enabled": true, "salt": "...", "variants": [...]}}}
A malformed payload returns a descriptive error; the caller should keep the last-known-good Set rather than replacing it. ParseRemoteSet never panics; it is safe to call from any goroutine.
func (Set) GetAssignment ¶
func (parseSet Set) GetAssignment(parseName string, parseSubject string) Assignment
GetAssignment returns a deterministic weighted experiment assignment.
func (Set) GetEnabled ¶
GetEnabled returns whether a named flag is enabled.