github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/services/helpers/rpcbroadcaster/broadcaster.go (about) 1 package rpcbroadcaster 2 3 import ( 4 "time" 5 6 "go.uber.org/zap" 7 ) 8 9 // RPCBroadcaster represents a generic RPC broadcaster. 10 type RPCBroadcaster struct { 11 Clients map[string]*RPCClient 12 Log *zap.Logger 13 Responses chan []any 14 15 close chan struct{} 16 finished chan struct{} 17 sendTimeout time.Duration 18 } 19 20 // NewRPCBroadcaster returns a new RPC broadcaster instance. 21 func NewRPCBroadcaster(log *zap.Logger, sendTimeout time.Duration) *RPCBroadcaster { 22 return &RPCBroadcaster{ 23 Clients: make(map[string]*RPCClient), 24 Log: log, 25 close: make(chan struct{}), 26 finished: make(chan struct{}), 27 Responses: make(chan []any), 28 sendTimeout: sendTimeout, 29 } 30 } 31 32 // Run implements oracle.Broadcaster. 33 func (r *RPCBroadcaster) Run() { 34 for _, c := range r.Clients { 35 go c.run() 36 } 37 run: 38 for { 39 select { 40 case <-r.close: 41 break run 42 case ps := <-r.Responses: 43 for _, c := range r.Clients { 44 select { 45 case c.responses <- ps: 46 default: 47 c.log.Error("can't send response, channel is full") 48 } 49 } 50 } 51 } 52 for _, c := range r.Clients { 53 <-c.finished 54 } 55 drain: 56 for { 57 select { 58 case <-r.Responses: 59 default: 60 break drain 61 } 62 } 63 close(r.Responses) 64 close(r.finished) 65 } 66 67 // SendParams sends a request using all clients if the broadcaster is active. 68 func (r *RPCBroadcaster) SendParams(params []any) { 69 select { 70 case <-r.close: 71 case r.Responses <- params: 72 } 73 } 74 75 // Shutdown implements oracle.Broadcaster. The same instance can't be Run again 76 // after the shutdown. 77 func (r *RPCBroadcaster) Shutdown() { 78 close(r.close) 79 <-r.finished 80 }