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 { state := NewState() logger.Info(ctx, "starting reconciliation ticker", logger.F("interval", a.interval)) ticker := time.NewTicker(a.interval) defer ticker.Stop() for { select { case <-ticker.C: logger.Debug(ctx, "state before reconciliation", logger.F("state", state)) if err := a.Reconcile(ctx, state); err != nil { logger.Error(ctx, "could not reconcile node with state", logger.E(errors.WithStack(err))) continue } logger.Debug(ctx, "state after reconciliation", logger.F("state", state)) case <-ctx.Done(): return errors.WithStack(ctx.Err()) } } } func (a *Agent) Reconcile(ctx context.Context, state *State) error { for _, ctrl := range a.controllers { ctrlCtx := logger.With(ctx, logger.F("controller", ctrl.Name())) logger.Debug( ctrlCtx, "executing controller", logger.F("state", state), ) if err := ctrl.Reconcile(ctrlCtx, state); err != nil { return errors.WithStack(err) } } return nil } func New(funcs ...OptionFunc) *Agent { opt := defaultOption() for _, fn := range funcs { fn(opt) } return &Agent{ controllers: opt.Controllers, interval: opt.Interval, } }