From 40b39e093ce6af33e82801c1edd7f64faa5ceee7 Mon Sep 17 00:00:00 2001 From: Bernhard Guillon Date: Mon, 6 Jul 2026 22:24:18 +0200 Subject: Fix event debouncing: merge ops instead of overwriting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - touch fires CREATE then CHMOD, the CHMOD was overwriting CREATE in the debounce map, and CHMOD is not handled, so file was never synced - Now debounce merges event ops (CREATE|CHMOD → treated as CREATE) - Added sync/remove debug logging - Tested in Docker: create, modify, delete all working --- watcher.go | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'watcher.go') diff --git a/watcher.go b/watcher.go index 8c8177e..68a1a1b 100644 --- a/watcher.go +++ b/watcher.go @@ -18,7 +18,8 @@ func watch(ctx context.Context, hostDir, dataDir string, manifest *Manifest, sta defer watcher.Close() var mu sync.Mutex - debounce := make(map[string]*time.Timer) + debounceTimers := make(map[string]*time.Timer) + debounceOps := make(map[string]fsnotify.Op) if err := addWatchersRecursively(watcher, hostDir, stack); err != nil { return err @@ -50,14 +51,20 @@ func watch(ctx context.Context, hostDir, dataDir string, manifest *Manifest, sta logDebug("event: %s %s", event.Op, relPath) mu.Lock() - if t, exists := debounce[relPath]; exists { - t.Stop() + if existing, exists := debounceOps[relPath]; exists { + debounceTimers[relPath].Stop() + debounceOps[relPath] = existing | event.Op + } else { + debounceOps[relPath] = event.Op } - debounce[relPath] = time.AfterFunc(200*time.Millisecond, func() { + path := relPath + debounceTimers[relPath] = time.AfterFunc(200*time.Millisecond, func() { mu.Lock() - delete(debounce, relPath) + op := debounceOps[path] + delete(debounceOps, path) + delete(debounceTimers, path) mu.Unlock() - handleEvent(event.Op, hostDir, dataDir, relPath, manifest, stack, dryRun, watcher) + handleEvent(op, hostDir, dataDir, path, manifest, stack, dryRun, watcher) }) mu.Unlock() -- cgit v1.2.3