neo-go/pkg/services/helpers/rpcbroadcaster/broadcaster.go
Anna Shaleva 6b21ad9922 *: replace interface{} with any keyword
Everywhere including examples, external interop APIs, bindings generators
code and in other valuable places. A couple of `interface{}` usages are
intentionally left in the CHANGELOG.md, documentation and tests.
2023-04-04 13:22:42 +03:00

80 lines
1.5 KiB
Go

package rpcbroadcaster
import (
"time"
"go.uber.org/zap"
)
// RPCBroadcaster represents a generic RPC broadcaster.
type RPCBroadcaster struct {
Clients map[string]*RPCClient
Log *zap.Logger
Responses chan []any
close chan struct{}
finished chan struct{}
sendTimeout time.Duration
}
// NewRPCBroadcaster returns a new RPC broadcaster instance.
func NewRPCBroadcaster(log *zap.Logger, sendTimeout time.Duration) *RPCBroadcaster {
return &RPCBroadcaster{
Clients: make(map[string]*RPCClient),
Log: log,
close: make(chan struct{}),
finished: make(chan struct{}),
Responses: make(chan []any),
sendTimeout: sendTimeout,
}
}
// Run implements oracle.Broadcaster.
func (r *RPCBroadcaster) Run() {
for _, c := range r.Clients {
go c.run()
}
run:
for {
select {
case <-r.close:
break run
case ps := <-r.Responses:
for _, c := range r.Clients {
select {
case c.responses <- ps:
default:
c.log.Error("can't send response, channel is full")
}
}
}
}
for _, c := range r.Clients {
<-c.finished
}
drain:
for {
select {
case <-r.Responses:
default:
break drain
}
}
close(r.Responses)
close(r.finished)
}
// SendParams sends a request using all clients if the broadcaster is active.
func (r *RPCBroadcaster) SendParams(params []any) {
select {
case <-r.close:
case r.Responses <- params:
}
}
// Shutdown implements oracle.Broadcaster. The same instance can't be Run again
// after the shutdown.
func (r *RPCBroadcaster) Shutdown() {
close(r.close)
<-r.finished
}