• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lightningnetwork / lnd / 23572043051

26 Mar 2026 12:56AM UTC coverage: 52.204% (-9.9%) from 62.117%
23572043051

Pull #9985

github

web-flow
Merge d8d2a45f2 into 46fbc10fc
Pull Request #9985: multi: implement awareness of the final/production taproot channel variant

376 of 589 new or added lines in 25 files covered. (63.84%)

31494 existing lines in 479 files now uncovered.

101631 of 194681 relevant lines covered (52.2%)

2.16 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.39
/graph/db/graph_cache_state.go
1
package graphdb
2

3
import (
4
        "sync"
5
        "sync/atomic"
6
)
7

8
// pendingUpdatesWarnThreshold is the number of buffered cache mutations at
9
// which a warning is logged. A large buffer indicates that cache population is
10
// taking a long time relative to the incoming gossip rate.
11
const pendingUpdatesWarnThreshold = 10_000
12

13
// graphCacheState tracks the in-memory graph cache together with its
14
// population state. The underlying GraphCache is independently thread-safe, so
15
// once reads are allowed to use it, they do not need to hold updateMtx.
16
type graphCacheState struct {
17
        graphCache *GraphCache
18
        loaded     atomic.Bool
19
        failed     atomic.Bool
20

21
        updateMtx sync.Mutex
22
        loading   bool
23

24
        pendingUpdates []func(*GraphCache)
25
}
26

27
// newGraphCacheState constructs a graph cache state with a new cache instance.
28
func newGraphCacheState(preAllocNumNodes int) *graphCacheState {
4✔
29
        return &graphCacheState{
4✔
30
                graphCache: NewGraphCache(preAllocNumNodes),
4✔
31
        }
4✔
32
}
4✔
33

34
// isLoaded reports whether the cache has finished its initial population and
35
// is safe to serve reads from.
36
func (s *graphCacheState) isLoaded() bool {
4✔
37
        return s.loaded.Load()
4✔
38
}
4✔
39

40
// isFailed reports whether the cache population attempt has failed.
UNCOV
41
func (s *graphCacheState) isFailed() bool {
×
UNCOV
42
        return s.failed.Load()
×
UNCOV
43
}
×
44

45
// stats returns the cache stats if the cache has finished its initial
46
// population.
47
func (s *graphCacheState) stats() (string, bool) {
4✔
48
        if !s.isLoaded() {
6✔
49
                return "", false
2✔
50
        }
2✔
51

52
        return s.graphCache.Stats(), true
4✔
53
}
54

55
// beginPopulation marks the cache as loading and starts buffering concurrent
56
// cache mutations until the population pass completes.
57
func (s *graphCacheState) beginPopulation() {
4✔
58
        s.updateMtx.Lock()
4✔
59
        defer s.updateMtx.Unlock()
4✔
60

4✔
61
        s.loading = true
4✔
62
        s.pendingUpdates = nil
4✔
63
}
4✔
64

65
// finishPopulation replays any buffered mutations and marks the cache as ready
66
// when the initial population completed successfully. If population failed,
67
// buffered mutations are discarded since the cache won't be used for reads.
68
func (s *graphCacheState) finishPopulation(loaded bool) {
4✔
69
        s.updateMtx.Lock()
4✔
70
        defer s.updateMtx.Unlock()
4✔
71

4✔
72
        if loaded {
8✔
73
                for _, update := range s.pendingUpdates {
6✔
74
                        update(s.graphCache)
2✔
75
                }
2✔
76

77
                s.loaded.Store(true)
4✔
UNCOV
78
        } else {
×
UNCOV
79
                s.failed.Store(true)
×
UNCOV
80
        }
×
81

82
        s.pendingUpdates = nil
4✔
83
        s.loading = false
4✔
84
}
85

86
// applyUpdate applies a cache mutation immediately or buffers it when the
87
// cache is still being populated.
88
func (s *graphCacheState) applyUpdate(update func(cache *GraphCache)) {
4✔
89
        s.updateMtx.Lock()
4✔
90
        defer s.updateMtx.Unlock()
4✔
91

4✔
92
        if s.loading {
6✔
93
                s.pendingUpdates = append(s.pendingUpdates, update)
2✔
94

2✔
95
                if len(s.pendingUpdates)%pendingUpdatesWarnThreshold == 0 {
2✔
96
                        log.Warnf("Graph cache has %d pending updates "+
×
97
                                "buffered during population",
×
98
                                len(s.pendingUpdates))
×
99
                }
×
100

101
                return
2✔
102
        }
103

104
        update(s.graphCache)
4✔
105
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc