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

lightningnetwork / lnd / 24453602233

15 Apr 2026 12:08PM UTC coverage: 51.23% (-11.0%) from 62.198%
24453602233

Pull #10732

github

web-flow
Merge d307aaaa7 into 3fc674161
Pull Request #10732: channeldb: split channel close into two phases to avoid long DB write-locks

201 of 321 new or added lines in 4 files covered. (62.62%)

24474 existing lines in 293 files now uncovered.

115853 of 226144 relevant lines covered (51.23%)

19478.77 hits per line

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

88.24
/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 {
168✔
29
        return &graphCacheState{
168✔
30
                graphCache: NewGraphCache(preAllocNumNodes),
168✔
31
        }
168✔
32
}
168✔
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 {
1,329✔
37
        return s.loaded.Load()
1,329✔
38
}
1,329✔
39

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

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

52
        return s.graphCache.Stats(), true
241✔
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() {
168✔
58
        s.updateMtx.Lock()
168✔
59
        defer s.updateMtx.Unlock()
168✔
60

168✔
61
        s.loading = true
168✔
62
        s.pendingUpdates = nil
168✔
63
}
168✔
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) {
168✔
69
        s.updateMtx.Lock()
168✔
70
        defer s.updateMtx.Unlock()
168✔
71

168✔
72
        if loaded {
333✔
73
                for _, update := range s.pendingUpdates {
166✔
74
                        update(s.graphCache)
1✔
75
                }
1✔
76

77
                s.loaded.Store(true)
165✔
78
        } else {
3✔
79
                s.failed.Store(true)
3✔
80
        }
3✔
81

82
        s.pendingUpdates = nil
168✔
83
        s.loading = false
168✔
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)) {
6,063✔
89
        s.updateMtx.Lock()
6,063✔
90
        defer s.updateMtx.Unlock()
6,063✔
91

6,063✔
92
        if s.loading {
6,064✔
93
                s.pendingUpdates = append(s.pendingUpdates, update)
1✔
94

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

101
                return
1✔
102
        }
103

104
        update(s.graphCache)
6,062✔
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