From 5b266f19951d54530cf224851941772fbaf327e8 Mon Sep 17 00:00:00 2001 From: Anduin Xue Date: Sun, 21 Jun 2026 02:14:18 +0800 Subject: [PATCH] agent: use proto.Equal instead of reflect.DeepEqual for node comparison reflect.DeepEqual treats nil slices and empty slices as not equal, which causes spurious node description updates when protobuf repeated fields (like CSIInfo) are nil in the executor output but become empty slices after gRPC serialization/deserialization round-trip. This triggers 'agent: found node update' every 20 seconds (the nodeUpdatePeriod), causing unnecessary session restarts, VXLAN reinitialization, and excessive Raft WAL writes (~388/day, ~429MB of WAL accumulation). proto.Equal correctly handles protobuf semantics where nil slices and empty slices are equivalent, as well as treating zero values and unset fields as equal. Co-Authored-By: Claude Signed-off-by: Anduin Xue --- agent/agent.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/agent/agent.go b/agent/agent.go index 60df8a602c..d092a8ec7c 100644 --- a/agent/agent.go +++ b/agent/agent.go @@ -4,10 +4,10 @@ import ( "bytes" "context" "math/rand" - "reflect" "sync" "time" + "github.com/gogo/protobuf/proto" "github.com/moby/swarmkit/v2/agent/exec" "github.com/moby/swarmkit/v2/api" "github.com/moby/swarmkit/v2/log" @@ -249,7 +249,7 @@ func (a *Agent) run(ctx context.Context) { // if the node description has changed, update it to the new one // and close the session. The old session will be stopped and a // new one will be created with the updated description - if !reflect.DeepEqual(nodeDescription, newNodeDescription) { + if !proto.Equal(nodeDescription, newNodeDescription) { nodeDescription = newNodeDescription // close the session log.G(ctx).Info("agent: found node update") @@ -652,5 +652,5 @@ func nodesEqual(a, b *api.Node) bool { a.Status, b.Status = api.NodeStatus{}, api.NodeStatus{} a.Meta, b.Meta = api.Meta{}, api.Meta{} - return reflect.DeepEqual(a, b) + return proto.Equal(a, b) }