79 lines
1.4 KiB
Go

package agent
import (
"context"
"time"
"github.com/pkg/errors"
"gitlab.com/wpetit/goweb/logger"
)
type Agent struct {
controllers []Controller
interval time.Duration
}
func (a *Agent) Run(ctx context.Context) error {
ticker := time.NewTicker(a.interval)
defer ticker.Stop()
prevState := NewState()
for {
select {
case <-ticker.C:
newState, err := a.Reconcile(ctx, prevState)
if err != nil {
logger.Error(ctx, "could not reconcile node with desired state", logger.E(errors.WithStack(err)))
continue
}
if newState != nil {
prevState = newState
}
case <-ctx.Done():
return errors.WithStack(ctx.Err())
}
}
}
func (a *Agent) Reconcile(ctx context.Context, state *State) (*State, error) {
prevState := state
for _, ctrl := range a.controllers {
ctrlCtx := logger.With(ctx, logger.F("controller", ctrl.Name()))
logger.Debug(
ctrlCtx, "executing controller",
logger.F("state", state),
)
newState, err := ctrl.Reconcile(ctrlCtx, prevState)
if err != nil {
return nil, errors.WithStack(err)
}
logger.Debug(ctrlCtx, "new state", logger.F("newState", newState))
if newState != nil {
prevState = newState
}
}
return prevState, nil
}
func New(funcs ...OptionFunc) *Agent {
opt := defaultOption()
for _, fn := range funcs {
fn(opt)
}
return &Agent{
controllers: opt.Controllers,
interval: opt.Interval,
}
}