package store import "sync" type ScopeState uint8 const ( ScopeRecovering ScopeState = iota + 1 ScopeReady ScopeDirtyReadable ScopeUnavailable ) type ScopeKey struct { Kind string ID string } type ScopeHealth struct { mu sync.RWMutex required map[ScopeKey]bool states map[ScopeKey]ScopeState } func NewScopeHealth(required []ScopeKey) *ScopeHealth { health := &ScopeHealth{required: make(map[ScopeKey]bool, len(required)), states: make(map[ScopeKey]ScopeState, len(required))} for _, scope := range required { health.required[scope] = true health.states[scope] = ScopeRecovering } return health } func (health *ScopeHealth) Set(scope ScopeKey, state ScopeState) bool { if health == nil || scope.Kind == "" || state < ScopeRecovering || state > ScopeUnavailable { return false } health.mu.Lock() defer health.mu.Unlock() health.states[scope] = state return true } func (health *ScopeHealth) State(scope ScopeKey) ScopeState { if health == nil { return ScopeUnavailable } health.mu.RLock() defer health.mu.RUnlock() state := health.states[scope] if state == 0 { return ScopeUnavailable } return state } func (health *ScopeHealth) GloballyReady() bool { if health == nil { return false } health.mu.RLock() defer health.mu.RUnlock() for scope := range health.required { if health.states[scope] != ScopeReady { return false } } return true } func (health *ScopeHealth) ReadAllowed(scope ScopeKey) bool { state := health.State(scope) return state == ScopeReady || state == ScopeDirtyReadable } func (health *ScopeHealth) MutationAllowed(scope ScopeKey) bool { return health.State(scope) == ScopeReady }