github.com/number571/tendermint@v0.34.11-gost/libs/pubsub/subscription.go (about)

     1  package pubsub
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  
     7  	"github.com/number571/tendermint/abci/types"
     8  	tmsync "github.com/number571/tendermint/internal/libs/sync"
     9  	"github.com/google/uuid"
    10  )
    11  
    12  var (
    13  	// ErrUnsubscribed is returned by Err when a client unsubscribes.
    14  	ErrUnsubscribed = errors.New("client unsubscribed")
    15  
    16  	// ErrOutOfCapacity is returned by Err when a client is not pulling messages
    17  	// fast enough. Note the client's subscription will be terminated.
    18  	ErrOutOfCapacity = errors.New("client is not pulling messages fast enough")
    19  )
    20  
    21  // A Subscription represents a client subscription for a particular query and
    22  // consists of three things:
    23  // 1) channel onto which messages and events are published
    24  // 2) channel which is closed if a client is too slow or choose to unsubscribe
    25  // 3) err indicating the reason for (2)
    26  type Subscription struct {
    27  	id  string
    28  	out chan Message
    29  
    30  	canceled chan struct{}
    31  	mtx      tmsync.RWMutex
    32  	err      error
    33  }
    34  
    35  // NewSubscription returns a new subscription with the given outCapacity.
    36  func NewSubscription(outCapacity int) *Subscription {
    37  	return &Subscription{
    38  		id:       uuid.NewString(),
    39  		out:      make(chan Message, outCapacity),
    40  		canceled: make(chan struct{}),
    41  	}
    42  }
    43  
    44  // Out returns a channel onto which messages and events are published.
    45  // Unsubscribe/UnsubscribeAll does not close the channel to avoid clients from
    46  // receiving a nil message.
    47  func (s *Subscription) Out() <-chan Message {
    48  	return s.out
    49  }
    50  
    51  func (s *Subscription) ID() string { return s.id }
    52  
    53  // Canceled returns a channel that's closed when the subscription is
    54  // terminated and supposed to be used in a select statement.
    55  func (s *Subscription) Canceled() <-chan struct{} {
    56  	return s.canceled
    57  }
    58  
    59  // Err returns nil if the channel returned by Canceled is not yet closed.
    60  // If the channel is closed, Err returns a non-nil error explaining why:
    61  //   - ErrUnsubscribed if the subscriber choose to unsubscribe,
    62  //   - ErrOutOfCapacity if the subscriber is not pulling messages fast enough
    63  //   and the channel returned by Out became full,
    64  // After Err returns a non-nil error, successive calls to Err return the same
    65  // error.
    66  func (s *Subscription) Err() error {
    67  	s.mtx.RLock()
    68  	defer s.mtx.RUnlock()
    69  	return s.err
    70  }
    71  
    72  func (s *Subscription) cancel(err error) {
    73  	s.mtx.Lock()
    74  	defer s.mtx.Unlock()
    75  	defer func() {
    76  		perr := recover()
    77  		if err == nil && perr != nil {
    78  			err = fmt.Errorf("problem closing subscription: %v", perr)
    79  		}
    80  	}()
    81  
    82  	if s.err == nil && err != nil {
    83  		s.err = err
    84  	}
    85  
    86  	close(s.canceled)
    87  }
    88  
    89  // Message glues data and events together.
    90  type Message struct {
    91  	subID  string
    92  	data   interface{}
    93  	events []types.Event
    94  }
    95  
    96  func NewMessage(subID string, data interface{}, events []types.Event) Message {
    97  	return Message{
    98  		subID:  subID,
    99  		data:   data,
   100  		events: events,
   101  	}
   102  }
   103  
   104  // SubscriptionID returns the unique identifier for the subscription
   105  // that produced this message.
   106  func (msg Message) SubscriptionID() string { return msg.subID }
   107  
   108  // Data returns an original data published.
   109  func (msg Message) Data() interface{} { return msg.data }
   110  
   111  // Events returns events, which matched the client's query.
   112  func (msg Message) Events() []types.Event { return msg.events }