Skip to content

Commit 2da701c

Browse files
committed
graph/db+sqldb: impl PruneGraphNodes
Which lets us run `TestChannelEdgePruningUpdateIndexDeletion` against our SQL backends.
1 parent 102c04d commit 2da701c

File tree

5 files changed

+146
-1
lines changed

5 files changed

+146
-1
lines changed

graph/db/graph_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3291,7 +3291,7 @@ func TestPruneGraphNodes(t *testing.T) {
32913291
t.Parallel()
32923292
ctx := context.Background()
32933293

3294-
graph := MakeTestGraph(t)
3294+
graph := MakeTestGraphNew(t)
32953295

32963296
// We'll start off by inserting our source node, to ensure that it's
32973297
// the only node left after we prune the graph.

graph/db/sql_store.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

sqldb/sqlc/graph.sql.go

Lines changed: 55 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sqldb/sqlc/querier.go

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sqldb/sqlc/queries/graph.sql

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,31 @@ SELECT EXISTS (
6565
AND n.pub_key = $1
6666
);
6767

68+
-- name: GetUnconnectedNodes :many
69+
SELECT n.id, n.pub_key
70+
FROM nodes n
71+
-- Select all nodes that do not have any channels.
72+
WHERE NOT EXISTS (
73+
SELECT 1
74+
FROM channels c
75+
WHERE c.node_id_1 = n.id OR c.node_id_2 = n.id
76+
)
77+
-- Ignore any of our source nodes.
78+
AND NOT EXISTS (
79+
SELECT 1
80+
FROM source_nodes sn
81+
WHERE sn.node_id = n.id
82+
);
83+
6884
-- name: DeleteNodeByPubKey :execresult
6985
DELETE FROM nodes
7086
WHERE pub_key = $1
7187
AND version = $2;
7288

89+
-- name: DeleteNode :exec
90+
DELETE FROM nodes
91+
WHERE id = $1;
92+
7393
/* ─────────────────────────────────────────────
7494
node_features table queries
7595
─────────────────────────────────────────────

0 commit comments

Comments
 (0)