From 54a5e7d4aa122944548c35023d8240209a163423 Mon Sep 17 00:00:00 2001 From: Guillaume Lours <705411+glours@users.noreply.github.com> Date: Mon, 17 Jun 2024 10:59:57 +0200 Subject: [PATCH] stop watch process when associated up process is stopped Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com> --- cmd/formatter/shortcut.go | 11 ++++++----- pkg/compose/up.go | 8 ++++---- pkg/compose/watch.go | 21 +++++++++++++++++---- pkg/compose/watch_test.go | 2 +- 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/cmd/formatter/shortcut.go b/cmd/formatter/shortcut.go index 1f8974b7d..0c78d3e8e 100644 --- a/cmd/formatter/shortcut.go +++ b/cmd/formatter/shortcut.go @@ -73,7 +73,7 @@ func (ke *KeyboardError) error() string { type KeyboardWatch struct { Watcher watch.Notify Watching bool - WatchFn func(ctx context.Context, project *types.Project, services []string, options api.WatchOptions) error + WatchFn func(ctx context.Context, doneCh chan bool, project *types.Project, services []string, options api.WatchOptions) error Ctx context.Context Cancel context.CancelFunc } @@ -117,6 +117,7 @@ var eg multierror.Group func NewKeyboardManager(ctx context.Context, isDockerDesktopActive, isWatchConfigured, isDockerDesktopConfigActive bool, sc chan<- os.Signal, watchFn func(ctx context.Context, + doneCh chan bool, project *types.Project, services []string, options api.WatchOptions, @@ -272,7 +273,7 @@ func (lk *LogKeyboard) keyboardError(prefix string, err error) { }() } -func (lk *LogKeyboard) StartWatch(ctx context.Context, project *types.Project, options api.UpOptions) { +func (lk *LogKeyboard) StartWatch(ctx context.Context, doneCh chan bool, project *types.Project, options api.UpOptions) { if !lk.IsWatchConfigured { eg.Go(tracing.EventWrapFuncForErrGroup(ctx, "menu/watch", tracing.SpanOptions{}, func(ctx context.Context) error { @@ -297,7 +298,7 @@ func (lk *LogKeyboard) StartWatch(ctx context.Context, project *types.Project, o lk.Watch.newContext(ctx) buildOpts := *options.Create.Build buildOpts.Quiet = true - return lk.Watch.WatchFn(lk.Watch.Ctx, project, options.Start.Services, api.WatchOptions{ + return lk.Watch.WatchFn(lk.Watch.Ctx, doneCh, project, options.Start.Services, api.WatchOptions{ Build: &buildOpts, LogTo: options.Start.Attach, }) @@ -305,12 +306,12 @@ func (lk *LogKeyboard) StartWatch(ctx context.Context, project *types.Project, o } } -func (lk *LogKeyboard) HandleKeyEvents(event keyboard.KeyEvent, ctx context.Context, project *types.Project, options api.UpOptions) { +func (lk *LogKeyboard) HandleKeyEvents(event keyboard.KeyEvent, ctx context.Context, doneCh chan bool, project *types.Project, options api.UpOptions) { switch kRune := event.Rune; kRune { case 'v': lk.openDockerDesktop(ctx, project) case 'w': - lk.StartWatch(ctx, project, options) + lk.StartWatch(ctx, doneCh, project, options) case 'o': lk.openDDComposeUI(ctx, project) } diff --git a/pkg/compose/up.go b/pkg/compose/up.go index 494b86154..1f7827a1e 100644 --- a/pkg/compose/up.go +++ b/pkg/compose/up.go @@ -101,9 +101,9 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options isDockerDesktopComposeUI := s.isDesktopUIEnabled() tracing.KeyboardMetrics(ctx, options.Start.NavigationMenu, isDockerDesktopActive, isWatchConfigured, isDockerDesktopComposeUI) - formatter.NewKeyboardManager(ctx, isDockerDesktopActive, isWatchConfigured, isDockerDesktopComposeUI, signalChan, s.Watch) + formatter.NewKeyboardManager(ctx, isDockerDesktopActive, isWatchConfigured, isDockerDesktopComposeUI, signalChan, s.watch) if options.Start.Watch { - formatter.KeyboardManager.StartWatch(ctx, project, options) + formatter.KeyboardManager.StartWatch(ctx, doneCh, project, options) } } } @@ -136,7 +136,7 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options }) return nil case event := <-kEvents: - formatter.KeyboardManager.HandleKeyEvents(event, ctx, project, options) + formatter.KeyboardManager.HandleKeyEvents(event, ctx, doneCh, project, options) } } }) @@ -160,7 +160,7 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options eg.Go(func() error { buildOpts := *options.Create.Build buildOpts.Quiet = true - return s.Watch(ctx, project, options.Start.Services, api.WatchOptions{ + return s.watch(ctx, doneCh, project, options.Start.Services, api.WatchOptions{ Build: &buildOpts, LogTo: options.Start.Attach, }) diff --git a/pkg/compose/watch.go b/pkg/compose/watch.go index 3654e5e7c..26ba98faf 100644 --- a/pkg/compose/watch.go +++ b/pkg/compose/watch.go @@ -77,7 +77,10 @@ func (s *composeService) shouldWatch(project *types.Project) bool { return shouldWatch } -func (s *composeService) Watch(ctx context.Context, project *types.Project, services []string, options api.WatchOptions) error { //nolint: gocyclo +func (s *composeService) Watch(ctx context.Context, project *types.Project, services []string, options api.WatchOptions) error { + return s.watch(ctx, nil, project, services, options) +} +func (s *composeService) watch(ctx context.Context, syncChannel chan bool, project *types.Project, services []string, options api.WatchOptions) error { //nolint: gocyclo var err error if project, err = project.WithSelectedServices(services); err != nil { return err @@ -172,7 +175,7 @@ func (s *composeService) Watch(ctx context.Context, project *types.Project, serv watching = true eg.Go(func() error { defer watcher.Close() //nolint:errcheck - return s.watch(ctx, project, service.Name, options, watcher, syncer, config.Watch) + return s.watchEvents(ctx, project, service.Name, options, watcher, syncer, config.Watch) }) } if !watching { @@ -180,10 +183,20 @@ func (s *composeService) Watch(ctx context.Context, project *types.Project, serv } options.LogTo.Log(api.WatchLogger, "Watch enabled") - return eg.Wait() + err = eg.Wait() + for { + select { + case <-ctx.Done(): + return err + case <-syncChannel: + options.LogTo.Log(api.WatchLogger, "Watch disabled") + ctx.Done() + return err + } + } } -func (s *composeService) watch(ctx context.Context, project *types.Project, name string, options api.WatchOptions, watcher watch.Notify, syncer sync.Syncer, triggers []types.Trigger) error { +func (s *composeService) watchEvents(ctx context.Context, project *types.Project, name string, options api.WatchOptions, watcher watch.Notify, syncer sync.Syncer, triggers []types.Trigger) error { ctx, cancel := context.WithCancel(ctx) defer cancel() diff --git a/pkg/compose/watch_test.go b/pkg/compose/watch_test.go index 39fbf2bcb..28d5c85ff 100644 --- a/pkg/compose/watch_test.go +++ b/pkg/compose/watch_test.go @@ -144,7 +144,7 @@ func TestWatch_Sync(t *testing.T) { dockerCli: cli, clock: clock, } - err := service.watch(ctx, &proj, "test", api.WatchOptions{ + err := service.watchEvents(ctx, &proj, "test", api.WatchOptions{ Build: &api.BuildOptions{}, LogTo: stdLogger{}, }, watcher, syncer, []types.Trigger{