From 9fa50dd7b997a0d20e9edee118ed9e721a0042fb Mon Sep 17 00:00:00 2001 From: riccardom Date: Tue, 20 Oct 2026 10:30:43 +0200 Subject: [PATCH] [client] Publish the network map event once per converged map Every bounded pass published "Network map updated", so a large map pushed dozens of identical events to the UI for a single update. The event now fires from the converging pass, next to the lazy-exclude finalize. A map ignored as outdated no longer publishes it either, since nothing was applied. --- client/internal/engine.go | 4 ++-- client/internal/engine_test.go | 30 ++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/client/internal/engine.go b/client/internal/engine.go index 402280fdf..0550180e1 100644 --- a/client/internal/engine.go +++ b/client/internal/engine.go @@ -1066,8 +1066,6 @@ func (e *Engine) applySyncPass(update *mgmProto.SyncResponse, firstPass bool) (b return false, err } - e.statusRecorder.PublishEvent(cProto.SystemEvent_INFO, cProto.SystemEvent_SYSTEM, "Network map updated", "", nil) - return more, nil } @@ -1766,6 +1764,8 @@ func (e *Engine) updateNetworkMap(networkMap *mgmProto.NetworkMap, maxBatch int, excludedLazyPeers := e.toExcludedLazyPeers(remotePeers) e.connMgr.SetExcludeList(e.ctx, excludedLazyPeers) doneLazy() + + e.statusRecorder.PublishEvent(cProto.SystemEvent_INFO, cProto.SystemEvent_SYSTEM, "Network map updated", "", nil) } e.networkSerial = serial diff --git a/client/internal/engine_test.go b/client/internal/engine_test.go index b882e8986..41e41d391 100644 --- a/client/internal/engine_test.go +++ b/client/internal/engine_test.go @@ -718,6 +718,36 @@ func TestEngine_UpdateNetworkMap(t *testing.T) { require.False(t, more, "pass 2 should converge") require.Len(t, engine.peerStore.PeersPubKey(), 1) }) + + // The UI shows one "Network map updated" event per map, so the passes that + // only drain peer batches must stay silent and the converging one publishes. + t.Run("chunked apply publishes one network map event", func(t *testing.T) { + countMapEvents := func() int { + n := 0 + for _, ev := range engine.statusRecorder.GetEventHistory() { + if ev.GetMessage() == "Network map updated" { + n++ + } + } + return n + } + before := countMapEvents() + + nm := &mgmtProto.NetworkMap{ + Serial: 8, + RemotePeers: []*mgmtProto.RemotePeerConfig{peer1, peer2, peer3}, + } + + more, err := engine.updateNetworkMap(nm, 1, true) + require.NoError(t, err) + require.True(t, more, "pass 1 should signal more") + assert.Equal(t, before, countMapEvents(), "a draining pass should not publish the event") + + more, err = engine.updateNetworkMap(nm, 1, false) + require.NoError(t, err) + require.False(t, more, "pass 2 should converge") + assert.Equal(t, before+1, countMapEvents(), "the converging pass should publish exactly one event") + }) } func TestEngine_UpdateNetworkMapWithRoutes(t *testing.T) {