@@ -20,6 +20,7 @@ var errUnwatchedPollStopped = errors.New("unwatched poll coordinator stopped")
2020
2121type unwatchedPollSyncer interface {
2222 ReconcileWatchRoots (context.Context , []string , bool ) error
23+ ReconcileProviderRoots (context.Context , parser.AgentType , []string ) error
2324}
2425
2526type unwatchedPollAdd struct {
@@ -30,6 +31,7 @@ type unwatchedPollAdd struct {
3031
3132type pollingObligation struct {
3233 Key string
34+ Agent parser.AgentType
3335 Roots []string
3436 // Probe mirrors sync.PollingObligation.Probe: the physical watcher path
3537 // whose availability gates this obligation's reconciliation Roots. When
@@ -173,8 +175,9 @@ func (c *sharedUnwatchedPollCoordinator) run() {
173175 } else {
174176 obligations [request .obligation .Key ] = request .obligation
175177 }
176- c . setPollObligations (obligations )
178+ snapshot := sortedPollObligations (obligations )
177179 c .pollMu .Lock ()
180+ c .pollObligations = snapshot
178181 c .pollRevisions [request .obligation .Key ]++
179182 delete (c .pollStates , request .obligation .Key )
180183 c .pollMu .Unlock ()
@@ -188,19 +191,17 @@ func (c *sharedUnwatchedPollCoordinator) run() {
188191 }
189192}
190193
191- func ( c * sharedUnwatchedPollCoordinator ) setPollObligations (
194+ func sortedPollObligations (
192195 obligations map [string ]pollingObligation ,
193- ) {
196+ ) [] pollingObligation {
194197 snapshot := make ([]pollingObligation , 0 , len (obligations ))
195198 for _ , obligation := range obligations {
196199 snapshot = append (snapshot , obligation )
197200 }
198201 slices .SortFunc (snapshot , func (a , b pollingObligation ) int {
199202 return strings .Compare (a .Key , b .Key )
200203 })
201- c .pollMu .Lock ()
202- c .pollObligations = snapshot
203- c .pollMu .Unlock ()
204+ return snapshot
204205}
205206
206207func (c * sharedUnwatchedPollCoordinator ) currentPollObligations () []pollingObligation {
@@ -232,18 +233,18 @@ func (c *sharedUnwatchedPollCoordinator) runPollWorker() {
232233 return
233234 }
234235 obligations , priorStates , priorRevisions := c .currentPollSnapshot ()
235- roots , nextStates := c .preparePollRun (
236+ selected , nextStates := c .preparePollRun (
236237 c .workerCtx , obligations , priorStates ,
237238 )
238- if len (roots ) == 0 {
239+ if len (selected ) == 0 {
239240 continue
240241 }
241- log .Printf ("polling %d unwatched root(s)" , len (roots ))
242+ log .Printf ("polling %d unwatched root(s)" , len (unwatchedPollObligationSliceRoots ( selected ) ))
242243 c .doWork (func () {
243244 if c .workerCtx .Err () != nil {
244245 return
245246 }
246- if err := pollUnwatchedRootsOnce (c .workerCtx , c .engine , roots ); err != nil {
247+ if err := pollUnwatchedRootsOnce (c .workerCtx , c .engine , selected ); err != nil {
247248 return
248249 }
249250 c .commitPollStates (nextStates , priorRevisions )
@@ -270,10 +271,10 @@ func (c *sharedUnwatchedPollCoordinator) runPollWorker() {
270271// deferred scope as an authoritative empty discovery and tombstone its
271272// sessions.
272273func availableUnwatchedPollRoots (obligations []pollingObligation ) []string {
273- roots , _ := availableUnwatchedPollRootsWithState (
274+ selected , _ := availableUnwatchedPollObligationsWithState (
274275 context .Background (), obligations , nil ,
275276 )
276- return roots
277+ return unwatchedPollObligationSliceRoots ( selected )
277278}
278279
279280func unwatchedPollObligationRoots (obligations map [string ]pollingObligation ) []string {
@@ -288,6 +289,18 @@ func unwatchedPollObligationRoots(obligations map[string]pollingObligation) []st
288289 return unwatchedPollRoots (owned )
289290}
290291
292+ func unwatchedPollObligationSliceRoots (obligations []pollingObligation ) []string {
293+ owned := make (map [string ]struct {})
294+ for _ , obligation := range obligations {
295+ for _ , root := range obligation .Roots {
296+ if root != "" {
297+ owned [root ] = struct {}{}
298+ }
299+ }
300+ }
301+ return unwatchedPollRoots (owned )
302+ }
303+
291304func unwatchedPollRoots (owned map [string ]struct {}) []string {
292305 roots := make ([]string , 0 , len (owned ))
293306 for root := range owned {
@@ -298,14 +311,47 @@ func unwatchedPollRoots(owned map[string]struct{}) []string {
298311}
299312
300313func pollUnwatchedRootsOnce (
301- ctx context.Context , engine unwatchedPollSyncer , roots []string ,
314+ ctx context.Context , engine unwatchedPollSyncer , obligations []pollingObligation ,
302315) error {
303- if len (roots ) == 0 {
316+ if len (obligations ) == 0 {
304317 return nil
305318 }
306- if err := engine .ReconcileWatchRoots (ctx , roots , false ); err != nil {
307- log .Printf ("polling unwatched roots: %v" , err )
308- return err
319+ watchRoots := make (map [string ]struct {})
320+ byAgent := make (map [parser.AgentType ]map [string ]struct {})
321+ for _ , obligation := range obligations {
322+ target := watchRoots
323+ if obligation .Agent != "" {
324+ if byAgent [obligation .Agent ] == nil {
325+ byAgent [obligation .Agent ] = make (map [string ]struct {})
326+ }
327+ target = byAgent [obligation .Agent ]
328+ }
329+ for _ , root := range obligation .Roots {
330+ if root != "" {
331+ target [root ] = struct {}{}
332+ }
333+ }
334+ }
335+ if roots := unwatchedPollRoots (watchRoots ); len (roots ) > 0 {
336+ if err := engine .ReconcileWatchRoots (ctx , roots , false ); err != nil {
337+ log .Printf ("polling unwatched roots: %v" , err )
338+ return err
339+ }
340+ }
341+ agents := make ([]parser.AgentType , 0 , len (byAgent ))
342+ for agent := range byAgent {
343+ agents = append (agents , agent )
344+ }
345+ slices .Sort (agents )
346+ for _ , agent := range agents {
347+ roots := unwatchedPollRoots (byAgent [agent ])
348+ if len (roots ) == 0 {
349+ continue
350+ }
351+ if err := engine .ReconcileProviderRoots (ctx , agent , roots ); err != nil {
352+ log .Printf ("polling unwatched %s roots: %v" , agent , err )
353+ return err
354+ }
309355 }
310356 return nil
311357}
@@ -326,8 +372,8 @@ func (c *sharedUnwatchedPollCoordinator) preparePollRun(
326372 ctx context.Context ,
327373 obligations []pollingObligation ,
328374 prior map [string ]string ,
329- ) ([]string , map [string ]string ) {
330- return availableUnwatchedPollRootsWithState (
375+ ) ([]pollingObligation , map [string ]string ) {
376+ return availableUnwatchedPollObligationsWithState (
331377 ctx , obligations , prior ,
332378 )
333379}
@@ -349,15 +395,14 @@ func (c *sharedUnwatchedPollCoordinator) commitPollStates(
349395 }
350396}
351397
352- func availableUnwatchedPollRootsWithState (
398+ func availableUnwatchedPollObligationsWithState (
353399 ctx context.Context ,
354400 obligations []pollingObligation ,
355401 prior map [string ]string ,
356- ) ([]string , map [string ]string ) {
357- candidates := make (map [string ]struct {})
402+ ) ([]pollingObligation , map [string ]string ) {
358403 blocked := make (map [string ]struct {})
359- candidateOwners := make (map [string ][]string )
360404 pendingStates := make (map [string ]string )
405+ selected := make ([]pollingObligation , 0 , len (obligations ))
361406 for _ , obligation := range obligations {
362407 probeMissing := false
363408 if obligation .Probe != "" {
@@ -382,33 +427,42 @@ func availableUnwatchedPollRootsWithState(
382427 pendingStates [obligation .Key ] = state
383428 }
384429 }
430+ roots := make ([]string , 0 , len (obligation .Roots ))
385431 for _ , root := range obligation .Roots {
386432 if root == "" {
387433 continue
388434 }
389435 if _ , err := os .Stat (root ); err == nil {
390- candidates [root ] = struct {}{}
391- candidateOwners [root ] = append (candidateOwners [root ], obligation .Key )
436+ roots = append (roots , root )
392437 }
393438 }
394- }
395- for root := range candidates {
396- if overlapsDeferredScope (filepath .Clean (root ), blocked ) {
397- delete (candidates , root )
439+ if len (roots ) == 0 {
440+ continue
398441 }
442+ selected = append (selected , pollingObligation {
443+ Key : obligation .Key ,
444+ Agent : obligation .Agent ,
445+ Roots : roots ,
446+ Probe : obligation .Probe ,
447+ DegradedProbe : obligation .DegradedProbe ,
448+ })
399449 }
400- if len (pendingStates ) == 0 {
401- return unwatchedPollRoots (candidates ), nil
402- }
403- committed := make (map [string ]string )
404- for root := range candidates {
405- for _ , key := range candidateOwners [root ] {
406- if state , ok := pendingStates [key ]; ok {
407- committed [key ] = state
450+ filtered := make ([]pollingObligation , 0 , len (selected ))
451+ for _ , obligation := range selected {
452+ deferred := false
453+ for _ , root := range obligation .Roots {
454+ if overlapsDeferredScope (filepath .Clean (root ), blocked ) {
455+ deferred = true
456+ break
408457 }
409458 }
459+ if deferred {
460+ delete (pendingStates , obligation .Key )
461+ continue
462+ }
463+ filtered = append (filtered , obligation )
410464 }
411- return unwatchedPollRoots ( candidates ), committed
465+ return filtered , pendingStates
412466}
413467
414468func clonePollStates (states map [string ]string ) map [string ]string {
0 commit comments