channeldb+invoices: add ScanInvoices and integrate with InvoiceRegistry

This commit adds channeldb.ScanInvoices to scan through all invoices in
the database. The new call will also replace the already existing
channeldb.FetchAllInvoicesWithPaymentHash call in preparation to collect
invoices we'd like to delete and watch for expiry in one scan in later
commits.
This commit is contained in:
Andras Banki-Horvath
2020-07-28 21:22:23 +02:00
parent ba3c65bfd6
commit 92f3b0a30c
5 changed files with 90 additions and 148 deletions

View File

@@ -129,14 +129,11 @@ func (ew *InvoiceExpiryWatcher) prepareInvoice(
// AddInvoices adds multiple invoices to the InvoiceExpiryWatcher.
func (ew *InvoiceExpiryWatcher) AddInvoices(
invoices []channeldb.InvoiceWithPaymentHash) {
invoices map[lntypes.Hash]*channeldb.Invoice) {
invoicesWithExpiry := make([]*invoiceExpiry, 0, len(invoices))
for _, invoiceWithPaymentHash := range invoices {
newInvoiceExpiry := ew.prepareInvoice(
invoiceWithPaymentHash.PaymentHash,
&invoiceWithPaymentHash.Invoice,
)
for paymentHash, invoice := range invoices {
newInvoiceExpiry := ew.prepareInvoice(paymentHash, invoice)
if newInvoiceExpiry != nil {
invoicesWithExpiry = append(
invoicesWithExpiry, newInvoiceExpiry,

View File

@@ -158,24 +158,14 @@ func TestInvoiceExpiryWhenAddingMultipleInvoices(t *testing.T) {
t.Parallel()
test := newInvoiceExpiryWatcherTest(t, testTime, 5, 5)
var invoices []channeldb.InvoiceWithPaymentHash
invoices := make(map[lntypes.Hash]*channeldb.Invoice)
for hash, invoice := range test.testData.expiredInvoices {
invoices = append(invoices,
channeldb.InvoiceWithPaymentHash{
Invoice: *invoice,
PaymentHash: hash,
},
)
invoices[hash] = invoice
}
for hash, invoice := range test.testData.pendingInvoices {
invoices = append(invoices,
channeldb.InvoiceWithPaymentHash{
Invoice: *invoice,
PaymentHash: hash,
},
)
invoices[hash] = invoice
}
test.watcher.AddInvoices(invoices)

View File

@@ -147,21 +147,39 @@ func NewRegistry(cdb *channeldb.DB, expiryWatcher *InvoiceExpiryWatcher,
}
}
// populateExpiryWatcher fetches all active invoices and their corresponding
// payment hashes from ChannelDB and adds them to the expiry watcher.
func (i *InvoiceRegistry) populateExpiryWatcher() error {
pendingOnly := true
pendingInvoices, err := i.cdb.FetchAllInvoicesWithPaymentHash(pendingOnly)
if err != nil && err != channeldb.ErrNoInvoicesCreated {
log.Errorf(
"Error while prefetching active invoices from the database: %v", err,
)
// scanInvoicesOnStart will scan all invoices on start and add active invoices
// to the invoice expiry watcher.
func (i *InvoiceRegistry) scanInvoicesOnStart() error {
var pending map[lntypes.Hash]*channeldb.Invoice
reset := func() {
// Zero out our results on start and if the scan is ever run
// more than once. This latter case can happen if the kvdb
// layer needs to retry the View transaction underneath (eg.
// using the etcd driver, where all transactions are allowed
// to retry for serializability).
pending = make(map[lntypes.Hash]*channeldb.Invoice)
}
scanFunc := func(
paymentHash lntypes.Hash, invoice *channeldb.Invoice) error {
if invoice.IsPending() {
pending[paymentHash] = invoice
}
return nil
}
err := i.cdb.ScanInvoices(scanFunc, reset)
if err != nil {
return err
}
log.Debugf("Adding %d pending invoices to the expiry watcher",
len(pendingInvoices))
i.expiryWatcher.AddInvoices(pendingInvoices)
len(pending))
i.expiryWatcher.AddInvoices(pending)
return nil
}
@@ -178,8 +196,9 @@ func (i *InvoiceRegistry) Start() error {
i.wg.Add(1)
go i.invoiceEventLoop()
// Now prefetch all pending invoices to the expiry watcher.
err = i.populateExpiryWatcher()
// Now scan all pending and removable invoices to the expiry watcher or
// delete them.
err = i.scanInvoicesOnStart()
if err != nil {
i.Stop()
return err