// Copyright 2022 Terin Stock. // SPDX-License-Identifier: MPL-2.0 package manager import ( "context" "errors" "sync" "golang.org/x/sync/errgroup" ) type Manager struct { mu sync.Mutex started bool runnables []Runnable internalCtx context.Context group *errgroup.Group } func New() *Manager { return &Manager{ runnables: []Runnable{}, } } func (m *Manager) Add(r Runnable) error { m.mu.Lock() defer m.mu.Unlock() if m.started { m.group.Go(func() error { return r.Start(m.internalCtx) }) } else { m.runnables = append(m.runnables, r) } return nil } func (m *Manager) Start(ctx context.Context) error { m.mu.Lock() if m.started { m.mu.Unlock() return errors.New("manager already started") } g, internalCtx := errgroup.WithContext(ctx) m.group = g m.internalCtx = internalCtx for _, r := range m.runnables { r := r g.Go(func() error { return r.Start(internalCtx) }) } m.runnables = nil m.started = true m.mu.Unlock() return g.Wait() } type Runnable interface { Start(ctx context.Context) error }