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

lightningnetwork / lnd / 12281843618

11 Dec 2024 05:38PM UTC coverage: 49.477% (-0.06%) from 49.54%
12281843618

Pull #9242

github

aakselrod
docs: update release-notes for 0.19.0
Pull Request #9242: Reapply #8644

6 of 27 new or added lines in 2 files covered. (22.22%)

170 existing lines in 20 files now uncovered.

100257 of 202632 relevant lines covered (49.48%)

1.54 hits per line

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

59.32
/batch/batch.go
1
package batch
2

3
import (
4
        "errors"
5
        "sync"
6

7
        "github.com/lightningnetwork/lnd/kvdb"
8
        "github.com/lightningnetwork/lnd/sqldb"
9
)
10

11
// errSolo is a sentinel error indicating that the requester should re-run the
12
// operation in isolation.
13
var errSolo = errors.New(
14
        "batch function returned an error and should be re-run solo",
15
)
16

17
type request struct {
18
        *Request
19
        errChan chan error
20
}
21

22
type batch struct {
23
        db     kvdb.Backend
24
        start  sync.Once
25
        reqs   []*request
26
        clear  func(b *batch)
27
        locker sync.Locker
28
}
29

30
// trigger is the entry point for the batch and ensures that run is started at
31
// most once.
32
func (b *batch) trigger() {
3✔
33
        b.start.Do(b.run)
3✔
34
}
3✔
35

36
// run executes the current batch of requests. If any individual requests fail
37
// alongside others they will be retried by the caller.
38
func (b *batch) run() {
3✔
39
        // Clear the batch from its scheduler, ensuring that no new requests are
3✔
40
        // added to this batch.
3✔
41
        b.clear(b)
3✔
42

3✔
43
        // If a cache lock was provided, hold it until the this method returns.
3✔
44
        // This is critical for ensuring external consistency of the operation,
3✔
45
        // so that caches don't get out of sync with the on disk state.
3✔
46
        if b.locker != nil {
6✔
47
                b.locker.Lock()
3✔
48
                defer b.locker.Unlock()
3✔
49
        }
3✔
50

51
        // Apply the batch until a subset succeeds or all of them fail. Requests
52
        // that fail will be retried individually.
53
        for len(b.reqs) > 0 {
6✔
54
                var failIdx = -1
3✔
55
                err := kvdb.Update(b.db, func(tx kvdb.RwTx) error {
6✔
56
                        for i, req := range b.reqs {
6✔
57
                                err := req.Update(tx)
3✔
58
                                if err != nil {
3✔
NEW
59
                                        // If we get a serialization error, we
×
NEW
60
                                        // want the underlying SQL retry
×
NEW
61
                                        // mechanism to retry the entire batch.
×
NEW
62
                                        // Otherwise, we can succeed in an
×
NEW
63
                                        // sqldb retry and still re-execute the
×
NEW
64
                                        // failing request individually.
×
NEW
65
                                        dbErr := sqldb.MapSQLError(err)
×
NEW
66
                                        if !sqldb.IsSerializationError(dbErr) {
×
NEW
67
                                                failIdx = i
×
NEW
68

×
NEW
69
                                                return err
×
NEW
70
                                        }
×
71

NEW
72
                                        return dbErr
×
73
                                }
74
                        }
75
                        return nil
3✔
76
                }, func() {
3✔
77
                        for _, req := range b.reqs {
6✔
78
                                if req.Reset != nil {
6✔
79
                                        req.Reset()
3✔
80
                                }
3✔
81
                        }
82
                })
83

84
                // If a request's Update failed, extract it and re-run the
85
                // batch. The removed request will be retried individually by
86
                // the caller.
87
                if failIdx >= 0 {
3✔
88
                        req := b.reqs[failIdx]
×
89

×
90
                        // It's safe to shorten b.reqs here because the
×
91
                        // scheduler's batch no longer points to us.
×
92
                        b.reqs[failIdx] = b.reqs[len(b.reqs)-1]
×
93
                        b.reqs = b.reqs[:len(b.reqs)-1]
×
94

×
95
                        // Tell the submitter re-run it solo, continue with the
×
96
                        // rest of the batch.
×
97
                        req.errChan <- errSolo
×
98
                        continue
×
99
                }
100

101
                // None of the remaining requests failed, process the errors
102
                // using each request's OnCommit closure and return the error
103
                // to the requester. If no OnCommit closure is provided, simply
104
                // return the error directly.
105
                for _, req := range b.reqs {
6✔
106
                        if req.OnCommit != nil {
6✔
107
                                req.errChan <- req.OnCommit(err)
3✔
108
                        } else {
6✔
109
                                req.errChan <- err
3✔
110
                        }
3✔
111
                }
112

113
                return
3✔
114
        }
115
}
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

© 2025 Coveralls, Inc