added debounce (#11)

This commit is contained in:
davy wybiral 2019-07-03 14:44:31 -05:00 committed by GitHub
parent deb6808c75
commit 6b8d872d68
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 60 additions and 23 deletions

View file

@ -89,32 +89,10 @@ func (a *App) Run() error {
}
a.Watcher.Add(p.Path)
}
go a.watch()
go startWatcher(a)
return http.Serve(a.Listener, a.Router)
}
// Watch the library path and update Library with changes.
func (a *App) watch() {
for {
e, ok := <-a.Watcher.Events
if !ok {
return
}
if e.Op&fsnotify.Create > 0 {
// add new files to library
a.Library.Add(e.Name)
} else if e.Op&(fsnotify.Write|fsnotify.Chmod) > 0 {
// writes and chmods should remove old file before adding again
a.Library.Remove(e.Name)
a.Library.Add(e.Name)
} else if e.Op&(fsnotify.Remove|fsnotify.Rename) > 0 {
// remove and rename just remove file
// fsnotify will signal a Create event with the new file name
a.Library.Remove(e.Name)
}
}
}
// HTTP handler for /
func (a *App) indexHandler(w http.ResponseWriter, r *http.Request) {
log.Printf("/")

59
pkg/app/watcher.go Normal file
View file

@ -0,0 +1,59 @@
package app
import (
"time"
fs "github.com/fsnotify/fsnotify"
)
// This is the amount of time to wait after changes before reacting to them.
// Debounce is done because moving files into the watched directories causes
// many rapid "Write" events to fire which would cause excessive Remove/Add
// method calls on the Library. To avoid this we accumulate the changes and
// only perform them once the events have stopped for this amount of time.
const debounceTimeout = time.Second * 5
// create, write, and chmod all require an add event
const addFlags = fs.Create | fs.Write | fs.Chmod
// remove, rename, write, and chmod all require a remove event
const removeFlags = fs.Remove | fs.Rename | fs.Write | fs.Chmod
// watch library paths and update Library with changes.
func startWatcher(a *App) {
timer := time.NewTimer(debounceTimeout)
addEvents := make(map[string]struct{})
removeEvents := make(map[string]struct{})
for {
select {
case e := <-a.Watcher.Events:
if e.Op&removeFlags > 0 {
removeEvents[e.Name] = struct{}{}
}
if e.Op&addFlags > 0 {
addEvents[e.Name] = struct{}{}
}
// reset timer
timer.Reset(debounceTimeout)
case <-timer.C:
// handle remove events first
if len(removeEvents) > 0 {
for p := range removeEvents {
a.Library.Remove(p)
}
// clear map
removeEvents = make(map[string]struct{})
}
// then handle add events
if len(addEvents) > 0 {
for p := range addEvents {
a.Library.Add(p)
}
// clear map
addEvents = make(map[string]struct{})
}
// reset timer
timer.Reset(debounceTimeout)
}
}
}