feat(cloud): disconnect from cloud immediately when cloud URL changes or user requests to deregister

This commit is contained in:
Siyuan Miao 2025-04-04 12:58:19 +02:00
parent f3b5011d65
commit 73e715117e
2 changed files with 49 additions and 0 deletions

View File

@ -7,6 +7,7 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"net/url" "net/url"
"sync"
"time" "time"
"github.com/coder/websocket/wsjson" "github.com/coder/websocket/wsjson"
@ -113,6 +114,11 @@ var (
) )
) )
var (
cloudDisconnectChan chan error
cloudDisconnectLock = &sync.Mutex{}
)
func cloudResetMetrics(established bool) { func cloudResetMetrics(established bool) {
metricCloudConnectionLastPingTimestamp.Set(-1) metricCloudConnectionLastPingTimestamp.Set(-1)
metricCloudConnectionLastPingDuration.Set(-1) metricCloudConnectionLastPingDuration.Set(-1)
@ -213,6 +219,24 @@ func handleCloudRegister(c *gin.Context) {
c.JSON(200, gin.H{"message": "Cloud registration successful"}) c.JSON(200, gin.H{"message": "Cloud registration successful"})
} }
func disconnectCloud(reason error) {
cloudDisconnectLock.Lock()
defer cloudDisconnectLock.Unlock()
if cloudDisconnectChan == nil {
cloudLogger.Tracef("cloud disconnect channel is not set, no need to disconnect")
return
}
// just in case the channel is closed, we don't want to panic
defer func() {
if r := recover(); r != nil {
cloudLogger.Infof("cloud disconnect channel is closed, no need to disconnect: %v", r)
}
}()
cloudDisconnectChan <- reason
}
func runWebsocketClient() error { func runWebsocketClient() error {
if config.CloudToken == "" { if config.CloudToken == "" {
time.Sleep(5 * time.Second) time.Sleep(5 * time.Second)
@ -275,6 +299,23 @@ func runWebsocketClient() error {
metricCloudConnectionLastPingTimestamp.SetToCurrentTime() metricCloudConnectionLastPingTimestamp.SetToCurrentTime()
} }
}() }()
// create a channel to receive the disconnect event, once received, we cancelRun
cloudDisconnectChan = make(chan error)
defer func() {
close(cloudDisconnectChan)
cloudDisconnectChan = nil
}()
go func() {
for err := range cloudDisconnectChan {
if err == nil {
continue
}
cloudLogger.Infof("disconnecting from cloud due to: %v", err)
cancelRun()
}
}()
for { for {
typ, msg, err := c.Read(runCtx) typ, msg, err := c.Read(runCtx)
if err != nil { if err != nil {
@ -448,6 +489,9 @@ func rpcDeregisterDevice() error {
return fmt.Errorf("failed to save configuration after deregistering: %w", err) return fmt.Errorf("failed to save configuration after deregistering: %w", err)
} }
cloudLogger.Infof("device deregistered, disconnecting from cloud")
disconnectCloud(fmt.Errorf("device deregistered"))
return nil return nil
} }

View File

@ -771,9 +771,14 @@ func rpcSetUsbDeviceState(device string, enabled bool) error {
} }
func rpcSetCloudUrl(apiUrl string, appUrl string) error { func rpcSetCloudUrl(apiUrl string, appUrl string) error {
currentCloudURL := config.CloudURL
config.CloudURL = apiUrl config.CloudURL = apiUrl
config.CloudAppURL = appUrl config.CloudAppURL = appUrl
if currentCloudURL != apiUrl {
disconnectCloud(fmt.Errorf("cloud url changed from %s to %s", currentCloudURL, apiUrl))
}
if err := SaveConfig(); err != nil { if err := SaveConfig(); err != nil {
return fmt.Errorf("failed to save config: %w", err) return fmt.Errorf("failed to save config: %w", err)
} }