github.com/status-im/status-go@v1.1.0/services/subscriptions/subscription.go (about)

     1  package subscriptions
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"sync"
     7  	"time"
     8  )
     9  
    10  type SubscriptionID string
    11  
    12  type Subscription struct {
    13  	mu      sync.RWMutex
    14  	id      SubscriptionID
    15  	signal  *filterSignal
    16  	quit    chan struct{}
    17  	filter  filter
    18  	started bool
    19  }
    20  
    21  func NewSubscription(namespace string, filter filter) *Subscription {
    22  	subscriptionID := NewSubscriptionID(namespace, filter.getID())
    23  	return &Subscription{
    24  		id:     subscriptionID,
    25  		signal: newFilterSignal(string(subscriptionID)),
    26  		filter: filter,
    27  	}
    28  }
    29  
    30  func (s *Subscription) Start(checkPeriod time.Duration) error {
    31  	s.mu.Lock()
    32  	if s.started {
    33  		s.mu.Unlock()
    34  		return errors.New("subscription already started or used")
    35  	}
    36  	s.started = true
    37  	s.quit = make(chan struct{})
    38  	quit := s.quit
    39  	s.mu.Unlock()
    40  
    41  	ticker := time.NewTicker(checkPeriod)
    42  	defer ticker.Stop()
    43  
    44  	for {
    45  		select {
    46  		case <-ticker.C:
    47  			filterData, err := s.filter.getChanges()
    48  			if err != nil {
    49  				s.signal.SendError(err)
    50  			} else if len(filterData) > 0 {
    51  				s.signal.SendData(filterData)
    52  			}
    53  		case <-quit:
    54  			return nil
    55  		}
    56  	}
    57  }
    58  
    59  func (s *Subscription) Stop(uninstall bool) error {
    60  	s.mu.Lock()
    61  	defer s.mu.Unlock()
    62  	if !s.started {
    63  		return nil
    64  	}
    65  	select {
    66  	case _, ok := <-s.quit:
    67  		// handle a case of a closed channel
    68  		if !ok {
    69  			return nil
    70  		}
    71  	default:
    72  		close(s.quit)
    73  	}
    74  	if !uninstall {
    75  		return nil
    76  	}
    77  	return s.filter.uninstall()
    78  }
    79  
    80  func NewSubscriptionID(namespace, filterID string) SubscriptionID {
    81  	return SubscriptionID(fmt.Sprintf("%s-%s", namespace, filterID))
    82  }