diff --git a/config/version b/config/version index 69fd8687..98610aa4 100644 --- a/config/version +++ b/config/version @@ -1 +1 @@ -v1.6.1 \ No newline at end of file +v1.6.2 \ No newline at end of file diff --git a/database/db.go b/database/db.go index 62cf1f11..53e52922 100644 --- a/database/db.go +++ b/database/db.go @@ -266,6 +266,15 @@ func buildMariaDBDSN(dbConfig config.DBConfig) string { return cfg.FormatDSN() } +// OpenMariaDB opens a new MariaDB connection from the given config. +// Caller must close the returned db when done. +func OpenMariaDB(dbConfig config.DBConfig) (*gorm.DB, error) { + dsn := buildMariaDBDSN(dbConfig) + return gorm.Open(mysql.Open(dsn), &gorm.Config{ + Logger: logger.Discard, + }) +} + // initMariaDB opens a MariaDB connection and runs model migrations. func initMariaDB() error { dbConfig := config.GetDBConfigFromJSON() diff --git a/web/controller/node.go b/web/controller/node.go index 01a44d08..59dc6684 100644 --- a/web/controller/node.go +++ b/web/controller/node.go @@ -7,6 +7,7 @@ import ( "github.com/mhsanaei/3x-ui/v2/config" "github.com/mhsanaei/3x-ui/v2/database" + "github.com/mhsanaei/3x-ui/v2/database/model" "github.com/gin-gonic/gin" ) @@ -41,10 +42,33 @@ type NodeView struct { LastError string `json:"lastError"` } +// getNodeStatesFromShared queries node_states from the shared MariaDB. +// In shared mode, the master may use SQLite locally, so we must query +// the shared MariaDB directly to see worker heartbeats. +func getNodeStatesFromShared() ([]model.NodeState, error) { + // If current DB is already MariaDB, use it directly + if config.GetDBTypeFromJSON() == "mariadb" { + return database.GetNodeStates() + } + + // Otherwise, open a temporary connection to the shared MariaDB + dbConfig := config.GetDBConfigFromJSON() + db, err := database.OpenMariaDB(dbConfig) + if err != nil { + return nil, err + } + sqlDB, _ := db.DB() + defer sqlDB.Close() + + var states []model.NodeState + err = db.Order("node_id").Find(&states).Error + return states, err +} + // list returns connected nodes. Master sees all workers; worker sees the master. func (a *NodeController) list(c *gin.Context) { nodeCfg := config.GetNodeConfigFromJSON() - states, err := database.GetNodeStates() + states, err := getNodeStatesFromShared() if err != nil { jsonMsg(c, "get node states", err) return