feat(desktop&tenant): Enhance desktop account and task consumer presence management
Desktop Client Build / Resolve Build Metadata (push) Successful in 1m13s
Desktop Client Build / Build Desktop Client (push) Has been cancelled
Desktop Client Build / Publish Client Artifacts to NAS (push) Has been cancelled
Backend CI / Backend (push) Failing after 13m49s
Frontend CI / Frontend (push) Successful in 6m38s

- Added new fields to DesktopAccountInfo for tracking account session and task consumer online status, along with queued publish task count and oldest queued publish task timestamp.
- Updated DesktopDispatchEvent to include server time for better synchronization.
- Implemented separate presence management for task consumers, including marking presence and loading presence state.
- Enhanced DesktopAccountService to apply publish queue summaries and manage task consumer presence.
- Introduced new methods for replaying queued publish tasks in DesktopDispatchHandler.
- Updated tests to cover new presence management logic and ensure correct behavior of account session and task consumer online status.
This commit is contained in:
2026-06-07 19:15:20 +08:00
parent 88c37e50b2
commit 67be43319e
15 changed files with 636 additions and 129 deletions
@@ -58,7 +58,9 @@ func TestResolveDesktopClientOnline_StaleHeartbeatIsOffline(t *testing.T) {
}
func TestBuildDesktopAccountView_StoredClientOwnershipWinsOverPresence(t *testing.T) {
service := &DesktopAccountService{}
service := &DesktopAccountService{now: func() time.Time {
return time.Date(2026, 4, 19, 21, 30, 0, 0, time.UTC)
}}
accountID := uuid.New()
staleClientID := uuid.New()
activeClientID := uuid.New()
@@ -84,6 +86,12 @@ func TestBuildDesktopAccountView_StoredClientOwnershipWinsOverPresence(t *testin
map[uuid.UUID]uuid.UUID{
accountID: activeClientID,
},
map[uuid.UUID]bool{
activeClientID: true,
},
map[uuid.UUID]bool{
activeClientID: true,
},
)
if assert.NotNil(t, view.ClientID) {
@@ -92,16 +100,23 @@ func TestBuildDesktopAccountView_StoredClientOwnershipWinsOverPresence(t *testin
if assert.NotNil(t, view.ClientOnline) {
assert.False(t, *view.ClientOnline)
}
if assert.NotNil(t, view.AccountSessionOnline) {
assert.False(t, *view.AccountSessionOnline)
}
if assert.NotNil(t, view.TaskConsumerOnline) {
assert.False(t, *view.TaskConsumerOnline)
}
assert.Equal(t, "4181862206", view.PlatformUID)
assert.Nil(t, view.ClientLastSeenAt)
assert.Nil(t, view.ClientDeviceName)
}
func TestBuildDesktopAccountView_FallsBackToStoredClientWhenNoPresence(t *testing.T) {
service := &DesktopAccountService{}
now := time.Date(2026, 4, 19, 21, 30, 0, 0, time.UTC)
service := &DesktopAccountService{now: func() time.Time { return now }}
accountID := uuid.New()
storedClientID := uuid.New()
lastSeen := time.Date(2026, 4, 19, 21, 30, 0, 0, time.UTC)
lastSeen := now.Add(-desktopClientPresenceTTL / 2)
view := service.buildDesktopAccountView(
&repository.DesktopAccount{
@@ -119,17 +134,67 @@ func TestBuildDesktopAccountView_FallsBackToStoredClientWhenNoPresence(t *testin
},
},
nil,
nil,
nil,
)
if assert.NotNil(t, view.ClientID) {
assert.Equal(t, storedClientID.String(), *view.ClientID)
}
if assert.NotNil(t, view.ClientOnline) {
assert.False(t, *view.ClientOnline)
assert.True(t, *view.ClientOnline)
}
assert.Equal(t, &lastSeen, view.ClientLastSeenAt)
}
func TestBuildDesktopAccountView_SplitsHeartbeatAccountSessionAndTaskConsumer(t *testing.T) {
now := time.Date(2026, 4, 19, 21, 30, 0, 0, time.UTC)
service := &DesktopAccountService{now: func() time.Time { return now }}
accountID := uuid.New()
clientID := uuid.New()
lastSeen := now.Add(-time.Minute)
deviceName := "Windows Workstation"
view := service.buildDesktopAccountView(
&repository.DesktopAccount{
DesktopID: accountID,
ClientID: &clientID,
Platform: "sohuhao",
PlatformUID: "110424528162",
DisplayName: "全屋定制老炮",
Health: "live",
},
map[uuid.UUID]*repository.DesktopClient{
clientID: {
ID: clientID,
LastSeenAt: &lastSeen,
DeviceName: &deviceName,
},
},
map[uuid.UUID]uuid.UUID{
accountID: clientID,
},
map[uuid.UUID]bool{
clientID: true,
},
map[uuid.UUID]bool{
clientID: false,
},
)
if assert.NotNil(t, view.ClientOnline) {
assert.True(t, *view.ClientOnline)
}
if assert.NotNil(t, view.AccountSessionOnline) {
assert.True(t, *view.AccountSessionOnline)
}
if assert.NotNil(t, view.TaskConsumerOnline) {
assert.False(t, *view.TaskConsumerOnline)
}
assert.Equal(t, &lastSeen, view.ClientLastSeenAt)
assert.Equal(t, &deviceName, view.ClientDeviceName)
}
func TestShouldApplyDesktopAccountRuntimeHealth_IgnoresReportOlderThanVerifiedAt(t *testing.T) {
verifiedAt := time.Date(2026, 4, 30, 9, 30, 0, 0, time.UTC)
reportCheckedAt := verifiedAt.Add(-time.Minute)