From 19d8bf6923e08bfbd033251ae61ded972eeb67ef Mon Sep 17 00:00:00 2001 From: Teddy Sommavilla Date: Tue, 22 Apr 2025 11:29:31 +0200 Subject: [PATCH 1/6] refactor(fsnotifyext): handle Deduper timers in own goroutine, avoid mutex use --- internal/fsnotifyext/fsnotify_dedup.go | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/internal/fsnotifyext/fsnotify_dedup.go b/internal/fsnotifyext/fsnotify_dedup.go index ef9fa9cb1e..3c26be6673 100644 --- a/internal/fsnotifyext/fsnotify_dedup.go +++ b/internal/fsnotifyext/fsnotify_dedup.go @@ -2,7 +2,6 @@ package fsnotifyext import ( "math" - "sync" "time" "github.com/fsnotify/fsnotify" @@ -11,7 +10,6 @@ import ( type Deduper struct { w *fsnotify.Watcher waitTime time.Duration - mutex sync.Mutex } func NewDeduper(w *fsnotify.Watcher, waitTime time.Duration) *Deduper { @@ -23,9 +21,9 @@ func NewDeduper(w *fsnotify.Watcher, waitTime time.Duration) *Deduper { func (d *Deduper) GetChan() chan fsnotify.Event { channel := make(chan fsnotify.Event) - timers := make(map[string]*time.Timer) go func() { + timers := make(map[string]*time.Timer) for { event, ok := <-d.w.Events switch { @@ -35,17 +33,11 @@ func (d *Deduper) GetChan() chan fsnotify.Event { continue } - d.mutex.Lock() timer, ok := timers[event.String()] - d.mutex.Unlock() - if !ok { timer = time.AfterFunc(math.MaxInt64, func() { channel <- event }) timer.Stop() - - d.mutex.Lock() timers[event.String()] = timer - d.mutex.Unlock() } timer.Reset(d.waitTime) From a37d8f0956fde1785daea27b846c3bc8a52731e0 Mon Sep 17 00:00:00 2001 From: Teddy Sommavilla Date: Tue, 22 Apr 2025 11:29:58 +0200 Subject: [PATCH 2/6] refactor(fsnotifyext): GetChan should return a receive only chan --- internal/fsnotifyext/fsnotify_dedup.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/fsnotifyext/fsnotify_dedup.go b/internal/fsnotifyext/fsnotify_dedup.go index 3c26be6673..384ef42be7 100644 --- a/internal/fsnotifyext/fsnotify_dedup.go +++ b/internal/fsnotifyext/fsnotify_dedup.go @@ -19,7 +19,7 @@ func NewDeduper(w *fsnotify.Watcher, waitTime time.Duration) *Deduper { } } -func (d *Deduper) GetChan() chan fsnotify.Event { +func (d *Deduper) GetChan() <-chan fsnotify.Event { channel := make(chan fsnotify.Event) go func() { From 126d8a78442a7beb3a35d8e0b1a8c497b09b3157 Mon Sep 17 00:00:00 2001 From: Teddy Sommavilla Date: Tue, 22 Apr 2025 11:39:02 +0200 Subject: [PATCH 3/6] doc(fsnotifyext): add godoc for GetChan method --- internal/fsnotifyext/fsnotify_dedup.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/internal/fsnotifyext/fsnotify_dedup.go b/internal/fsnotifyext/fsnotify_dedup.go index 384ef42be7..def9b6c787 100644 --- a/internal/fsnotifyext/fsnotify_dedup.go +++ b/internal/fsnotifyext/fsnotify_dedup.go @@ -19,6 +19,9 @@ func NewDeduper(w *fsnotify.Watcher, waitTime time.Duration) *Deduper { } } +// GetChan returns a chan of deduplicated [fsnotify.Event]. +// +// [fsnotify.Chmod] operations will be skipped. func (d *Deduper) GetChan() <-chan fsnotify.Event { channel := make(chan fsnotify.Event) From 3b862b715e570366fe3518ae809bbd66ac8e2e30 Mon Sep 17 00:00:00 2001 From: Teddy Sommavilla Date: Tue, 22 Apr 2025 11:40:56 +0200 Subject: [PATCH 4/6] refactor(fsnotifyext): use Event.Has to check for chmod operations As recommended by the Event.Op godoc. Op is a bitmask, and some systems may send multiple operations at once --- internal/fsnotifyext/fsnotify_dedup.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/fsnotifyext/fsnotify_dedup.go b/internal/fsnotifyext/fsnotify_dedup.go index def9b6c787..d081842380 100644 --- a/internal/fsnotifyext/fsnotify_dedup.go +++ b/internal/fsnotifyext/fsnotify_dedup.go @@ -32,7 +32,7 @@ func (d *Deduper) GetChan() <-chan fsnotify.Event { switch { case !ok: return - case event.Op == fsnotify.Chmod: + case event.Has(fsnotify.Chmod): continue } From d2a8fcb1227c48b3feeb7e98b9109acb81a55d4a Mon Sep 17 00:00:00 2001 From: Teddy Sommavilla Date: Tue, 22 Apr 2025 11:42:28 +0200 Subject: [PATCH 5/6] refactor: watchTasks - Chmod operations are already filtered in the Deduper --- watch.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/watch.go b/watch.go index 76bab9ae6c..515bde0af9 100644 --- a/watch.go +++ b/watch.go @@ -71,12 +71,9 @@ func (e *Executor) watchTasks(calls ...*Call) error { for { select { case event, ok := <-eventsChan: - switch { - case !ok: + if !ok { cancel() return - case event.Op == fsnotify.Chmod: - continue } e.Logger.VerboseErrf(logger.Magenta, "task: received watch event: %v\n", event) From b5d406cc195a94e52a44b1c15c9ca3496b52d582 Mon Sep 17 00:00:00 2001 From: Teddy Sommavilla Date: Thu, 22 May 2025 21:08:02 +0200 Subject: [PATCH 6/6] chore: go mod tidy --- go.sum | 8 -------- 1 file changed, 8 deletions(-) diff --git a/go.sum b/go.sum index a2e8cb4b2f..ff09ac65a0 100644 --- a/go.sum +++ b/go.sum @@ -11,8 +11,6 @@ github.com/ProtonMail/go-crypto v1.1.6 h1:ZcV+Ropw6Qn0AX9brlQLAUXfqLBc7Bl+f/DmNx github.com/ProtonMail/go-crypto v1.1.6/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= -github.com/alecthomas/chroma/v2 v2.17.0 h1:3r2Cgk+nXNICMBxIFGnTRTbQFUwMiLisW+9uos0TtUI= -github.com/alecthomas/chroma/v2 v2.17.0/go.mod h1:RVX6AvYm4VfYe/zsk7mjHueLDZor3aWCNE14TFlepBk= github.com/alecthomas/chroma/v2 v2.17.2 h1:Rm81SCZ2mPoH+Q8ZCc/9YvzPUN/E7HgPiPJD8SLV6GI= github.com/alecthomas/chroma/v2 v2.17.2/go.mod h1:RVX6AvYm4VfYe/zsk7mjHueLDZor3aWCNE14TFlepBk= github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= @@ -143,8 +141,6 @@ golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbR golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= -golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= -golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -156,13 +152,9 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= -golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o= -golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw= golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=