feat(agent): diff inventories and debounce docker events

This commit is contained in:
2026-10-12 14:36:11 +02:00
parent abee9abb1b
commit 3edaf4e602
4 changed files with 166 additions and 0 deletions
+52
View File
@@ -0,0 +1,52 @@
package inventory
import (
"context"
"fmt"
"time"
"github.com/docker/docker/api/types/events"
"github.com/docker/docker/api/types/filters"
)
// EventSource is the subset of the Docker SDK Watch needs.
// *client.Client satisfies it.
type EventSource interface {
Events(ctx context.Context, opts events.ListOptions) (<-chan events.Message, <-chan error)
}
// Watch subscribes to container and service lifecycle events and calls
// onChange once after each burst has been quiet for the given duration.
// A Compose restart emits a dozen events; this turns them into one
// inventory refresh. Returns nil when ctx ends, or an error if the event
// stream breaks (for example when the daemon restarts) — the caller should
// resubscribe and refresh, since events may have been missed.
func Watch(ctx context.Context, src EventSource, quiet time.Duration, onChange func()) error {
args := filters.NewArgs(
filters.Arg("type", string(events.ContainerEventType)),
filters.Arg("type", string(events.ServiceEventType)),
)
for _, action := range []string{"create", "start", "stop", "die", "destroy", "rename", "update", "remove"} {
args.Add("event", action)
}
msgs, errs := src.Events(ctx, events.ListOptions{Filters: args})
timer := time.NewTimer(quiet)
timer.Stop()
defer timer.Stop()
for {
select {
case <-ctx.Done():
return nil
case err := <-errs:
if ctx.Err() != nil {
return nil
}
return fmt.Errorf("docker events: %w", err)
case <-msgs:
timer.Reset(quiet)
case <-timer.C:
onChange()
}
}
}