Skip to content

Commit f9d29f9

Browse files
authored
Merge pull request #9513 from ellemouton/graph5
graph+routing: refactor to remove `graphsession`
2 parents b08bc99 + f380500 commit f9d29f9

18 files changed

+223
-330
lines changed

docs/release-notes/release-notes-0.19.0.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,13 +248,16 @@ The underlying functionality between those two options remain the same.
248248
* Graph abstraction work:
249249
- [Abstract autopilot access](https://github.com/lightningnetwork/lnd/pull/9480)
250250
- [Abstract invoicerpc server access](https://github.com/lightningnetwork/lnd/pull/9516)
251+
- [Refactor to hide DB transactions](https://github.com/lightningnetwork/lnd/pull/9513)
252+
253+
* [Golang was updated to
254+
`v1.22.11`](https://github.com/lightningnetwork/lnd/pull/9462).
251255

252256
* Move funding transaction validation to the gossiper
253257
[1](https://github.com/lightningnetwork/lnd/pull/9476)
254258
[2](https://github.com/lightningnetwork/lnd/pull/9477)
255259
[3](https://github.com/lightningnetwork/lnd/pull/9478).
256260

257-
258261
## Breaking Changes
259262
## Performance Improvements
260263

graph/db/graph.go

Lines changed: 98 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -403,16 +403,6 @@ func initChannelGraph(db kvdb.Backend) error {
403403
return nil
404404
}
405405

406-
// NewPathFindTx returns a new read transaction that can be used for a single
407-
// path finding session. Will return nil if the graph cache is enabled.
408-
func (c *ChannelGraph) NewPathFindTx() (kvdb.RTx, error) {
409-
if c.graphCache != nil {
410-
return nil, nil
411-
}
412-
413-
return c.db.BeginReadTx()
414-
}
415-
416406
// AddrsForNode returns all known addresses for the target node public key that
417407
// the graph DB is aware of. The returned boolean indicates if the given node is
418408
// unknown to the graph DB or not.
@@ -500,13 +490,14 @@ func (c *ChannelGraph) ForEachChannel(cb func(*models.ChannelEdgeInfo,
500490
}, func() {})
501491
}
502492

503-
// ForEachNodeDirectedChannel iterates through all channels of a given node,
493+
// forEachNodeDirectedChannel iterates through all channels of a given node,
504494
// executing the passed callback on the directed edge representing the channel
505495
// and its incoming policy. If the callback returns an error, then the iteration
506-
// is halted with the error propagated back up to the caller.
496+
// is halted with the error propagated back up to the caller. An optional read
497+
// transaction may be provided. If none is provided, a new one will be created.
507498
//
508499
// Unknown policies are passed into the callback as nil values.
509-
func (c *ChannelGraph) ForEachNodeDirectedChannel(tx kvdb.RTx,
500+
func (c *ChannelGraph) forEachNodeDirectedChannel(tx kvdb.RTx,
510501
node route.Vertex, cb func(channel *DirectedChannel) error) error {
511502

512503
if c.graphCache != nil {
@@ -517,7 +508,7 @@ func (c *ChannelGraph) ForEachNodeDirectedChannel(tx kvdb.RTx,
517508
toNodeCallback := func() route.Vertex {
518509
return node
519510
}
520-
toNodeFeatures, err := c.FetchNodeFeatures(node)
511+
toNodeFeatures, err := c.fetchNodeFeatures(tx, node)
521512
if err != nil {
522513
return err
523514
}
@@ -561,17 +552,18 @@ func (c *ChannelGraph) ForEachNodeDirectedChannel(tx kvdb.RTx,
561552
return nodeTraversal(tx, node[:], c.db, dbCallback)
562553
}
563554

564-
// FetchNodeFeatures returns the features of a given node. If no features are
565-
// known for the node, an empty feature vector is returned.
566-
func (c *ChannelGraph) FetchNodeFeatures(
555+
// fetchNodeFeatures returns the features of a given node. If no features are
556+
// known for the node, an empty feature vector is returned. An optional read
557+
// transaction may be provided. If none is provided, a new one will be created.
558+
func (c *ChannelGraph) fetchNodeFeatures(tx kvdb.RTx,
567559
node route.Vertex) (*lnwire.FeatureVector, error) {
568560

569561
if c.graphCache != nil {
570562
return c.graphCache.GetFeatures(node), nil
571563
}
572564

573565
// Fallback that uses the database.
574-
targetNode, err := c.FetchLightningNode(node)
566+
targetNode, err := c.FetchLightningNodeTx(tx, node)
575567
switch err {
576568
// If the node exists and has features, return them directly.
577569
case nil:
@@ -588,6 +580,34 @@ func (c *ChannelGraph) FetchNodeFeatures(
588580
}
589581
}
590582

583+
// ForEachNodeDirectedChannel iterates through all channels of a given node,
584+
// executing the passed callback on the directed edge representing the channel
585+
// and its incoming policy. If the callback returns an error, then the iteration
586+
// is halted with the error propagated back up to the caller. If the graphCache
587+
// is available, then it will be used to retrieve the node's channels instead
588+
// of the database.
589+
//
590+
// Unknown policies are passed into the callback as nil values.
591+
//
592+
// NOTE: this is part of the graphdb.NodeTraverser interface.
593+
func (c *ChannelGraph) ForEachNodeDirectedChannel(nodePub route.Vertex,
594+
cb func(channel *DirectedChannel) error) error {
595+
596+
return c.forEachNodeDirectedChannel(nil, nodePub, cb)
597+
}
598+
599+
// FetchNodeFeatures returns the features of the given node. If no features are
600+
// known for the node, an empty feature vector is returned.
601+
// If the graphCache is available, then it will be used to retrieve the node's
602+
// features instead of the database.
603+
//
604+
// NOTE: this is part of the graphdb.NodeTraverser interface.
605+
func (c *ChannelGraph) FetchNodeFeatures(nodePub route.Vertex) (
606+
*lnwire.FeatureVector, error) {
607+
608+
return c.fetchNodeFeatures(nil, nodePub)
609+
}
610+
591611
// ForEachNodeCached is similar to forEachNode, but it utilizes the channel
592612
// graph cache instead. Note that this doesn't return all the information the
593613
// regular forEachNode method does.
@@ -617,8 +637,8 @@ func (c *ChannelGraph) ForEachNodeCached(cb func(node route.Vertex,
617637
toNodeCallback := func() route.Vertex {
618638
return node.PubKeyBytes
619639
}
620-
toNodeFeatures, err := c.FetchNodeFeatures(
621-
node.PubKeyBytes,
640+
toNodeFeatures, err := c.fetchNodeFeatures(
641+
tx, node.PubKeyBytes,
622642
)
623643
if err != nil {
624644
return err
@@ -3873,6 +3893,64 @@ func (c *ChannelGraph) IsClosedScid(scid lnwire.ShortChannelID) (bool, error) {
38733893
return isClosed, nil
38743894
}
38753895

3896+
// GraphSession will provide the call-back with access to a NodeTraverser
3897+
// instance which can be used to perform queries against the channel graph. If
3898+
// the graph cache is not enabled, then the call-back will be provided with
3899+
// access to the graph via a consistent read-only transaction.
3900+
func (c *ChannelGraph) GraphSession(cb func(graph NodeTraverser) error) error {
3901+
var (
3902+
tx kvdb.RTx
3903+
err error
3904+
commit = func() {}
3905+
)
3906+
if c.graphCache == nil {
3907+
tx, err = c.db.BeginReadTx()
3908+
if err != nil {
3909+
return err
3910+
}
3911+
3912+
commit = func() {
3913+
if err := tx.Rollback(); err != nil {
3914+
log.Errorf("Unable to rollback tx: %v", err)
3915+
}
3916+
}
3917+
}
3918+
defer commit()
3919+
3920+
return cb(&nodeTraverserSession{
3921+
db: c,
3922+
tx: tx,
3923+
})
3924+
}
3925+
3926+
// nodeTraverserSession implements the NodeTraverser interface but with a
3927+
// backing read only transaction for a consistent view of the graph in the case
3928+
// where the graph Cache has not been enabled.
3929+
type nodeTraverserSession struct {
3930+
tx kvdb.RTx
3931+
db *ChannelGraph
3932+
}
3933+
3934+
// ForEachNodeDirectedChannel calls the callback for every channel of the given
3935+
// node.
3936+
//
3937+
// NOTE: Part of the NodeTraverser interface.
3938+
func (c *nodeTraverserSession) ForEachNodeDirectedChannel(nodePub route.Vertex,
3939+
cb func(channel *DirectedChannel) error) error {
3940+
3941+
return c.db.forEachNodeDirectedChannel(c.tx, nodePub, cb)
3942+
}
3943+
3944+
// FetchNodeFeatures returns the features of the given node. If the node is
3945+
// unknown, assume no additional features are supported.
3946+
//
3947+
// NOTE: Part of the NodeTraverser interface.
3948+
func (c *nodeTraverserSession) FetchNodeFeatures(nodePub route.Vertex) (
3949+
*lnwire.FeatureVector, error) {
3950+
3951+
return c.db.fetchNodeFeatures(c.tx, nodePub)
3952+
}
3953+
38763954
func putLightningNode(nodeBucket kvdb.RwBucket, aliasBucket kvdb.RwBucket, // nolint:dupl
38773955
updateIndex kvdb.RwBucket, node *models.LightningNode) error {
38783956

graph/db/graph_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3915,7 +3915,7 @@ func BenchmarkForEachChannel(b *testing.B) {
39153915
}
39163916
}
39173917

3918-
// TestGraphCacheForEachNodeChannel tests that the ForEachNodeDirectedChannel
3918+
// TestGraphCacheForEachNodeChannel tests that the forEachNodeDirectedChannel
39193919
// method works as expected, and is able to handle nil self edges.
39203920
func TestGraphCacheForEachNodeChannel(t *testing.T) {
39213921
graph, err := MakeTestGraph(t)
@@ -3952,7 +3952,7 @@ func TestGraphCacheForEachNodeChannel(t *testing.T) {
39523952

39533953
getSingleChannel := func() *DirectedChannel {
39543954
var ch *DirectedChannel
3955-
err = graph.ForEachNodeDirectedChannel(nil, node1.PubKeyBytes,
3955+
err = graph.forEachNodeDirectedChannel(nil, node1.PubKeyBytes,
39563956
func(c *DirectedChannel) error {
39573957
require.Nil(t, ch)
39583958
ch = c

graph/db/interfaces.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package graphdb
22

33
import (
44
"github.com/lightningnetwork/lnd/graph/db/models"
5+
"github.com/lightningnetwork/lnd/lnwire"
56
"github.com/lightningnetwork/lnd/routing/route"
67
)
78

@@ -23,3 +24,16 @@ type NodeRTx interface {
2324
// the same transaction.
2425
FetchNode(node route.Vertex) (NodeRTx, error)
2526
}
27+
28+
// NodeTraverser is an abstract read only interface that provides information
29+
// about nodes and their edges. The interface is about providing fast read-only
30+
// access to the graph and so if a cache is available, it should be used.
31+
type NodeTraverser interface {
32+
// ForEachNodeDirectedChannel calls the callback for every channel of
33+
// the given node.
34+
ForEachNodeDirectedChannel(nodePub route.Vertex,
35+
cb func(channel *DirectedChannel) error) error
36+
37+
// FetchNodeFeatures returns the features of the given node.
38+
FetchNodeFeatures(nodePub route.Vertex) (*lnwire.FeatureVector, error)
39+
}

graph/graphsession/graph_session.go

Lines changed: 0 additions & 141 deletions
This file was deleted.

routing/bandwidth.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ func newBandwidthManager(graph Graph, sourceNode route.Vertex,
6363

6464
// First, we'll collect the set of outbound edges from the target
6565
// source node and add them to our bandwidth manager's map of channels.
66-
err := graph.ForEachNodeChannel(sourceNode,
66+
err := graph.ForEachNodeDirectedChannel(sourceNode,
6767
func(channel *graphdb.DirectedChannel) error {
6868
shortID := lnwire.NewShortChanIDFromInt(
6969
channel.ChannelID,

0 commit comments

Comments
 (0)