diff --git a/management/server/affected_peers_test.go b/management/server/affected_peers_test.go index 1a9d2d5d9..b66eeb3b5 100644 --- a/management/server/affected_peers_test.go +++ b/management/server/affected_peers_test.go @@ -1433,6 +1433,10 @@ func TestAffectedPeers_IsolatedEntitiesOnlyAffectTheirPeers(t *testing.T) { updateManager.CloseChannel(ctx, peer3.ID) }) + // The setup policy/route above dispatch affected-peer updates asynchronously; + // drain any in-flight ones so the assertions only observe the UpdateGroup below. + settleAffectedUpdates(updMsg1, updMsg2, updMsg3) + t.Run("policy group change does not affect route-only peer", func(t *testing.T) { done := make(chan struct{}) go func() { diff --git a/management/server/group.go b/management/server/group.go index 51c558c08..070344c61 100644 --- a/management/server/group.go +++ b/management/server/group.go @@ -269,7 +269,7 @@ func (am *DefaultAccountManager) CreateGroups(ctx context.Context, accountID, us storeEvent() } - am.dispatchAffected(ctx, accountID, snaps, changes) + go am.dispatchAffected(ctx, accountID, snaps, changes) return globalErr } @@ -312,7 +312,7 @@ func (am *DefaultAccountManager) UpdateGroups(ctx context.Context, accountID, us storeEvent() } - am.dispatchAffected(ctx, accountID, snaps, changes) + go am.dispatchAffected(ctx, accountID, snaps, changes) return globalErr } diff --git a/management/server/networks/manager.go b/management/server/networks/manager.go index b0d0e46cd..d572502fd 100644 --- a/management/server/networks/manager.go +++ b/management/server/networks/manager.go @@ -187,7 +187,7 @@ func (m *managerImpl) DeleteNetwork(ctx context.Context, accountID, userID, netw event() } - go m.accountManager.ExpandAndUpdateAffected(ctx, accountID, snap, change) + m.accountManager.ExpandAndUpdateAffected(ctx, accountID, snap, change) return nil } diff --git a/management/server/networks/resources/manager.go b/management/server/networks/resources/manager.go index 53fddaca7..6c427ce62 100644 --- a/management/server/networks/resources/manager.go +++ b/management/server/networks/resources/manager.go @@ -130,7 +130,7 @@ func (m *managerImpl) CreateResource(ctx context.Context, userID string, resourc event() } - go m.accountManager.ExpandAndUpdateAffected(ctx, resource.AccountID, snap, change) + m.accountManager.ExpandAndUpdateAffected(ctx, resource.AccountID, snap, change) return resource, nil } @@ -297,7 +297,7 @@ func (m *managerImpl) UpdateResource(ctx context.Context, userID string, resourc } }() - go m.accountManager.ExpandAndUpdateAffected(ctx, resource.AccountID, snap, change) + m.accountManager.ExpandAndUpdateAffected(ctx, resource.AccountID, snap, change) return resource, nil } @@ -397,7 +397,7 @@ func (m *managerImpl) DeleteResource(ctx context.Context, accountID, userID, net event() } - go m.accountManager.ExpandAndUpdateAffected(ctx, accountID, snap, change) + m.accountManager.ExpandAndUpdateAffected(ctx, accountID, snap, change) return nil } diff --git a/management/server/networks/routers/manager.go b/management/server/networks/routers/manager.go index e0d4c9934..f1b31093c 100644 --- a/management/server/networks/routers/manager.go +++ b/management/server/networks/routers/manager.go @@ -126,7 +126,7 @@ func (m *managerImpl) CreateRouter(ctx context.Context, userID string, router *t m.accountManager.StoreEvent(ctx, userID, router.ID, router.AccountID, activity.NetworkRouterCreated, router.EventMeta(network)) - go m.accountManager.ExpandAndUpdateAffected(ctx, router.AccountID, snap, change) + m.accountManager.ExpandAndUpdateAffected(ctx, router.AccountID, snap, change) return router, nil } @@ -175,7 +175,7 @@ func (m *managerImpl) UpdateRouter(ctx context.Context, userID string, router *t m.accountManager.StoreEvent(ctx, userID, router.ID, router.AccountID, activity.NetworkRouterUpdated, router.EventMeta(network)) - go m.accountManager.ExpandAndUpdateAffected(ctx, router.AccountID, snap, change) + m.accountManager.ExpandAndUpdateAffected(ctx, router.AccountID, snap, change) return router, nil } @@ -256,7 +256,7 @@ func (m *managerImpl) DeleteRouter(ctx context.Context, accountID, userID, netwo event() - go m.accountManager.ExpandAndUpdateAffected(ctx, accountID, snap, change) + m.accountManager.ExpandAndUpdateAffected(ctx, accountID, snap, change) return nil } diff --git a/management/server/peer.go b/management/server/peer.go index e2afbf3b2..e8990481b 100644 --- a/management/server/peer.go +++ b/management/server/peer.go @@ -1477,14 +1477,18 @@ func (am *DefaultAccountManager) UpdateAccountPeers(ctx context.Context, account // never holds the write lock, over the consistent in-tx snapshot. Exported so the // networks sub-package managers (which hold only account.Manager) share it. func (am *DefaultAccountManager) ExpandAndUpdateAffected(ctx context.Context, accountID string, snap *affectedpeers.Snapshot, change affectedpeers.Change) { - am.dispatchAffected(ctx, accountID, []*affectedpeers.Snapshot{snap}, []affectedpeers.Change{change}) + go am.dispatchAffected(ctx, accountID, []*affectedpeers.Snapshot{snap}, []affectedpeers.Change{change}) } // dispatchAffected expands one or more (snapshot, change) pairs — collected across // one or several transactions — unions their affected peers, and dispatches a // single network-map refresh. Each snapshot must already be loaded inside its -// transaction; this runs AFTER commit (pure in-memory + dispatch). +// transaction; this runs AFTER commit (pure in-memory + dispatch). It is spawned +// in a goroutine that outlives the request, so it detaches from the request +// context's cancellation up front. func (am *DefaultAccountManager) dispatchAffected(ctx context.Context, accountID string, snaps []*affectedpeers.Snapshot, changes []affectedpeers.Change) { + ctx = context.WithoutCancel(ctx) + var lists [][]string for i, snap := range snaps { if snap == nil { @@ -1500,7 +1504,7 @@ func (am *DefaultAccountManager) dispatchAffected(ctx context.Context, accountID } log.WithContext(ctx).Debugf("updating %d affected peers for account %s: %v", len(affectedPeerIDs), accountID, affectedPeerIDs) - _ = am.networkMapController.UpdateAffectedPeers(context.WithoutCancel(ctx), accountID, affectedPeerIDs) + _ = am.networkMapController.UpdateAffectedPeers(ctx, accountID, affectedPeerIDs) } // unionStrings concatenates the given string lists into one deduplicated slice,