MCPcopy Create free account
hub / github.com/coder/coder / handleEvent

Method handleEvent

agent/x/agentmcp/configwatcher.go:241–308  ·  view source on GitHub ↗

handleEvent decides whether the event concerns one of the watched files (or could promote an ancestor watch) and, if so, schedules a debounced fire.

(ctx context.Context, evt fsnotify.Event)

Source from the content-addressed store, hash-verified

239// watched files (or could promote an ancestor watch) and, if so,
240// schedules a debounced fire.
241func (cw *configWatcher) handleEvent(ctx context.Context, evt fsnotify.Event) {
242 cw.mu.Lock()
243 if cw.closed {
244 cw.mu.Unlock()
245 return
246 }
247
248 // Match against any watched file. fsnotify event names are
249 // already absolute when the watched directory is absolute,
250 // which it is because armAncestorLocked called filepath.Dir
251 // on a path resolved to absolute. The filepath.Abs call below
252 // is a defensive normalization.
253 evtAbs, err := filepath.Abs(evt.Name)
254 if err != nil {
255 cw.mu.Unlock()
256 return
257 }
258
259 matchedFile := ""
260 for rp := range cw.files {
261 if rp == evtAbs {
262 matchedFile = rp
263 break
264 }
265 }
266
267 // If a directory we are watching for an ancestor of an
268 // unrealized path just gained a new child, try to re-arm
269 // deeper. This handles `mkdir ~/.config; touch
270 // ~/.config/.mcp.json` cases.
271 if matchedFile == "" && evt.Has(fsnotify.Create) {
272 for rp, dir := range cw.files {
273 // Only re-arm files whose final parent is not yet
274 // being watched directly.
275 expected := filepath.Dir(rp)
276 if dir == expected {
277 continue
278 }
279 // If this event is a directory inside our currently
280 // watched ancestor that lies on the way to rp,
281 // re-arm.
282 if isAncestorPathSegment(evtAbs, rp) {
283 cw.releaseDirLocked(dir)
284 newDir, armErr := cw.armAncestorLocked(rp)
285 if armErr != nil {
286 cw.logger.Debug(ctx,
287 "failed to re-arm config file watch on ancestor create",
288 slog.F("path", rp), slog.Error(armErr))
289 // Leave the file unarmed for now;
290 // next Sync will retry.
291 delete(cw.files, rp)
292 continue
293 }
294 cw.files[rp] = newDir
295 // The new dir may already contain the
296 // target file. Treat that as a match.
297 matchedFile = rp
298 }

Callers 1

runMethod · 0.95

Calls 8

releaseDirLockedMethod · 0.95
armAncestorLockedMethod · 0.95
scheduleFireMethod · 0.95
isAncestorPathSegmentFunction · 0.85
LockMethod · 0.45
UnlockMethod · 0.45
HasMethod · 0.45
ErrorMethod · 0.45

Tested by

no test coverage detected