From bb75169022451a7ead197b045830f6485ddccc9c Mon Sep 17 00:00:00 2001
From: Jono Wenger <jono@elixxir.io>
Date: Mon, 21 Jun 2021 23:37:43 +0000
Subject: [PATCH] XX-3354 / add unregister to health tracker

---
 bindings/client.go          | 13 +++++++---
 interfaces/healthTracker.go |  6 +++--
 network/health/tracker.go   | 51 ++++++++++++++++++++++++++++++-------
 3 files changed, 55 insertions(+), 15 deletions(-)

diff --git a/bindings/client.go b/bindings/client.go
index caeb5f93d..4c25423e1 100644
--- a/bindings/client.go
+++ b/bindings/client.go
@@ -256,10 +256,15 @@ func (c *Client) IsNetworkHealthy() bool {
 	return c.api.GetHealth().IsHealthy()
 }
 
-// registers the network health callback to be called any time the network
-// health changes
-func (c *Client) RegisterNetworkHealthCB(nhc NetworkHealthCallback) {
-	c.api.GetHealth().AddFunc(nhc.Callback)
+// RegisterNetworkHealthCB registers the network health callback to be called
+// any time the network health changes. Returns a unique ID that can be used to
+// unregister the network health callback.
+func (c *Client) RegisterNetworkHealthCB(nhc NetworkHealthCallback) uint64 {
+	return c.api.GetHealth().AddFunc(nhc.Callback)
+}
+
+func (c *Client) UnregisterNetworkHealthCB(funcID uint64) {
+	c.api.GetHealth().RemoveFunc(funcID)
 }
 
 // RegisterListener records and installs a listener for messages
diff --git a/interfaces/healthTracker.go b/interfaces/healthTracker.go
index 39441984e..0d746d50f 100644
--- a/interfaces/healthTracker.go
+++ b/interfaces/healthTracker.go
@@ -8,8 +8,10 @@
 package interfaces
 
 type HealthTracker interface {
-	AddChannel(chan bool)
-	AddFunc(f func(bool))
+	AddChannel(chan bool) uint64
+	RemoveChannel(uint64)
+	AddFunc(f func(bool)) uint64
+	RemoveFunc(uint64)
 	IsHealthy() bool
 	WasHealthy() bool
 }
diff --git a/network/health/tracker.go b/network/health/tracker.go
index 637540b27..1e6dfdd97 100644
--- a/network/health/tracker.go
+++ b/network/health/tracker.go
@@ -24,8 +24,10 @@ type Tracker struct {
 
 	heartbeat chan network.Heartbeat
 
-	channels []chan bool
-	funcs    []func(isHealthy bool)
+	channels   map[uint64]chan bool
+	funcs      map[uint64]func(isHealthy bool)
+	channelsID uint64
+	funcsID    uint64
 
 	running bool
 
@@ -51,7 +53,8 @@ func Init(instance *network.Instance, timeout time.Duration) *Tracker {
 func newTracker(timeout time.Duration) *Tracker {
 	return &Tracker{
 		timeout:   timeout,
-		channels:  []chan bool{},
+		channels:  map[uint64]chan bool{},
+		funcs:     map[uint64]func(isHealthy bool){},
 		heartbeat: make(chan network.Heartbeat, 100),
 		isHealthy: false,
 		running:   false,
@@ -59,26 +62,56 @@ func newTracker(timeout time.Duration) *Tracker {
 }
 
 // AddChannel adds a channel to the list of Tracker channels such that each
-// channel can be notified of network changes.
-func (t *Tracker) AddChannel(c chan bool) {
+// channel can be notified of network changes.  Returns a unique ID for the
+// channel.
+func (t *Tracker) AddChannel(c chan bool) uint64 {
+	var currentID uint64
+
 	t.mux.Lock()
-	t.channels = append(t.channels, c)
+	t.channels[t.channelsID] = c
+	currentID = t.channelsID
+	t.channelsID++
 	t.mux.Unlock()
 
 	select {
 	case c <- t.IsHealthy():
 	default:
 	}
+
+	return currentID
+}
+
+// RemoveChannel removes the channel with the given ID from the list of Tracker
+// channels so that it will not longer be notified of network changes.
+func (t *Tracker) RemoveChannel(chanID uint64) {
+	t.mux.Lock()
+	delete(t.channels, chanID)
+	t.mux.Unlock()
 }
 
 // AddFunc adds a function to the list of Tracker functions such that each
-// function can be run after network changes.
-func (t *Tracker) AddFunc(f func(isHealthy bool)) {
+// function can be run after network changes. Returns a unique ID for the
+// function.
+func (t *Tracker) AddFunc(f func(isHealthy bool)) uint64 {
+	var currentID uint64
+
 	t.mux.Lock()
-	t.funcs = append(t.funcs, f)
+	t.funcs[t.funcsID] = f
+	currentID = t.funcsID
+	t.funcsID++
 	t.mux.Unlock()
 
 	go f(t.IsHealthy())
+
+	return currentID
+}
+
+// RemoveFunc removes the function with the given ID from the list of Tracker
+// functions so that it will not longer be run.
+func (t *Tracker) RemoveFunc(chanID uint64) {
+	t.mux.Lock()
+	delete(t.channels, chanID)
+	t.mux.Unlock()
 }
 
 func (t *Tracker) IsHealthy() bool {
-- 
GitLab