Skip to content

Instantly share code, notes, and snippets.

@dimroc
Created December 20, 2018 13:14
Show Gist options
  • Save dimroc/d7a44d784b36a1811b756258d79ec8f8 to your computer and use it in GitHub Desktop.
Save dimroc/d7a44d784b36a1811b756258d79ec8f8 to your computer and use it in GitHub Desktop.
diff --git a/services/application.go b/services/application.go
index 39573a5b..3d5c0cad 100644
--- a/services/application.go
+++ b/services/application.go
@@ -43,7 +43,7 @@ type ChainlinkApplication struct {
BulkRunDeleter SleeperTask
pendingConnectionResumer *pendingConnectionResumer
bridgeTypeMutex sync.Mutex
- jobSubscriberID, txManagerID, connectionResumerID string
+ jobSubscriberID, txManagerID, connectionResumerID int
}
// NewApplication initializes a new store if one is not already
diff --git a/services/head_tracker.go b/services/head_tracker.go
index 962c7f51..58284719 100644
--- a/services/head_tracker.go
+++ b/services/head_tracker.go
@@ -3,11 +3,11 @@ package services
import (
"errors"
"fmt"
+ "sort"
"sync"
"time"
"github.com/asdine/storm"
- uuid "github.com/satori/go.uuid"
"github.com/smartcontractkit/chainlink/logger"
"github.com/smartcontractkit/chainlink/store"
strpkg "github.com/smartcontractkit/chainlink/store"
@@ -21,14 +21,14 @@ import (
// in a thread safe manner. Reconstitutes the last block number from the data
// store on reboot.
type HeadTracker struct {
- trackerIDs map[string]store.HeadTrackable
- sortedTrackerIDs []string // map order is non-deterministic, so keep order.
+ trackers map[int]store.HeadTrackable
+ trackersNonce int // Used to generate a sortable ID for trackers
+ trackersMutex sync.RWMutex
headers chan models.BlockHeader
headSubscription models.EthSubscription
store *strpkg.Store
head *models.IndexableBlockNumber
headMutex sync.RWMutex
- trackersMutex sync.RWMutex
connected *abool.AtomicBool
sleeper utils.Sleeper
done chan struct{}
@@ -49,11 +49,10 @@ func NewHeadTracker(store *strpkg.Store, sleepers ...utils.Sleeper) *HeadTracker
sleeper = utils.NewBackoffSleeper()
}
return &HeadTracker{
- store: store,
- trackerIDs: map[string]strpkg.HeadTrackable{},
- sortedTrackerIDs: []string{},
- sleeper: sleeper,
- connected: abool.New(),
+ store: store,
+ trackers: map[int]strpkg.HeadTrackable{},
+ sleeper: sleeper,
+ connected: abool.New(),
}
}
@@ -127,12 +126,12 @@ func (ht *HeadTracker) Head() *models.IndexableBlockNumber {
// Attach registers an object that will have HeadTrackable events fired on occurence,
// such as Connect.
-func (ht *HeadTracker) Attach(t store.HeadTrackable) string {
+func (ht *HeadTracker) Attach(t store.HeadTrackable) int {
ht.trackersMutex.Lock()
defer ht.trackersMutex.Unlock()
- id := uuid.Must(uuid.NewV4()).String()
- ht.trackerIDs[id] = t
- ht.sortedTrackerIDs = append(ht.sortedTrackerIDs, id)
+ id := ht.trackersNonce
+ ht.trackersNonce++
+ ht.trackers[id] = t
if ht.connected.IsSet() {
logger.WarnIf(t.Connect(ht.Head()))
}
@@ -140,34 +139,14 @@ func (ht *HeadTracker) Attach(t store.HeadTrackable) string {
}
// Detach deregisters an object from having HeadTrackable events fired.
-func (ht *HeadTracker) Detach(id string) {
+func (ht *HeadTracker) Detach(id int) {
ht.trackersMutex.Lock()
defer ht.trackersMutex.Unlock()
- t, present := ht.trackerIDs[id]
+ t, present := ht.trackers[id]
if ht.connected.IsSet() && present {
t.Disconnect()
}
- if present {
- ht.sortedTrackerIDs = removeTrackerID(id, ht.sortedTrackerIDs, t)
- }
- delete(ht.trackerIDs, id)
-}
-
-func removeTrackerID(id string, old []string, t store.HeadTrackable) []string {
- idx := indexOf(id, old)
- if idx == -1 {
- logger.Panicf("invariant violated: id %s for %T exists in trackerIDs but not in sortedTrackerIDs in HeadTracker", id, t)
- }
- return append(old[:idx], old[idx+1:]...)
-}
-
-func indexOf(value string, arr []string) int {
- for i, v := range arr {
- if v == value {
- return i
- }
- }
- return -1
+ delete(ht.trackers, id)
}
// Connected returns whether or not this HeadTracker is connected.
@@ -176,25 +155,37 @@ func (ht *HeadTracker) Connected() bool { return ht.connected.IsSet() }
func (ht *HeadTracker) connect(bn *models.IndexableBlockNumber) {
ht.trackersMutex.RLock()
defer ht.trackersMutex.RUnlock()
- for _, id := range ht.sortedTrackerIDs {
- logger.WarnIf(ht.trackerIDs[id].Connect(bn))
+ for _, id := range sortedTrackerKeys(ht.trackers) {
+ logger.WarnIf(ht.trackers[id].Connect(bn))
}
}
func (ht *HeadTracker) disconnect() {
ht.trackersMutex.RLock()
defer ht.trackersMutex.RUnlock()
- for _, id := range ht.sortedTrackerIDs {
- ht.trackerIDs[id].Disconnect()
+ for _, id := range sortedTrackerKeys(ht.trackers) {
+ ht.trackers[id].Disconnect()
}
}
func (ht *HeadTracker) onNewHead(head *models.BlockHeader) {
ht.trackersMutex.RLock()
defer ht.trackersMutex.RUnlock()
- for _, id := range ht.sortedTrackerIDs {
- ht.trackerIDs[id].OnNewHead(head)
+ // sorts on every block! bad!
+ for _, id := range sortedTrackerKeys(ht.trackers) {
+ ht.trackers[id].OnNewHead(head)
+ }
+}
+
+func sortedTrackerKeys(m map[int]store.HeadTrackable) []int {
+ keys := make([]int, len(m))
+ i := 0
+ for k := range m {
+ keys[i] = k
+ i++
}
+ sort.Ints(keys)
+ return keys
}
func (ht *HeadTracker) listenForNewHeads() {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment