dendrite/setup/process/process.go
2022-10-04 13:02:41 +01:00

73 lines
1.6 KiB
Go

package process
import (
"context"
"sync"
"github.com/getsentry/sentry-go"
"github.com/sirupsen/logrus"
)
type ProcessContext struct {
mu sync.RWMutex
wg *sync.WaitGroup // used to wait for components to shutdown
ctx context.Context // cancelled when Stop is called
shutdown context.CancelFunc // shut down Dendrite
degraded map[string]struct{} // reasons why the process is degraded
}
func NewProcessContext() *ProcessContext {
ctx, shutdown := context.WithCancel(context.Background())
return &ProcessContext{
ctx: ctx,
shutdown: shutdown,
wg: &sync.WaitGroup{},
}
}
func (b *ProcessContext) Context() context.Context {
return context.WithValue(b.ctx, "scope", "process") // nolint:staticcheck
}
func (b *ProcessContext) ComponentStarted() {
b.wg.Add(1)
}
func (b *ProcessContext) ComponentFinished() {
b.wg.Done()
}
func (b *ProcessContext) ShutdownDendrite() {
b.shutdown()
}
func (b *ProcessContext) WaitForShutdown() <-chan struct{} {
return b.ctx.Done()
}
func (b *ProcessContext) WaitForComponentsToFinish() {
b.wg.Wait()
}
func (b *ProcessContext) Degraded(err error) {
b.mu.Lock()
defer b.mu.Unlock()
if _, ok := b.degraded[err.Error()]; !ok {
logrus.WithError(err).Warn("Dendrite has entered a degraded state")
sentry.CaptureException(err)
b.degraded[err.Error()] = struct{}{}
}
}
func (b *ProcessContext) IsDegraded() (bool, []string) {
b.mu.RLock()
defer b.mu.RUnlock()
if len(b.degraded) == 0 {
return false, nil
}
reasons := make([]string, 0, len(b.degraded))
for reason := range b.degraded {
reasons = append(reasons, reason)
}
return true, reasons
}