invoiceregistry: ensure we never send duplicate add/settle notifications

In this commit, we add additional logic to the primary notification
dispatch loop to ensure that we'll never send the same add/settle event
to the same client twice.

Consider the case where as we're sending a client its notification
backlog, a new invoice is settled (index=9). In this case, the database
will be reflected immediately, and the event will also be queued for
notifying later. We'll send out this latest event during the backlog
clear, but then will send it again once we return back to the main loop.

To ensure that this never happens, we'll now record the last index that
we’ve sent to a client to ensure that we no longer are able to send
duplicate notification events.
This commit is contained in:
Olaoluwa Osuntokun 2018-06-29 16:08:16 -07:00
parent 3bedffcc1a
commit 2dcc2d63a6
No known key found for this signature in database
GPG Key ID: 964EA263DD637C21

@ -135,14 +135,45 @@ func (i *invoiceRegistry) invoiceEventNotifier() {
// dispatch notifications to all registered clients.
case event := <-i.invoiceEvents:
for _, client := range i.notificationClients {
// Before we dispatch this event, we'll check
// to ensure that this client hasn't already
// received this notification in order to
// ensure we don't duplicate any events.
invoice := event.invoice
switch {
// If we've already sent this settle event to
// the client, then we can skip this.
case event.isSettle &&
client.settleIndex == invoice.SettleIndex:
continue
// Similarly, if we've already sent this add to
// the client then we can skip this one.
case !event.isSettle &&
client.addIndex == invoice.AddIndex:
continue
}
select {
case client.ntfnQueue.ChanIn() <- &invoiceEvent{
isSettle: event.isSettle,
invoice: event.invoice,
invoice: invoice,
}:
case <-i.quit:
return
}
// Each time we send a notification to a
// client, we'll record the latest add/settle
// index it has. We'll use this to ensure we
// don't send a notification twice, which can
// happen if a new event is added while we're
// catching up a new client.
if event.isSettle {
client.settleIndex = invoice.SettleIndex
} else {
client.addIndex = invoice.AddIndex
}
}
case <-i.quit: