From e32b72d1eeea6f32314acb65267f6ff925f29560 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Walstr=C3=B6m?= Date: Sat, 20 Jun 2026 08:26:42 +0200 Subject: [PATCH] yangerd: containers: widen event debounce to avoid podman contention --- .../internal/containermonitor/containermonitor.go | 11 +++++++++-- .../containermonitor/containermonitor_test.go | 3 ++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/yangerd/internal/containermonitor/containermonitor.go b/src/yangerd/internal/containermonitor/containermonitor.go index 70e1556b..ffab5a16 100644 --- a/src/yangerd/internal/containermonitor/containermonitor.go +++ b/src/yangerd/internal/containermonitor/containermonitor.go @@ -31,8 +31,15 @@ import ( const ( treeKey = "infix-containers:containers" - // debounceDelay coalesces bursts of events into one re-read. - debounceDelay = 200 * time.Millisecond + // debounceDelay coalesces bursts of events into one re-read. It is + // deliberately generous: container lifecycle events fire while confd + // is still running its own `podman` start/stop/rm operations, so + // re-reading too eagerly makes yangerd's `podman ps/inspect/stats` + // contend with confd for the libpod lock on a CPU-starved guest. + // Waiting for the churn to settle keeps yangerd off confd's back + // during config apply/reset; a couple of seconds of staleness in + // operational data is harmless. + debounceDelay = 2 * time.Second ) // ContainerMonitor subscribes to container lifecycle events via a diff --git a/src/yangerd/internal/containermonitor/containermonitor_test.go b/src/yangerd/internal/containermonitor/containermonitor_test.go index 6634f4bd..d70c0f60 100644 --- a/src/yangerd/internal/containermonitor/containermonitor_test.go +++ b/src/yangerd/internal/containermonitor/containermonitor_test.go @@ -64,7 +64,8 @@ func TestEventTriggersRefresh(t *testing.T) { // A container "died" event, newline-framed as podman emits it. go m.readEvents(strings.NewReader(`{"Type":"container","Status":"died","Name":"gone"}` + "\n")) - deadline := time.After(2 * time.Second) + // Must comfortably exceed debounceDelay, or this races the re-read. + deadline := time.After(debounceDelay + 3*time.Second) for { if tr.Get(treeKey) == nil && calls > 0 { break