From 546a3f11020173859d877283ed48610d3836477f Mon Sep 17 00:00:00 2001 From: Igor Anic Date: Tue, 9 Nov 2021 18:08:48 +0100 Subject: [PATCH] add event for each watch cycle and summary --- cli/controller/watch.go | 109 ++++++++++++++++++++++++++-------------- cli/log/log.go | 9 +++- domain/event.go | 19 +++++++ 3 files changed, 97 insertions(+), 40 deletions(-) diff --git a/cli/controller/watch.go b/cli/controller/watch.go index 71132faa..d8493b9a 100644 --- a/cli/controller/watch.go +++ b/cli/controller/watch.go @@ -9,6 +9,7 @@ import ( "github.com/mantil-io/mantil/cli/log" "github.com/mantil-io/mantil/cli/ui" + "github.com/mantil-io/mantil/domain" "github.com/radovskyb/watcher" ) @@ -29,80 +30,110 @@ func Watch(a WatchArgs) error { if err != nil { return log.Wrap(err) } - var invoke func() error + w := watch{ + deploy: func() (bool, error) { + if err := deploy.Deploy(); err != nil { + return false, err + } + return deploy.HasUpdates(), nil + }, + } + if a.Method != "" { - invoke = stageInvokeCallback(stage, a.Method, a.Data, true, buildShowResponseHandler(false)) + w.invoke = stageInvokeCallback(stage, a.Method, a.Data, true, buildShowResponseHandler(false)) } - var test func() error if a.Test { - test = func() error { + w.test = func() error { return runTests(fs.ProjectRoot(), stage.Endpoints.Rest, "") } } - return runWatch(fs.ProjectRoot(), deploy, invoke, test) + + return w.run(fs.ProjectRoot()) } -func runWatch(path string, deploy *Deploy, invoke, test func() error) error { - onChange := func() { - ui.Info("") - ui.Info("==> Changes detected") - if err := deploy.Deploy(); err != nil { +type watch struct { + deploy func() (bool, error) + invoke func() error + test func() error + cycles int +} + +func (w *watch) onChange() { + w.cycles++ + var hasUpdates bool + var err error + tmr := timerFn() + defer func() { + log.Event(domain.Event{WatchCycle: &domain.WatchCycle{ + Duration: tmr(), + CycleNo: w.cycles, + HasUpdates: hasUpdates, + Invoke: w.invoke != nil, + Test: w.test != nil, + }}) + _ = log.SendEvents() + }() + + ui.Info("") + ui.Info("==> Changes detected") + hasUpdates, err = w.deploy() + if err != nil { + ui.Error(err) + return + } + if !hasUpdates { + return + } + ui.Info("") + if w.invoke != nil { + ui.Info("==> Invoking function") + if err = w.invoke(); err != nil { ui.Error(err) - return - } - if !deploy.HasUpdates() { - return } + } + if w.test != nil { ui.Info("") - if invoke != nil { - ui.Info("==> Invoking function") - if err := invoke(); err != nil { - ui.Error(err) - } - } - if test != nil { - ui.Info("") - ui.Info("==> Running tests") - if err := test(); err != nil { - ui.Error(err) - } + ui.Info("==> Running tests") + if err = w.test(); err != nil { + ui.Error(err) } } - return runWatcher(onChange, path) } -func runWatcher(onChange func(), path string) error { - w := watcher.New() - w.SetMaxEvents(1) - w.FilterOps(watcher.Write, watcher.Create, watcher.Remove) +func (w *watch) run(path string) error { + wr := watcher.New() + wr.SetMaxEvents(1) + wr.FilterOps(watcher.Write, watcher.Create, watcher.Remove) // only watch for changes in go files r := regexp.MustCompile(`\.go$`) - w.AddFilterHook(watcher.RegexFilterHook(r, false)) + wr.AddFilterHook(watcher.RegexFilterHook(r, false)) ctrlc := make(chan os.Signal, 1) signal.Notify(ctrlc, syscall.SIGINT) go func() { for { select { - case <-w.Event: - onChange() - case err := <-w.Error: + case <-wr.Event: + w.onChange() + case err := <-wr.Error: ui.Error(err) - case <-w.Closed: + case <-wr.Closed: return case <-ctrlc: - w.Close() + wr.Close() } } }() - if err := w.AddRecursive(path); err != nil { + if err := wr.AddRecursive(path); err != nil { return log.Wrap(err) } ui.Info("Watching Go files in %s", path) - if err := w.Start(1 * time.Second); err != nil { + if err := wr.Start(1 * time.Second); err != nil { return log.Wrap(err) } + + log.Event(domain.Event{WatchDone: &domain.WatchDone{Cycles: w.cycles}}) return nil } diff --git a/cli/log/log.go b/cli/log/log.go index fddf842c..bc8850ec 100644 --- a/cli/log/log.go +++ b/cli/log/log.go @@ -48,7 +48,7 @@ func startEventCollector() { eventPublisher = make(chan func([]byte) error, 1) go func() { p, err := net.NewPublisher(secret.EventPublisherCreds) - defer close(eventPublisher) + //defer close(eventPublisher) if err != nil { Error(err) return @@ -100,6 +100,7 @@ func sendEvents() error { if ep == nil { return fmt.Errorf("publisher not found") } + eventPublisher <- ep if err := ep(buf); err != nil { return Wrap(err) } @@ -110,6 +111,12 @@ func Event(e domain.Event) { cliCommand.Add(e) } +func SendEvents() error { + err := sendEvents() + cliCommand.Clear() + return err +} + func Printf(format string, v ...interface{}) { if logFile == nil { return diff --git a/domain/event.go b/domain/event.go index 001816a1..7a4a8d3d 100644 --- a/domain/event.go +++ b/domain/event.go @@ -92,6 +92,11 @@ func (c *CliCommand) AddError(e CliError) { c.Errors = append(c.Errors, e) } +func (c *CliCommand) Clear() { + c.Events = make([]Event, 0) + c.Errors = make([]CliError, 0) +} + // placeholder for all events // only one attribute is not nil type Event struct { @@ -102,6 +107,8 @@ type Event struct { NodeCreate *NodeEvent `short:"nc,omitempty" json:"nodeCreate,omitempty"` NodeDelete *NodeEvent `short:"nd,omitempty" json:"nodeDelete,omitempty"` ProjectNew *ProjectNew `short:"n,omitempty" json:"projectNew,omitempty"` + WatchCycle *WatchCycle `short:"wc,omitempty" json:"watchCycle,omitempty"` + WatchDone *WatchDone `short:"wd,omitempty" json:"watchDone,omitempty"` } type GoBuild struct { @@ -141,6 +148,18 @@ type ProjectNew struct { Repo string `short:"r,omitempty" json:"repo,omitempty"` } +type WatchDone struct { + Cycles int `short:"c,omitempty" json:"cycles,omitempty"` +} + +type WatchCycle struct { + Duration int `short:"d,omitempty" json:"duration,omitempty"` + CycleNo int `short:"c,omitempty" json:"cycleNo,omitempty"` + HasUpdates bool `short:"b,omitempty" json:"hasUpdates,omitempty"` + Invoke bool `short:"i,omitempty" json:"invoke,omitempty"` + Test bool `short:"t,omitempty" json:"test,omitempty"` +} + const ( AWSCredentialsByArguments = 1 AWSCredentialsByEnv = 2