[#1549] shard: Turn to ModeDegraded on metabase failure

Make `Shard` to work in degraded mode if metabase is unavailable on
opening/init stage. Close metabase in non-degraded mode only.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
Leonard Lyubich 2022-06-27 11:06:01 +03:00 committed by Evgenii Stratonikov
parent 1684cd63fa
commit 263497a92b

View file

@ -12,10 +12,25 @@ import (
"go.uber.org/zap" "go.uber.org/zap"
) )
func (s *Shard) handleMetabaseFailure(stage string, err error) error {
s.log.Error("metabase failure, switching mode",
zap.String("stage", stage),
zap.Stringer("mode", ModeDegraded),
zap.Error(err),
)
err = s.SetMode(ModeDegraded)
if err != nil {
return fmt.Errorf("could not switch to mode %s", ModeDegraded)
}
return nil
}
// Open opens all Shard's components. // Open opens all Shard's components.
func (s *Shard) Open() error { func (s *Shard) Open() error {
components := []interface{ Open() error }{ components := []interface{ Open() error }{
s.blobStor, s.metaBase, s.pilorama, s.blobStor, s.pilorama,
} }
if s.hasWriteCache() { if s.hasWriteCache() {
@ -24,32 +39,67 @@ func (s *Shard) Open() error {
for _, component := range components { for _, component := range components {
if err := component.Open(); err != nil { if err := component.Open(); err != nil {
if component == s.metaBase {
err = s.handleMetabaseFailure("open", err)
if err != nil {
return err
}
continue
}
return fmt.Errorf("could not open %T: %w", component, err) return fmt.Errorf("could not open %T: %w", component, err)
} }
} }
return nil return nil
} }
type metabaseSynchronizer Shard
func (x *metabaseSynchronizer) Init() error {
return (*Shard)(x).refillMetabase()
}
// Init initializes all Shard's components. // Init initializes all Shard's components.
func (s *Shard) Init() error { func (s *Shard) Init() error {
var fMetabase func() error type initializer interface {
Init() error
if s.needRefillMetabase() {
fMetabase = s.refillMetabase
} else {
fMetabase = s.metaBase.Init
} }
components := []func() error{ var components []initializer
s.blobStor.Init, fMetabase, s.pilorama.Init,
if s.GetMode() != ModeDegraded {
var initMetabase initializer
if s.needRefillMetabase() {
initMetabase = (*metabaseSynchronizer)(s)
} else {
initMetabase = s.metaBase
}
components = []initializer{
s.blobStor, initMetabase, s.pilorama,
}
} else {
components = []initializer{s.blobStor, s.pilorama}
} }
if s.hasWriteCache() { if s.hasWriteCache() {
components = append(components, s.writeCache.Init) components = append(components, s.writeCache)
} }
for _, component := range components { for _, component := range components {
if err := component(); err != nil { if err := component.Init(); err != nil {
if component == s.metaBase {
err = s.handleMetabaseFailure("init", err)
if err != nil {
return err
}
continue
}
return fmt.Errorf("could not initialize %T: %w", component, err) return fmt.Errorf("could not initialize %T: %w", component, err)
} }
} }
@ -154,7 +204,11 @@ func (s *Shard) Close() error {
components = append(components, s.writeCache) components = append(components, s.writeCache)
} }
components = append(components, s.pilorama, s.blobStor, s.metaBase) components = append(components, s.pilorama, s.blobStor)
if s.GetMode() != ModeDegraded {
components = append(components, s.metaBase)
}
for _, component := range components { for _, component := range components {
if err := component.Close(); err != nil { if err := component.Close(); err != nil {