github.com/vmware/transport-go@v1.3.4/bus/store_stream.go (about)

     1  // Copyright 2019-2020 VMware, Inc.
     2  // SPDX-License-Identifier: BSD-2-Clause
     3  
     4  package bus
     5  
     6  import (
     7  	"fmt"
     8  	"sync"
     9  )
    10  
    11  type StoreChangeHandlerFunction func(change *StoreChange)
    12  
    13  // Interface for subscribing for store changes
    14  type StoreStream interface {
    15  	// Subscribe to the store changes stream.
    16  	Subscribe(handler StoreChangeHandlerFunction) error
    17  	// Unsubscribe from the stream.
    18  	Unsubscribe() error
    19  }
    20  
    21  type streamFilter struct {
    22  	states        []interface{}
    23  	itemId        string
    24  	matchAllItems bool
    25  }
    26  
    27  func (f *streamFilter) match(change *StoreChange) bool {
    28  	if f.matchAllItems || f.itemId == change.Id {
    29  		if len(f.states) == 0 {
    30  			return true
    31  		}
    32  
    33  		for _, s := range f.states {
    34  			if s == change.State {
    35  				return true
    36  			}
    37  		}
    38  
    39  	}
    40  	return false
    41  }
    42  
    43  type storeStream struct {
    44  	handler StoreChangeHandlerFunction
    45  	lock    sync.RWMutex
    46  	store   *busStore
    47  	filter  *streamFilter
    48  }
    49  
    50  func newStoreStream(store *busStore, filter *streamFilter) *storeStream {
    51  	stream := new(storeStream)
    52  	stream.store = store
    53  	stream.filter = filter
    54  	return stream
    55  }
    56  
    57  func (s *storeStream) Subscribe(handler StoreChangeHandlerFunction) error {
    58  	if handler == nil {
    59  		return fmt.Errorf("invalid StoreChangeHandlerFunction")
    60  	}
    61  
    62  	s.lock.Lock()
    63  	if s.handler != nil {
    64  		s.lock.Unlock()
    65  		return fmt.Errorf("stream already subscribed")
    66  	}
    67  	s.handler = handler
    68  	s.lock.Unlock()
    69  
    70  	s.store.onStreamSubscribe(s)
    71  	return nil
    72  }
    73  
    74  func (s *storeStream) Unsubscribe() error {
    75  	s.lock.Lock()
    76  	if s.handler == nil {
    77  		s.lock.Unlock()
    78  		return fmt.Errorf("stream not subscribed")
    79  	}
    80  	s.handler = nil
    81  	s.lock.Unlock()
    82  
    83  	s.store.onStreamUnsubscribe(s)
    84  	return nil
    85  }
    86  
    87  func (s *storeStream) onStoreChange(change *StoreChange) {
    88  	if !s.filter.match(change) {
    89  		return
    90  	}
    91  
    92  	s.lock.RLock()
    93  	defer s.lock.RUnlock()
    94  	if s.handler != nil {
    95  		go s.handler(change)
    96  	}
    97  }