github.com/status-im/status-go@v1.1.0/services/ext/mailservers/connmonitor.go (about)

     1  package mailservers
     2  
     3  import (
     4  	"sync"
     5  	"time"
     6  
     7  	"github.com/ethereum/go-ethereum/log"
     8  
     9  	"github.com/status-im/status-go/eth-node/types"
    10  )
    11  
    12  // NewLastUsedConnectionMonitor returns pointer to the instance of LastUsedConnectionMonitor.
    13  func NewLastUsedConnectionMonitor(ps *PeerStore, cache *Cache, eventSub EnvelopeEventSubscriber) *LastUsedConnectionMonitor {
    14  	return &LastUsedConnectionMonitor{
    15  		ps:       ps,
    16  		cache:    cache,
    17  		eventSub: eventSub,
    18  	}
    19  }
    20  
    21  // LastUsedConnectionMonitor watches relevant events and reflects it in cache.
    22  type LastUsedConnectionMonitor struct {
    23  	ps    *PeerStore
    24  	cache *Cache
    25  
    26  	eventSub EnvelopeEventSubscriber
    27  
    28  	quit chan struct{}
    29  	wg   sync.WaitGroup
    30  }
    31  
    32  // Start spins a separate goroutine to watch connections.
    33  func (mon *LastUsedConnectionMonitor) Start() {
    34  	mon.quit = make(chan struct{})
    35  	mon.wg.Add(1)
    36  	go func() {
    37  		events := make(chan types.EnvelopeEvent, whisperEventsBuffer)
    38  		sub := mon.eventSub.SubscribeEnvelopeEvents(events)
    39  		defer sub.Unsubscribe()
    40  		defer mon.wg.Done()
    41  		for {
    42  			select {
    43  			case <-mon.quit:
    44  				return
    45  			case err := <-sub.Err():
    46  				log.Error("retry after error suscribing to eventSub events", "error", err)
    47  				return
    48  			case ev := <-events:
    49  				node := mon.ps.Get(ev.Peer)
    50  				if node == nil {
    51  					continue
    52  				}
    53  				if ev.Event == types.EventMailServerRequestCompleted {
    54  					err := mon.updateRecord(ev.Peer)
    55  					if err != nil {
    56  						log.Error("unable to update storage", "peer", ev.Peer, "error", err)
    57  					}
    58  				}
    59  			}
    60  		}
    61  	}()
    62  }
    63  
    64  func (mon *LastUsedConnectionMonitor) updateRecord(nodeID types.EnodeID) error {
    65  	node := mon.ps.Get(nodeID)
    66  	if node == nil {
    67  		return nil
    68  	}
    69  	return mon.cache.UpdateRecord(PeerRecord{node: node, LastUsed: time.Now()})
    70  }
    71  
    72  // Stop closes channel to signal a quit and waits until all goroutines are stoppped.
    73  func (mon *LastUsedConnectionMonitor) Stop() {
    74  	if mon.quit == nil {
    75  		return
    76  	}
    77  	select {
    78  	case <-mon.quit:
    79  		return
    80  	default:
    81  	}
    82  	close(mon.quit)
    83  	mon.wg.Wait()
    84  	mon.quit = nil
    85  }