79 lines
1.6 KiB
Go
79 lines
1.6 KiB
Go
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
|
|
}
|