From 2dcc2d63a666815218533b53318cbe52afe6e714 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 29 Jun 2018 16:08:16 -0700 Subject: [PATCH] invoiceregistry: ensure we never send duplicate add/settle notifications MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- invoiceregistry.go | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/invoiceregistry.go b/invoiceregistry.go index ab38ea777..1ed3e95bf 100644 --- a/invoiceregistry.go +++ b/invoiceregistry.go @@ -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: