| 344 | } |
| 345 | |
| 346 | func (s *composeService) watchEvents(ctx context.Context, project *types.Project, options api.WatchOptions, watcher watch.Notify, syncer sync.Syncer, rules []watchRule) error { |
| 347 | ctx, cancel := context.WithCancel(ctx) |
| 348 | defer cancel() |
| 349 | |
| 350 | // debounce and group filesystem events so that we capture IDE saving many files as one "batch" event |
| 351 | batchEvents := watch.BatchDebounceEvents(ctx, s.clock, watcher.Events()) |
| 352 | |
| 353 | for { |
| 354 | select { |
| 355 | case <-ctx.Done(): |
| 356 | options.LogTo.Log(api.WatchLogger, "Watch disabled") |
| 357 | // Ensure watcher is closed to release resources |
| 358 | _ = watcher.Close() |
| 359 | return nil |
| 360 | case err, open := <-watcher.Errors(): |
| 361 | if err != nil { |
| 362 | options.LogTo.Err(api.WatchLogger, "Watch disabled with errors: "+err.Error()) |
| 363 | } |
| 364 | if open { |
| 365 | continue |
| 366 | } |
| 367 | _ = watcher.Close() |
| 368 | return err |
| 369 | case batch, ok := <-batchEvents: |
| 370 | if !ok { |
| 371 | options.LogTo.Log(api.WatchLogger, "Watch disabled") |
| 372 | _ = watcher.Close() |
| 373 | return nil |
| 374 | } |
| 375 | if len(batch) > 1000 { |
| 376 | logrus.Warnf("Very large batch of file changes detected: %d files. This may impact performance.", len(batch)) |
| 377 | options.LogTo.Log(api.WatchLogger, "Large batch of file changes detected. If you just switched branches, this is expected.") |
| 378 | } |
| 379 | start := time.Now() |
| 380 | logrus.Debugf("batch start: count[%d]", len(batch)) |
| 381 | err := s.handleWatchBatch(ctx, project, options, batch, rules, syncer) |
| 382 | if err != nil { |
| 383 | logrus.Warnf("Error handling changed files: %v", err) |
| 384 | // If context was canceled, exit immediately |
| 385 | if ctx.Err() != nil { |
| 386 | _ = watcher.Close() |
| 387 | return ctx.Err() |
| 388 | } |
| 389 | } |
| 390 | logrus.Debugf("batch complete: duration[%s] count[%d]", time.Since(start), len(batch)) |
| 391 | } |
| 392 | } |
| 393 | } |
| 394 | |
| 395 | func loadDevelopmentConfig(service types.ServiceConfig, project *types.Project) (*types.DevelopConfig, error) { |
| 396 | var config types.DevelopConfig |