@@ -63,7 +63,9 @@ type SQLQueries interface {
6363 ListNodesPaginated (ctx context.Context , arg sqlc.ListNodesPaginatedParams ) ([]sqlc.Node , error )
6464 ListNodeIDsAndPubKeys (ctx context.Context , arg sqlc.ListNodeIDsAndPubKeysParams ) ([]sqlc.ListNodeIDsAndPubKeysRow , error )
6565 IsPublicV1Node (ctx context.Context , pubKey []byte ) (bool , error )
66+ GetUnconnectedNodes (ctx context.Context ) ([]sqlc.GetUnconnectedNodesRow , error )
6667 DeleteNodeByPubKey (ctx context.Context , arg sqlc.DeleteNodeByPubKeyParams ) (sql.Result , error )
68+ DeleteNode (ctx context.Context , id int64 ) error
6769
6870 GetExtraNodeTypes (ctx context.Context , nodeID int64 ) ([]sqlc.NodeExtraType , error )
6971 UpsertNodeExtraType (ctx context.Context , arg sqlc.UpsertNodeExtraTypeParams ) error
@@ -2200,6 +2202,70 @@ func (s *SQLStore) FilterKnownChanIDs(chansInfo []ChannelUpdateInfo) ([]uint64,
22002202 return newChanIDs , knownZombies , nil
22012203}
22022204
2205+ // PruneGraphNodes is a garbage collection method which attempts to prune out
2206+ // any nodes from the channel graph that are currently unconnected. This ensure
2207+ // that we only maintain a graph of reachable nodes. In the event that a pruned
2208+ // node gains more channels, it will be re-added back to the graph.
2209+ //
2210+ // NOTE: this prunes nodes across protocol versions. It will never prune the
2211+ // source nodes.
2212+ //
2213+ // NOTE: part of the V1Store interface.
2214+ func (s * SQLStore ) PruneGraphNodes () ([]route.Vertex , error ) {
2215+ var ctx = context .TODO ()
2216+
2217+ var prunedNodes []route.Vertex
2218+ err := s .db .ExecTx (ctx , sqldb .WriteTxOpt (), func (db SQLQueries ) error {
2219+ var err error
2220+ prunedNodes , err = s .pruneGraphNodes (ctx , db )
2221+
2222+ return err
2223+ }, func () {
2224+ prunedNodes = nil
2225+ })
2226+ if err != nil {
2227+ return nil , fmt .Errorf ("unable to prune nodes: %w" , err )
2228+ }
2229+
2230+ return prunedNodes , nil
2231+ }
2232+
2233+ // pruneGraphNodes deletes any node in the DB that doesn't have a channel.
2234+ //
2235+ // NOTE: this prunes nodes across protocol versions. It will never prune the
2236+ // source nodes.
2237+ func (s * SQLStore ) pruneGraphNodes (ctx context.Context ,
2238+ db SQLQueries ) ([]route.Vertex , error ) {
2239+
2240+ // Fetch all un-connected nodes from the database.
2241+ // NOTE: this will not include any nodes that are listed in the
2242+ // source table.
2243+ nodes , err := db .GetUnconnectedNodes (ctx )
2244+ if err != nil {
2245+ return nil , fmt .Errorf ("unable to fetch unconnected nodes: %w" ,
2246+ err )
2247+ }
2248+
2249+ prunedNodes := make ([]route.Vertex , 0 , len (nodes ))
2250+ for _ , node := range nodes {
2251+ // TODO(elle): update to use sqlc.slice() once that works.
2252+ if err = db .DeleteNode (ctx , node .ID ); err != nil {
2253+ return nil , fmt .Errorf ("unable to delete " +
2254+ "node(id=%d): %w" , node .ID , err )
2255+ }
2256+
2257+ pubKey , err := route .NewVertexFromBytes (node .PubKey )
2258+ if err != nil {
2259+ return nil , fmt .Errorf ("unable to parse pubkey " +
2260+ "for node(id=%d): %w" , node .ID , err )
2261+ }
2262+
2263+ prunedNodes = append (prunedNodes , pubKey )
2264+ }
2265+
2266+ return prunedNodes , nil
2267+ }
2268+
22032269// forEachNodeDirectedChannel iterates through all channels of a given
22042270// node, executing the passed callback on the directed edge representing the
22052271// channel and its incoming policy. If the node is not found, no error is
0 commit comments