github.com/glide-im/glide@v1.6.0/pkg/subscription/subscription_impl/subscription.go (about)

     1  package subscription_impl
     2  
     3  import (
     4  	"errors"
     5  	"github.com/glide-im/glide/pkg/gate"
     6  	"github.com/glide-im/glide/pkg/store"
     7  	"github.com/glide-im/glide/pkg/subscription"
     8  	"sync"
     9  )
    10  
    11  var _ subscription.Subscribe = (*subscriptionImpl)(nil)
    12  
    13  type subscriptionImpl struct {
    14  	unwrap *realSubscription
    15  }
    16  
    17  func NewSubscription(store store.SubscriptionStore, seqStore ChannelSequenceStore) subscription.Subscribe {
    18  	return &subscriptionImpl{
    19  		unwrap: newRealSubscription(store, seqStore),
    20  	}
    21  }
    22  
    23  func (s *subscriptionImpl) UpdateSubscriber(id subscription.ChanID, updates []subscription.Update) error {
    24  
    25  	var errs []error
    26  
    27  	for _, update := range updates {
    28  		var err error
    29  		switch update.Flag {
    30  		case subscription.SubscriberSubscribe:
    31  			err = s.unwrap.Subscribe(id, update.ID, update.Extra)
    32  		case subscription.SubscriberUnsubscribe:
    33  			err = s.unwrap.UnSubscribe(id, update.ID)
    34  		case subscription.SubscriberUpdate:
    35  			err = s.unwrap.UpdateSubscriber(id, update.ID, update.Extra)
    36  		default:
    37  			return subscription.ErrUnknownFlag
    38  		}
    39  		if err != nil {
    40  			errs = append(errs, err)
    41  		}
    42  	}
    43  	if len(errs) == 0 {
    44  		return nil
    45  	}
    46  
    47  	errMsg := ""
    48  	for _, err := range errs {
    49  		errMsg += err.Error() + "\n"
    50  	}
    51  
    52  	return errors.New(errMsg)
    53  }
    54  
    55  func (s *subscriptionImpl) UpdateChannel(id subscription.ChanID, update subscription.ChannelUpdate) error {
    56  
    57  	switch update.Flag {
    58  	case subscription.ChanCreate:
    59  		info, ok := update.Extra.(*subscription.ChanInfo)
    60  		if !ok {
    61  			return errors.New("invalid channel info")
    62  		}
    63  		return s.unwrap.CreateChannel(id, info)
    64  	case subscription.ChanUpdate:
    65  		info, ok := update.Extra.(*subscription.ChanInfo)
    66  		if !ok {
    67  			return errors.New("invalid channel info")
    68  		}
    69  		return s.unwrap.UpdateChannel(id, info)
    70  	case subscription.ChanDelete:
    71  		return s.unwrap.RemoveChannel(id)
    72  	default:
    73  		return subscription.ErrUnknownFlag
    74  	}
    75  }
    76  
    77  func (s *subscriptionImpl) PublishMessage(id subscription.ChanID, message subscription.Message) error {
    78  	return s.unwrap.Publish(id, message)
    79  }
    80  
    81  func (s *subscriptionImpl) SetGateInterface(g gate.DefaultGateway) {
    82  	s.unwrap.gate = g
    83  }
    84  
    85  var _ SubscribeWrap = (*realSubscription)(nil)
    86  
    87  type realSubscription struct {
    88  	mu       sync.RWMutex
    89  	channels map[subscription.ChanID]subscription.Channel
    90  	store    store.SubscriptionStore
    91  	seqStore ChannelSequenceStore
    92  	gate     gate.DefaultGateway
    93  }
    94  
    95  func newRealSubscription(msgStore store.SubscriptionStore, seqStore ChannelSequenceStore) *realSubscription {
    96  	return &realSubscription{
    97  		mu:       sync.RWMutex{},
    98  		channels: make(map[subscription.ChanID]subscription.Channel),
    99  		store:    msgStore,
   100  		seqStore: seqStore,
   101  	}
   102  }
   103  
   104  func (u *realSubscription) Subscribe(chID subscription.ChanID, sbID subscription.SubscriberID, extra interface{}) error {
   105  	u.mu.RLock()
   106  	defer u.mu.RUnlock()
   107  
   108  	ch, ok := u.channels[chID]
   109  	if !ok {
   110  		return errors.New(subscription.ErrChanNotExist)
   111  	}
   112  	return ch.Subscribe(sbID, extra)
   113  }
   114  
   115  func (u *realSubscription) UnSubscribe(chID subscription.ChanID, id subscription.SubscriberID) error {
   116  	u.mu.RLock()
   117  	defer u.mu.RUnlock()
   118  
   119  	ch, ok := u.channels[chID]
   120  	if !ok {
   121  		return errors.New(subscription.ErrChanNotExist)
   122  	}
   123  
   124  	return ch.Unsubscribe(id)
   125  }
   126  
   127  func (u *realSubscription) UpdateSubscriber(chID subscription.ChanID, id subscription.SubscriberID, update interface{}) error {
   128  	u.mu.RLock()
   129  	defer u.mu.RUnlock()
   130  
   131  	ch, ok := u.channels[chID]
   132  	if !ok {
   133  		return errors.New(subscription.ErrChanNotExist)
   134  	}
   135  	return ch.Subscribe(id, update)
   136  }
   137  
   138  func (u *realSubscription) RemoveChannel(chID subscription.ChanID) error {
   139  	u.mu.Lock()
   140  	defer u.mu.Unlock()
   141  
   142  	_, ok := u.channels[chID]
   143  	if !ok {
   144  		return errors.New(subscription.ErrChanNotExist)
   145  	}
   146  	delete(u.channels, chID)
   147  	return nil
   148  }
   149  
   150  func (u *realSubscription) CreateChannel(chID subscription.ChanID, update *subscription.ChanInfo) error {
   151  	u.mu.Lock()
   152  	defer u.mu.Unlock()
   153  
   154  	if _, ok := u.channels[chID]; ok {
   155  		return errors.New(subscription.ErrChanAlreadyExists)
   156  	}
   157  
   158  	channel, err := NewChannel(chID, u.gate, u.store, u.seqStore)
   159  	if err != nil {
   160  		return err
   161  	}
   162  	u.channels[chID] = channel
   163  	return nil
   164  }
   165  
   166  func (u *realSubscription) UpdateChannel(chID subscription.ChanID, update *subscription.ChanInfo) error {
   167  	u.mu.RLock()
   168  	defer u.mu.RUnlock()
   169  
   170  	ch, ok := u.channels[chID]
   171  	if !ok {
   172  		return errors.New(subscription.ErrChanNotExist)
   173  	}
   174  
   175  	return ch.Update(update)
   176  }
   177  
   178  func (u *realSubscription) Publish(chID subscription.ChanID, msg subscription.Message) error {
   179  	u.mu.RLock()
   180  	defer u.mu.RUnlock()
   181  
   182  	ch, ok := u.channels[chID]
   183  	if !ok {
   184  		return errors.New(subscription.ErrChanNotExist)
   185  	}
   186  	return ch.Publish(msg)
   187  }