@@ -2,6 +2,7 @@ package http
22
33import (
44 "encoding/json"
5+ "fmt"
56 "net/http"
67 "os"
78 "sort"
@@ -696,60 +697,8 @@ func InitServer(log *logrus.Logger, db *gorm.DB, statsService *service.StatsServ
696697 // Get all unique peers
697698 peerMap := make (map [string ]* PeerStat )
698699
699- // Collect peers from messages table
700- type PeerInfo struct {
701- Peer string
702- Count int64
703- FirstSeen string
704- LastSeen string
705- }
706- var messagePeers []PeerInfo
707- if err := db .Table ("messages" ).
708- Select ("peer, COUNT(*) as count, MIN(received_at) as first_seen, MAX(received_at) as last_seen" ).
709- Where ("peer != ''" ).
710- Group ("peer" ).
711- Find (& messagePeers ).Error ; err == nil {
712- for _ , p := range messagePeers {
713- // Parse time strings - try multiple formats
714- var firstSeen , lastSeen time.Time
715- var err error
716-
717- // Try different time formats that SQLite might return
718- timeFormats := []string {
719- "2006-01-02 15:04:05" ,
720- "2006-01-02T15:04:05Z" ,
721- "2006-01-02T15:04:05" ,
722- time .RFC3339 ,
723- }
724-
725- for _ , format := range timeFormats {
726- if firstSeen , err = time .Parse (format , p .FirstSeen ); err == nil {
727- break
728- }
729- }
730- if err != nil {
731- firstSeen = time .Now () // fallback
732- }
733-
734- for _ , format := range timeFormats {
735- if lastSeen , err = time .Parse (format , p .LastSeen ); err == nil {
736- break
737- }
738- }
739- if err != nil {
740- lastSeen = time .Now () // fallback
741- }
742-
743- peerMap [p .Peer ] = & PeerStat {
744- PeerID : p .Peer ,
745- TotalMessages : p .Count ,
746- FirstSeen : firstSeen ,
747- LastSeen : lastSeen ,
748- Networks : []string {},
749- MessageTypes : make (map [string ]int64 ),
750- }
751- }
752- }
700+ // Skip querying the non-existent messages table - the database has been optimized
701+ // to use specialized tables (blocks, subtrees, node_statuses, rejected_txes)
753702
754703 // Add data from specialized tables
755704 // Blocks
@@ -761,43 +710,38 @@ func InitServer(log *logrus.Logger, db *gorm.DB, statsService *service.StatsServ
761710 LastSeen string
762711 }
763712
764- // Helper function to process specialized tables
713+ // Optimized helper function to process specialized tables with less memory overhead
765714 processPeerTable := func (tableName , messageType string ) {
766715 var peers []PeerTableInfo
767- if err := db .Table (tableName ).
768- Select ("peer_id, network, COUNT(*) as count, MIN(received_at) as first_seen, MAX(received_at) as last_seen" ).
769- Where ("peer_id != ''" ).
770- Group ("peer_id, network" ).
771- Find (& peers ).Error ; err == nil {
716+ // Use raw SQL for better performance with large datasets
717+ query := fmt .Sprintf (`
718+ SELECT peer_id, network, COUNT(*) as count,
719+ MIN(received_at) as first_seen,
720+ MAX(received_at) as last_seen
721+ FROM %s
722+ WHERE peer_id != ''
723+ GROUP BY peer_id, network` , tableName )
724+
725+ if err := db .Raw (query ).Scan (& peers ).Error ; err == nil {
772726 for _ , p := range peers {
773- // Parse time strings - try multiple formats
727+ // Use Go's built-in time parsing which handles SQLite format
774728 var firstSeen , lastSeen time.Time
775- var err error
776-
777- // Try different time formats that SQLite might return
778- timeFormats := []string {
779- "2006-01-02 15:04:05" ,
780- "2006-01-02T15:04:05Z" ,
781- "2006-01-02T15:04:05" ,
782- time .RFC3339 ,
783- }
784729
785- for _ , format := range timeFormats {
786- if firstSeen , err = time .Parse (format , p .FirstSeen ); err == nil {
787- break
788- }
730+ // SQLite returns timestamps in RFC3339 format by default
731+ firstSeen , _ = time .Parse (time . RFC3339 , p .FirstSeen )
732+ if firstSeen . IsZero () {
733+ firstSeen , _ = time . Parse ( "2006-01-02 15:04:05" , p . FirstSeen )
789734 }
790- if err != nil {
791- firstSeen = time .Now () // fallback
735+ if firstSeen . IsZero () {
736+ firstSeen = time .Now ()
792737 }
793738
794- for _ , format := range timeFormats {
795- if lastSeen , err = time .Parse (format , p .LastSeen ); err == nil {
796- break
797- }
739+ lastSeen , _ = time .Parse (time .RFC3339 , p .LastSeen )
740+ if lastSeen .IsZero () {
741+ lastSeen , _ = time .Parse ("2006-01-02 15:04:05" , p .LastSeen )
798742 }
799- if err != nil {
800- lastSeen = time .Now () // fallback
743+ if lastSeen . IsZero () {
744+ lastSeen = time .Now ()
801745 }
802746
803747 if stat , exists := peerMap [p .PeerID ]; exists {
@@ -836,6 +780,8 @@ func InitServer(log *logrus.Logger, db *gorm.DB, statsService *service.StatsServ
836780 peerMap [p .PeerID ].MessageTypes [messageType ] = p .Count
837781 }
838782 }
783+ } else if err != nil {
784+ logrus .Printf ("Error querying %s table for peer stats: %v" , tableName , err )
839785 }
840786 }
841787
@@ -845,6 +791,46 @@ func InitServer(log *logrus.Logger, db *gorm.DB, statsService *service.StatsServ
845791 processPeerTable ("rejected_txes" , "rejected_tx" )
846792 processPeerTable ("node_statuses" , "node_status" )
847793
794+ // Get latest user agent and best height from node_statuses for each peer
795+ type NodeStatusInfo struct {
796+ PeerID string
797+ UserAgent string
798+ BestHeight uint32
799+ }
800+ var nodeStatuses []NodeStatusInfo
801+ query := `
802+ SELECT DISTINCT ON (peer_id)
803+ peer_id,
804+ user_agent,
805+ best_height
806+ FROM node_statuses
807+ WHERE peer_id != ''
808+ ORDER BY peer_id, received_at DESC`
809+
810+ if db .Dialector .Name () == "sqlite" {
811+ // SQLite doesn't support DISTINCT ON, use a different approach
812+ query = `
813+ SELECT peer_id, user_agent, best_height
814+ FROM node_statuses ns1
815+ WHERE peer_id != ''
816+ AND received_at = (
817+ SELECT MAX(received_at)
818+ FROM node_statuses ns2
819+ WHERE ns2.peer_id = ns1.peer_id
820+ )`
821+ }
822+
823+ if err := db .Raw (query ).Scan (& nodeStatuses ).Error ; err == nil {
824+ for _ , ns := range nodeStatuses {
825+ if stat , exists := peerMap [ns .PeerID ]; exists {
826+ stat .LastUserAgent = ns .UserAgent
827+ stat .LastBestHeight = ns .BestHeight
828+ }
829+ }
830+ } else {
831+ logrus .Printf ("Error querying node_statuses for user agent and best height: %v" , err )
832+ }
833+
848834 // Convert map to slice and sort by total messages
849835 peers := make ([]PeerStat , 0 , len (peerMap ))
850836 for _ , peer := range peerMap {
0 commit comments