Add base setup
This commit is contained in:
121
manager.go
Normal file
121
manager.go
Normal file
@@ -0,0 +1,121 @@
|
||||
package curre
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
OK = 0
|
||||
Internal = 1
|
||||
)
|
||||
|
||||
type Manager struct {
|
||||
components []Component
|
||||
logger Logger
|
||||
startStopLock sync.Mutex
|
||||
started bool
|
||||
exitChan chan int
|
||||
exitCode int
|
||||
lifetime Lifetime
|
||||
}
|
||||
|
||||
func NewManager() *Manager {
|
||||
return &Manager{
|
||||
logger: &DefaultLogger{}, exitChan: make(chan int, 1),
|
||||
exitCode: OK,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Manager) Register(components ...Component) *Manager {
|
||||
if m.started {
|
||||
panic("cannot register to a started manager")
|
||||
}
|
||||
|
||||
m.components = append(m.components, components...)
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *Manager) Init(ctx context.Context) error {
|
||||
if m.started {
|
||||
panic("cannot reinit a started manager")
|
||||
}
|
||||
|
||||
for _, c := range m.components {
|
||||
err := c.Init(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.logger.Info("Manager: Init: %T", c)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Manager) Start(ctx context.Context) error {
|
||||
for _, c := range m.components {
|
||||
go m.startComponent(ctx, c)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Manager) startComponent(ctx context.Context, component Component) {
|
||||
defer func() {
|
||||
err := recover()
|
||||
if err != nil {
|
||||
m.logger.Error("Panic occurred in component: %T, error: %s", component, err)
|
||||
}
|
||||
|
||||
m.exitChan <- Internal
|
||||
}()
|
||||
|
||||
m.logger.Info("Starting %T", component)
|
||||
err := component.Start(ctx)
|
||||
if err != nil {
|
||||
m.logger.Error("Component: %T encountered an error: ", component, err)
|
||||
m.exitChan <- Internal
|
||||
return
|
||||
}
|
||||
|
||||
m.logger.Info("Component %T, done running", component)
|
||||
|
||||
}
|
||||
|
||||
func (m *Manager) initLifetime() {
|
||||
go func() {
|
||||
exitCode := m.lifetime()
|
||||
m.logger.Info("Exit signal received: %d", exitCode)
|
||||
m.exitChan <- exitCode
|
||||
}()
|
||||
}
|
||||
|
||||
func (m *Manager) Wait(ctx context.Context) error {
|
||||
exitCode := <-m.exitChan
|
||||
m.exitCode = exitCode
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Manager) Shutdown(ctx context.Context) error {
|
||||
shutdownChan := make(chan struct{}, 1)
|
||||
closers := m.getClosers(ctx)
|
||||
|
||||
go func(ctx context.Context) {
|
||||
for _, c := range closers {
|
||||
c.Close(ctx)
|
||||
}
|
||||
|
||||
shutdownChan <- struct{}{}
|
||||
}(ctx)
|
||||
|
||||
<-shutdownChan
|
||||
m.logger.Info("Shutting down of components complete")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Manager) getClosers(ctx context.Context) []Component {
|
||||
return m.components
|
||||
}
|
Reference in New Issue
Block a user