You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

74 lines
2.1 KiB

6 years ago
6 years ago
  1. package pubsub
  2. import (
  3. "errors"
  4. "sync"
  5. )
  6. var (
  7. // ErrUnsubscribed is returned by Err when a client unsubscribes.
  8. ErrUnsubscribed = errors.New("client unsubscribed")
  9. // ErrOutOfCapacity is returned by Err when a client is not pulling messages
  10. // fast enough. Note the client's subscription will be terminated.
  11. ErrOutOfCapacity = errors.New("client is not pulling messages fast enough")
  12. )
  13. // A Subscription represents a client subscription for a particular query and
  14. // consists of three things:
  15. // 1) channel onto which messages and tags are published
  16. // 2) channel which is closed if a client is too slow or choose to unsubscribe
  17. // 3) err indicating the reason for (2)
  18. type Subscription struct {
  19. out chan Message
  20. cancelled chan struct{}
  21. mtx sync.RWMutex
  22. err error
  23. }
  24. // Out returns a channel onto which messages and tags are published.
  25. // Unsubscribe/UnsubscribeAll does not close the channel to avoid clients from
  26. // receiving a nil message.
  27. func (s *Subscription) Out() <-chan Message {
  28. return s.out
  29. }
  30. // Cancelled returns a channel that's closed when the subscription is
  31. // terminated and supposed to be used in a select statement.
  32. func (s *Subscription) Cancelled() <-chan struct{} {
  33. return s.cancelled
  34. }
  35. // Err returns nil if the channel returned by Cancelled is not yet closed.
  36. // If the channel is closed, Err returns a non-nil error explaining why:
  37. // - ErrUnsubscribed if the subscriber choose to unsubscribe,
  38. // - ErrOutOfCapacity if the subscriber is not pulling messages fast enough
  39. // and the channel returned by Out became full,
  40. // After Err returns a non-nil error, successive calls to Err return the same
  41. // error.
  42. func (s *Subscription) Err() error {
  43. s.mtx.RLock()
  44. defer s.mtx.RUnlock()
  45. return s.err
  46. }
  47. // Message glues data and tags together.
  48. type Message struct {
  49. data interface{}
  50. tags map[string]string
  51. }
  52. func NewMessage(data interface{}, tags map[string]string) Message {
  53. return Message{data, tags}
  54. }
  55. // Data returns an original data published.
  56. func (msg Message) Data() interface{} {
  57. return msg.data
  58. }
  59. // Tags returns tags, which matched the client's query.
  60. func (msg Message) Tags() map[string]string {
  61. return msg.tags
  62. }