fix(agent): improve WebSocket and SSH fallback handling (#2441)

Make WebSocket reconnect and SSH fallback transitions reliable across asynchronous disconnects, stale callbacks, and overlapping connections. Keep the SSH listener available while disconnected and allow a verified WebSocket connection to take precedence when it recovers.

Co-authored-by: henrygd <hank@henrygd.me>
This commit is contained in:
spatiumstas
2026-10-01 20:33:19 +03:00
committed by henrygd
parent d8c2b1f310
commit 4ffd83677d
10 changed files with 688 additions and 65 deletions

View File

@@ -10,6 +10,7 @@ import (
"github.com/henrygd/beszel/agent/zfs"
"github.com/henrygd/beszel/internal/common"
"github.com/henrygd/beszel/internal/entities/smart"
"github.com/henrygd/beszel/internal/entities/system"
"github.com/stretchr/testify/assert"
)
@@ -32,6 +33,30 @@ func TestNewAgentResponseSmartData(t *testing.T) {
assert.True(t, response.SmartComplete)
}
func TestGetDataHandlerReportsRequestTransport(t *testing.T) {
cache := NewSystemDataCache()
cached := &system.CombinedData{}
cache.Set(cached, defaultDataCacheTimeMs)
agent := &Agent{cache: cache}
options, err := cbor.Marshal(common.DataRequestOptions{CacheTimeMs: defaultDataCacheTimeMs})
assert.NoError(t, err)
request := &common.HubRequest[cbor.RawMessage]{Action: common.GetData, Data: options}
for _, transport := range []system.ConnectionType{system.ConnectionTypeSSH, system.ConnectionTypeWebSocket} {
ctx := &HandlerContext{
Agent: agent,
Request: request,
ConnectionType: transport,
SendResponse: func(data any, _ *uint32) error {
response := data.(*system.CombinedData)
assert.Equal(t, transport, response.Info.ConnectionType)
return nil
},
}
assert.NoError(t, (&GetDataHandler{}).Handle(ctx))
assert.Equal(t, system.ConnectionTypeNone, cached.Info.ConnectionType)
}
}
func TestGetZfsDataHandlerForceRefresh(t *testing.T) {
poolCalls := 0
zm := &StoragePoolManager{detailInterval: time.Hour, backends: []*poolBackend{{name: "zfs"}}}