2018-07-27 15:54:40 +00:00
|
|
|
package rpcfilters
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"sync"
|
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/log"
|
2020-01-02 09:10:19 +00:00
|
|
|
|
2019-11-23 17:57:05 +00:00
|
|
|
"github.com/status-im/status-go/eth-node/types"
|
2018-07-27 15:54:40 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// transactionSentToUpstreamEvent represents an event that one can subscribe to
|
|
|
|
type transactionSentToUpstreamEvent struct {
|
|
|
|
sxMu sync.Mutex
|
2019-11-23 17:57:05 +00:00
|
|
|
sx map[int]chan types.Hash
|
|
|
|
listener chan types.Hash
|
2018-07-27 15:54:40 +00:00
|
|
|
quit chan struct{}
|
|
|
|
}
|
|
|
|
|
|
|
|
func newTransactionSentToUpstreamEvent() *transactionSentToUpstreamEvent {
|
|
|
|
return &transactionSentToUpstreamEvent{
|
2019-11-23 17:57:05 +00:00
|
|
|
sx: make(map[int]chan types.Hash),
|
|
|
|
listener: make(chan types.Hash),
|
2018-07-27 15:54:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *transactionSentToUpstreamEvent) Start() error {
|
|
|
|
if e.quit != nil {
|
|
|
|
return errors.New("latest transaction sent to upstream event is already started")
|
|
|
|
}
|
|
|
|
|
|
|
|
e.quit = make(chan struct{})
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case transactionHash := <-e.listener:
|
|
|
|
if e.numberOfSubscriptions() == 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
e.processTransactionSentToUpstream(transactionHash)
|
|
|
|
case <-e.quit:
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *transactionSentToUpstreamEvent) numberOfSubscriptions() int {
|
|
|
|
e.sxMu.Lock()
|
|
|
|
defer e.sxMu.Unlock()
|
|
|
|
return len(e.sx)
|
|
|
|
}
|
|
|
|
|
2019-11-23 17:57:05 +00:00
|
|
|
func (e *transactionSentToUpstreamEvent) processTransactionSentToUpstream(transactionHash types.Hash) {
|
2018-07-27 15:54:40 +00:00
|
|
|
|
|
|
|
e.sxMu.Lock()
|
|
|
|
defer e.sxMu.Unlock()
|
|
|
|
|
|
|
|
for id, channel := range e.sx {
|
|
|
|
select {
|
|
|
|
case channel <- transactionHash:
|
|
|
|
default:
|
|
|
|
log.Error("dropping messages %s for subscriotion %d because the channel is full", transactionHash, id)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *transactionSentToUpstreamEvent) Stop() {
|
|
|
|
if e.quit == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
select {
|
|
|
|
case <-e.quit:
|
|
|
|
return
|
|
|
|
default:
|
|
|
|
close(e.quit)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-23 17:57:05 +00:00
|
|
|
func (e *transactionSentToUpstreamEvent) Subscribe() (int, chan types.Hash) {
|
2018-07-27 15:54:40 +00:00
|
|
|
e.sxMu.Lock()
|
|
|
|
defer e.sxMu.Unlock()
|
|
|
|
|
2019-11-23 17:57:05 +00:00
|
|
|
channel := make(chan types.Hash, 512)
|
2018-07-27 15:54:40 +00:00
|
|
|
id := len(e.sx)
|
|
|
|
e.sx[id] = channel
|
|
|
|
return id, channel
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *transactionSentToUpstreamEvent) Unsubscribe(id int) {
|
|
|
|
e.sxMu.Lock()
|
|
|
|
defer e.sxMu.Unlock()
|
|
|
|
|
|
|
|
delete(e.sx, id)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Trigger gets called in order to trigger the event
|
2019-11-23 17:57:05 +00:00
|
|
|
func (e *transactionSentToUpstreamEvent) Trigger(transactionHash types.Hash) {
|
2018-07-27 15:54:40 +00:00
|
|
|
e.listener <- transactionHash
|
|
|
|
}
|