proxy-pool/internal/config/store.go

68 lines
1.5 KiB
Go

package config
import (
"errors"
"sync/atomic"
)
var ErrInvalidStore = errors.New("invalid configuration store")
// Store publishes complete validated configurations with one atomic pointer swap.
type Store struct {
current atomic.Pointer[publishedConfiguration]
}
type publishedConfiguration struct {
value Config
revision uint64
}
func NewStore(initial *Config) (*Store, error) {
if err := Validate(initial); err != nil {
return nil, errors.Join(ErrInvalidStore, err)
}
store := &Store{}
store.current.Store(&publishedConfiguration{value: cloneConfig(*initial)})
return store, nil
}
func (store *Store) Current() *Config {
if store == nil {
return nil
}
published := store.current.Load()
if published == nil {
return nil
}
cloned := cloneConfig(published.value)
return &cloned
}
func (store *Store) Revision() uint64 {
if store == nil {
return 0
}
published := store.current.Load()
if published == nil {
return 0
}
return published.revision
}
// PublishRevision publishes only a strictly newer authoritative revision.
func (store *Store) PublishRevision(configuration *Config, revision uint64) bool {
if store == nil || configuration == nil || revision == 0 {
return false
}
for {
current := store.current.Load()
if current != nil && revision <= current.revision {
return false
}
next := &publishedConfiguration{value: cloneConfig(*configuration), revision: revision}
if store.current.CompareAndSwap(current, next) {
return true
}
}
}