diff --git a/docs/release-notes/release-notes-0.19.0.md b/docs/release-notes/release-notes-0.19.0.md index 156b71b5d..bd4b5d2c9 100644 --- a/docs/release-notes/release-notes-0.19.0.md +++ b/docs/release-notes/release-notes-0.19.0.md @@ -327,6 +327,7 @@ The underlying functionality between those two options remain the same. - [3](https://github.com/lightningnetwork/lnd/pull/9550) - [4](https://github.com/lightningnetwork/lnd/pull/9551) - [5](https://github.com/lightningnetwork/lnd/pull/9552) + - [6](https://github.com/lightningnetwork/lnd/pull/9555) * [Golang was updated to `v1.22.11`](https://github.com/lightningnetwork/lnd/pull/9462). diff --git a/graph/db/graph.go b/graph/db/graph.go index f926aaea3..b9891ffc2 100644 --- a/graph/db/graph.go +++ b/graph/db/graph.go @@ -2,6 +2,7 @@ package graphdb import ( "errors" + "fmt" "sync" "sync/atomic" "time" @@ -63,50 +64,18 @@ func NewChannelGraph(cfg *Config, options ...ChanGraphOption) (*ChannelGraph, return nil, err } - if !opts.useGraphCache { - return &ChannelGraph{ - KVStore: store, - quit: make(chan struct{}), - }, nil + g := &ChannelGraph{ + KVStore: store, + quit: make(chan struct{}), } // The graph cache can be turned off (e.g. for mobile users) for a // speed/memory usage tradeoff. - graphCache := NewGraphCache(opts.preAllocCacheNumNodes) - startTime := time.Now() - log.Debugf("Populating in-memory channel graph, this might take a " + - "while...") - - err = store.ForEachNodeCacheable(func(node route.Vertex, - features *lnwire.FeatureVector) error { - - graphCache.AddNodeFeatures(node, features) - - return nil - }) - if err != nil { - return nil, err + if opts.useGraphCache { + g.graphCache = NewGraphCache(opts.preAllocCacheNumNodes) } - err = store.ForEachChannel(func(info *models.ChannelEdgeInfo, - policy1, policy2 *models.ChannelEdgePolicy) error { - - graphCache.AddChannel(info, policy1, policy2) - - return nil - }) - if err != nil { - return nil, err - } - - log.Debugf("Finished populating in-memory channel graph (took %v, %s)", - time.Since(startTime), graphCache.Stats()) - - return &ChannelGraph{ - KVStore: store, - graphCache: graphCache, - quit: make(chan struct{}), - }, nil + return g, nil } // Start kicks off any goroutines required for the ChannelGraph to function. @@ -119,6 +88,13 @@ func (c *ChannelGraph) Start() error { log.Debugf("ChannelGraph starting") defer log.Debug("ChannelGraph started") + if c.graphCache != nil { + if err := c.populateCache(); err != nil { + return fmt.Errorf("could not populate the graph "+ + "cache: %w", err) + } + } + return nil } @@ -137,6 +113,42 @@ func (c *ChannelGraph) Stop() error { return nil } +// populateCache loads the entire channel graph into the in-memory graph cache. +// +// NOTE: This should only be called if the graphCache has been constructed. +func (c *ChannelGraph) populateCache() error { + startTime := time.Now() + log.Info("Populating in-memory channel graph, this might take a " + + "while...") + + err := c.KVStore.ForEachNodeCacheable(func(node route.Vertex, + features *lnwire.FeatureVector) error { + + c.graphCache.AddNodeFeatures(node, features) + + return nil + }) + if err != nil { + return err + } + + err = c.KVStore.ForEachChannel(func(info *models.ChannelEdgeInfo, + policy1, policy2 *models.ChannelEdgePolicy) error { + + c.graphCache.AddChannel(info, policy1, policy2) + + return nil + }) + if err != nil { + return err + } + + log.Infof("Finished populating in-memory channel graph (took %v, %s)", + time.Since(startTime), c.graphCache.Stats()) + + return nil +} + // ForEachNodeDirectedChannel iterates through all channels of a given node, // executing the passed callback on the directed edge representing the channel // and its incoming policy. If the callback returns an error, then the iteration