viperguard

package
v1.228.0-test.39 Latest Latest
Warning

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

Go to latest
Published: Sep 5, 2026 License: Apache-2.0 Imports: 4 Imported by: 0

Documentation

Overview

Package viperguard mutex-guards the process-wide global spf13/viper singleton.

spf13/viper has no internal locking of its own: viper.Get*/Set/BindEnv all read or mutate one shared underlying map via deepSearch, and Go maps are not safe for any concurrent read/write access, regardless of which key each goroutine touches -- a BindEnv registering an unrelated key can still race with a concurrent Get of a completely different key. Any code that may run concurrently with other global-viper access (the DAG scheduler's per-node LoadConfig calls, the toolchain's concurrent batch installer, ...) must route through this package's functions instead of calling viper.* directly.

This lives in its own leaf package (no imports of any other Atmos package) specifically so packages low in the dependency graph -- pkg/http and pkg/ui/theme, which pkg/config itself depends on -- can use it without an import cycle. pkg/config.GlobalViper() delegates here rather than keeping a second, independent mutex: two separate locks guarding the same underlying viper singleton would not actually exclude each other, leaving exactly the kind of cross-package race this package exists to close.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BindEnv

func BindEnv(input ...string) error

BindEnv binds a Viper key to one or more environment variable names on the global Viper singleton. See viper.BindEnv for the input argument shape.

func GetBool

func GetBool(key string) bool

GetBool returns key's value coerced to bool. Returns false if unset.

func GetString

func GetString(key string) string

GetString returns key's value coerced to string. Returns "" if unset.

func GetStringSlice

func GetStringSlice(key string) []string

GetStringSlice returns a clone of key's value coerced to []string: viper's own GetStringSlice can return its value's existing backing array rather than a copy, and handing that out under the lock would let a caller mutate shared Viper state after the lock is released. Returns nil if unset.

func IsSet

func IsSet(key string) bool

IsSet reports whether key has a value from any source, including a registered default: viper.IsSet's underlying find() also checks viper.defaults, so a key registered only via SetDefault also reports true here. It cannot distinguish an explicit value (flag, env, config, override) from a default; callers needing that distinction need a separate check.

func Set

func Set(key string, value any)

Set sets key's value on the global Viper singleton.

func View

func View(fn func(v ViperReader))

View executes fn with a read lock held on the global Viper singleton, giving fn a consistent snapshot for the whole call. Use this instead of separate Get*/IsSet calls whenever a decision combines more than one read (e.g. an IsSet presence check followed by a GetBool value read): each individual function in this package locks and unlocks independently, so a concurrent Set() between two separate calls could let the decision combine one snapshot's presence result with a different snapshot's value.

The callback fn must not call Set, BindEnv, or any other guard writer, directly or transitively: mu.RLock is held for the whole call, and those writers block on mu.Lock until fn returns, so fn calling one deadlocks against itself.

Types

type ViperReader

type ViperReader interface {
	// IsSet reports whether key has a value from any source, including a
	// registered default (see the package-level IsSet's doc comment for why).
	IsSet(key string) bool
	// GetBool returns key's value coerced to bool. Returns false if unset.
	GetBool(key string) bool
	// GetString returns key's value coerced to string. Returns "" if unset.
	GetString(key string) string
	// GetStringSlice returns key's value coerced to []string, cloned so the
	// caller cannot mutate Viper's own backing array. Returns nil if unset.
	GetStringSlice(key string) []string
}

ViperReader exposes only *viper.Viper's read methods. View passes this (not *viper.Viper) to its callback, so the callback cannot call a mutator like Set while holding only the read lock -- doing so would race against another concurrent View call's reads, or against Set's write lock, defeating the whole point of View. Extend with more read methods as callers need them; never add a mutator here.

Jump to

Keyboard shortcuts

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