erigon-pulse/cl/sentinel/service/notifiers.go
a 436493350e
Sentinel refactor (#8296)
1. changes sentinel to use an http-like interface

2. moves hexutil, crypto/blake2b, metrics packages to erigon-lib
2023-10-22 01:17:18 +02:00

85 lines
1.8 KiB
Go

package service
import (
"fmt"
"sync"
"github.com/ledgerwatch/erigon-lib/gointerfaces/sentinel"
)
const (
maxSubscribers = 100 // only 100 clients per sentinel
)
type gossipObject struct {
data []byte // gossip data
t sentinel.GossipType // determine which gossip message we are notifying of
pid string // pid is the peer id of the sender
blobIndex *uint32 // index of the blob
}
type gossipNotifier struct {
notifiers []chan gossipObject
mu sync.Mutex
}
func newGossipNotifier() *gossipNotifier {
return &gossipNotifier{
notifiers: make([]chan gossipObject, 0, maxSubscribers),
}
}
func (g *gossipNotifier) notify(t sentinel.GossipType, data []byte, pid string) {
g.mu.Lock()
defer g.mu.Unlock()
for _, ch := range g.notifiers {
ch <- gossipObject{
data: data,
t: t,
pid: pid,
}
}
}
func (g *gossipNotifier) notifyBlob(t sentinel.GossipType, data []byte, pid string, blobIndex int) {
g.mu.Lock()
defer g.mu.Unlock()
index := new(uint32)
*index = uint32(blobIndex)
for _, ch := range g.notifiers {
ch <- gossipObject{
data: data,
t: t,
pid: pid,
blobIndex: index,
}
}
}
func (g *gossipNotifier) addSubscriber() (chan gossipObject, int, error) {
g.mu.Lock()
defer g.mu.Unlock()
if len(g.notifiers) >= maxSubscribers {
return nil, -1, fmt.Errorf("too many subsribers, try again later")
}
ch := make(chan gossipObject)
g.notifiers = append(g.notifiers, ch)
return ch, len(g.notifiers) - 1, nil
}
func (g *gossipNotifier) removeSubscriber(id int) error {
g.mu.Lock()
defer g.mu.Unlock()
if len(g.notifiers) <= id {
return fmt.Errorf("invalid id, no subscription exist with this id")
}
close(g.notifiers[id])
g.notifiers = append(g.notifiers[:id], g.notifiers[id+1:]...)
return nil
}