diff --git a/README.md b/README.md index cc0d7c9..6336c15 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ ## Development -Run postgresql (user=postgresql, pass=postgresql): +Run postgresql (default user=postgres, default pass=postgrespassword): ``` $ make postgresql-test diff --git a/ethstats/migrations/02-nodeInfo.sql b/ethstats/migrations/02-nodeInfo.sql index 4638d19..2a38494 100644 --- a/ethstats/migrations/02-nodeInfo.sql +++ b/ethstats/migrations/02-nodeInfo.sql @@ -11,5 +11,6 @@ CREATE TABLE IF NOT EXISTS nodeinfo osver TEXT, client TEXT, history boolean, - created_at TIMESTAMP NOT NULL DEFAULT NOW() + extra_data json, + updated_at TIMESTAMP NOT NULL DEFAULT NOW() ); diff --git a/ethstats/state.go b/ethstats/state.go index e35dde3..8a4e799 100644 --- a/ethstats/state.go +++ b/ethstats/state.go @@ -4,6 +4,7 @@ import ( "crypto/rand" "database/sql" "embed" + "encoding/json" "fmt" "io/fs" "math/big" @@ -143,14 +144,37 @@ func (s *State) WriteBlock(b *Block) error { } func (s *State) GetNodeInfo(nodeID string) (*NodeInfo, error) { - info := NodeInfo{} - if err := s.db.Get(&info, "SELECT * FROM nodeinfo WHERE node_id=$1", nodeID); err != nil { + + info2 := NodeInfo2{} + if err := s.db.Get(&info2, "SELECT * FROM nodeinfo WHERE node_id=$1", nodeID); err != nil { if err == sql.ErrNoRows { return nil, nil } return nil, err } - return &info, nil + + data := make(map[string]string) + err := json.Unmarshal(info2.Data, &data) + if err != nil { + return nil, err + } + + info := &NodeInfo{ + Name: info2.Name, + Node: info2.Node, + Port: info2.Port, + Network: info2.Network, + Protocol: info2.Protocol, + API: info2.API, + Os: info2.Os, + OsVer: info2.OsVer, + Client: info2.Client, + History: info2.History, + Data: data, + UpdatedAt: info2.UpdatedAt, + } + + return info, nil } func (s *State) WriteNodeInfo(nodeInfo *NodeInfo) error { @@ -164,24 +188,40 @@ func (s *State) WriteNodeInfo(nodeInfo *NodeInfo) error { return err } + data, err := json.Marshal(nodeInfo.Data) + if err != nil { + return err + } + var count int row := tx.QueryRow(fmt.Sprintf(`SELECT count(*) FROM nodeinfo Where node_id='%s'`, nodeID)) if err := row.Scan(&count); err != nil { return err } if count == 1 { + updateQuery := `UPDATE nodeinfo SET node = $2, port = $3, network = $4, protocol = $5, api = $6, os = $7, osver = $8, client = $9, history = $10, extra_data = $11, updated_at = $12 + WHERE node_id=$1;` + + if _, err := tx.Exec(updateQuery, nodeInfo.Name, nodeInfo.Node, nodeInfo.Port, nodeInfo.Network, nodeInfo.Protocol, nodeInfo.API, nodeInfo.Os, nodeInfo.OsVer, nodeInfo.Client, nodeInfo.History, data, time.Now()); err != nil { + return err + } + + if err := tx.Commit(); err != nil { + return err + } + return nil } - query := `INSERT INTO nodeinfo("node_id", "node", "port", "network", "protocol", "api", "os", "osver", "client", "history") - values(:node_id, :node, :port, :network, :protocol, :api, :os, :osver, :client, :history)` + insertQuery := `INSERT INTO nodeinfo("node_id", "node", "port", "network", "protocol", "api", "os", "osver", "client", "history", "extra_data") + values($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)` - if _, err := tx.NamedExec(query, nodeInfo); err != nil { + if _, err := tx.Exec(insertQuery, nodeInfo.Name, nodeInfo.Node, nodeInfo.Port, nodeInfo.Network, nodeInfo.Protocol, nodeInfo.API, nodeInfo.Os, nodeInfo.OsVer, nodeInfo.Client, nodeInfo.History, data); err != nil { return err } // write the initial node stats row with empty values so we can update it later more efficiently - query = `INSERT INTO nodestats("node_id") VALUES ($1)` + query := `INSERT INTO nodestats("node_id") VALUES ($1)` if _, err := tx.Exec(query, nodeID); err != nil { return err diff --git a/ethstats/state_test.go b/ethstats/state_test.go index 487de52..5f05de3 100644 --- a/ethstats/state_test.go +++ b/ethstats/state_test.go @@ -88,7 +88,7 @@ func TestState_NodeInfo(t *testing.T) { info2, err := s.GetNodeInfo("a") assert.NoError(t, err) - info2.CreatedAt = time.Time{} + info2.UpdatedAt = time.Time{} assert.Equal(t, info, info2) // get stats should be available but empty diff --git a/ethstats/types.go b/ethstats/types.go index d47ec01..9b44a8f 100644 --- a/ethstats/types.go +++ b/ethstats/types.go @@ -34,6 +34,22 @@ type Block struct { // nodeInfo is the collection of meta information about a node that is displayed // on the monitoring page. type NodeInfo struct { + Name string `json:"name" db:"node_id"` + Node string `json:"node" db:"node"` + Port int `json:"port" db:"port"` + Network string `json:"net" db:"network"` + Protocol string `json:"protocol" db:"protocol"` + API string `json:"api" db:"api"` + Os string `json:"os" db:"os"` + OsVer string `json:"os_v" db:"osver"` + Client string `json:"client" db:"client"` + History bool `json:"canUpdateHistory" db:"history"` + Data map[string]string `json:"data" db:"extra_data"` + UpdatedAt time.Time `db:"updated_at"` +} + +// NodeInfo2 is similar to Nodeinfo with Data as array of bytes +type NodeInfo2 struct { Name string `json:"name" db:"node_id"` Node string `json:"node" db:"node"` Port int `json:"port" db:"port"` @@ -44,7 +60,8 @@ type NodeInfo struct { OsVer string `json:"os_v" db:"osver"` Client string `json:"client" db:"client"` History bool `json:"canUpdateHistory" db:"history"` - CreatedAt time.Time `db:"created_at"` + Data []byte `json:"data" db:"extra_data"` + UpdatedAt time.Time `db:"updated_at"` } // nodeStats is the information to report about the local node. diff --git a/main.go b/main.go index 701ad9c..b4cc304 100644 --- a/main.go +++ b/main.go @@ -12,7 +12,7 @@ import ( ) var ( - defaultDBEndpoint = "postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable" + defaultDBEndpoint = "postgres://postgres:postgrespassword@localhost:5432/postgres?sslmode=disable" ) func main() {