@@ -397,6 +397,38 @@ func (u *updater) sendUpdateResponse(req *request[*TunnelMessage, *ManagerMessag
397
397
// createPeerUpdateLocked creates a PeerUpdate message from a workspace update, populating
398
398
// the network status of the agents.
399
399
func (u * updater )createPeerUpdateLocked (update tailnet.WorkspaceUpdate )* PeerUpdate {
400
+
401
+ // this flag is true on the first update after a reconnect
402
+ if update .FreshState {
403
+ // ignoredWorkspaces is initially populated with the workspaces that are
404
+ // in the current update. Later on we populate it with the deleted workspaces too
405
+ // so that we don't send duplicate updates.
406
+ ignoredWorkspaces := make (map [uuid.UUID ]struct {},len (update .UpsertedWorkspaces ))
407
+
408
+ for _ ,workspace := range update .UpsertedWorkspaces {
409
+ ignoredWorkspaces [workspace .ID ]= struct {}{}
410
+ }
411
+ for _ ,agent := range update .UpsertedAgents {
412
+ // delete any current agents that are not in the new update
413
+ if _ ,ok := u .agents [agent .ID ];! ok {
414
+ delete (u .agents ,agent .ID )
415
+ update .DeletedAgents = append (update .DeletedAgents ,& tailnet.Agent {
416
+ ID :agent .ID ,
417
+ Name :agent .Name ,
418
+ WorkspaceID :agent .WorkspaceID ,
419
+ })
420
+ if _ ,ok := ignoredWorkspaces [agent .WorkspaceID ];! ok {
421
+ update .DeletedWorkspaces = append (update .DeletedWorkspaces ,& tailnet.Workspace {
422
+ // other fields cannot be populated because the tunnel
423
+ // only stores agents and corresponding workspaceIDs
424
+ ID :agent .WorkspaceID ,
425
+ })
426
+ ignoredWorkspaces [agent .WorkspaceID ]= struct {}{}
427
+ }
428
+ }
429
+ }
430
+ }
431
+
400
432
out := & PeerUpdate {
401
433
UpsertedWorkspaces :make ([]* Workspace ,len (update .UpsertedWorkspaces )),
402
434
UpsertedAgents :make ([]* Agent ,len (update .UpsertedAgents )),
@@ -413,16 +445,6 @@ func (u *updater) createPeerUpdateLocked(update tailnet.WorkspaceUpdate) *PeerUp
413
445
delete (u .agents ,agent .ID )
414
446
}
415
447
416
- // this flag is true on the first update after a reconnect
417
- if update .FreshState {
418
- for _ ,agent := range update .UpsertedAgents {
419
- // delete any current agents that are not in the new update
420
- if _ ,ok := u .agents [agent .ID ];! ok {
421
- delete (u .agents ,agent .ID )
422
- }
423
- }
424
- }
425
-
426
448
for i ,ws := range update .UpsertedWorkspaces {
427
449
out .UpsertedWorkspaces [i ]= & Workspace {
428
450
Id :tailnet .UUIDToByteSlice (ws .ID ),