MCPcopy
hub / github.com/OpenNHP/opennhp / WatchFile

Function WatchFile

nhp/utils/file.go:76–133  ·  view source on GitHub ↗
(file string, callback func())

Source from the content-addressed store, hash-verified

74}
75
76func WatchFile(file string, callback func()) io.Closer {
77 watcher, err := fsnotify.NewWatcher()
78 if err != nil {
79 log.Error("failed to create file watcher for %s: %v", file, err)
80 return nil
81 }
82
83 // we have to watch the entire directory to pick up renames/atomic saves in a cross-platform way
84 filename := filepath.Clean(file)
85 dirPath, _ := filepath.Split(filename)
86 if err := watcher.Add(dirPath); err != nil {
87 log.Error("failed to add directory to watcher: %v", err)
88 return nil
89 }
90
91 var eventsWG sync.WaitGroup
92 var debounceTimer *time.Timer
93 debounceTime := 100 * time.Millisecond
94 eventsWG.Add(1)
95
96 go func() {
97 defer CatchPanic()
98 defer watcher.Close()
99 defer eventsWG.Done()
100
101 for {
102 select {
103 case event, ok := <-watcher.Events:
104 if !ok { // 'Events' channel is closed
105 return
106 }
107
108 // callback fires when file is modified or created
109 if filepath.Clean(event.Name) == filename {
110 if event.Has(fsnotify.Write) || event.Has(fsnotify.Create) {
111 if callback != nil {
112 if debounceTimer != nil {
113 debounceTimer.Stop()
114 }
115 debounceTimer = time.AfterFunc(debounceTime, func() { callback() })
116 }
117 } else if event.Has(fsnotify.Remove) {
118 return
119 }
120 }
121
122 case err, ok := <-watcher.Errors:
123 if ok { // 'Errors' channel is not closed
124 log.Error("file watcher error: %v", err)
125 }
126 return
127 }
128 }
129 }()
130
131 log.Info("start watching file %s", filename)
132 return &fileWatcher{filename, watcher, &eventsWG}
133}

Callers

nothing calls this directly

Calls 5

CatchPanicFunction · 0.85
ErrorMethod · 0.65
AddMethod · 0.65
CloseMethod · 0.65
StopMethod · 0.45

Tested by

no test coverage detected