gitee.com/liuxuezhan/go-micro-v1.18.0@v1.0.0/broker/memory/memory.go (about)

     1  // Package memory provides a memory broker
     2  package memory
     3  
     4  import (
     5  	"errors"
     6  	"math/rand"
     7  	"sync"
     8  	"time"
     9  
    10  	"github.com/google/uuid"
    11  	"gitee.com/liuxuezhan/go-micro-v1.18.0/broker"
    12  	maddr "gitee.com/liuxuezhan/go-micro-v1.18.0/util/addr"
    13  	mnet "gitee.com/liuxuezhan/go-micro-v1.18.0/util/net"
    14  )
    15  
    16  type memoryBroker struct {
    17  	opts broker.Options
    18  
    19  	addr string
    20  	sync.RWMutex
    21  	connected   bool
    22  	Subscribers map[string][]*memorySubscriber
    23  }
    24  
    25  type memoryEvent struct {
    26  	topic   string
    27  	message *broker.Message
    28  }
    29  
    30  type memorySubscriber struct {
    31  	id      string
    32  	topic   string
    33  	exit    chan bool
    34  	handler broker.Handler
    35  	opts    broker.SubscribeOptions
    36  }
    37  
    38  func (m *memoryBroker) Options() broker.Options {
    39  	return m.opts
    40  }
    41  
    42  func (m *memoryBroker) Address() string {
    43  	return m.addr
    44  }
    45  
    46  func (m *memoryBroker) Connect() error {
    47  	m.Lock()
    48  	defer m.Unlock()
    49  
    50  	if m.connected {
    51  		return nil
    52  	}
    53  
    54  	addr, err := maddr.Extract("::")
    55  	if err != nil {
    56  		return err
    57  	}
    58  	i := rand.Intn(20000)
    59  	// set addr with port
    60  	addr = mnet.HostPort(addr, 10000+i)
    61  
    62  	m.addr = addr
    63  	m.connected = true
    64  
    65  	return nil
    66  }
    67  
    68  func (m *memoryBroker) Disconnect() error {
    69  	m.Lock()
    70  	defer m.Unlock()
    71  
    72  	if !m.connected {
    73  		return nil
    74  	}
    75  
    76  	m.connected = false
    77  
    78  	return nil
    79  }
    80  
    81  func (m *memoryBroker) Init(opts ...broker.Option) error {
    82  	for _, o := range opts {
    83  		o(&m.opts)
    84  	}
    85  	return nil
    86  }
    87  
    88  func (m *memoryBroker) Publish(topic string, message *broker.Message, opts ...broker.PublishOption) error {
    89  	m.RLock()
    90  	if !m.connected {
    91  		m.RUnlock()
    92  		return errors.New("not connected")
    93  	}
    94  
    95  	subs, ok := m.Subscribers[topic]
    96  	m.RUnlock()
    97  	if !ok {
    98  		return nil
    99  	}
   100  
   101  	p := &memoryEvent{
   102  		topic:   topic,
   103  		message: message,
   104  	}
   105  
   106  	for _, sub := range subs {
   107  		if err := sub.handler(p); err != nil {
   108  			return err
   109  		}
   110  	}
   111  
   112  	return nil
   113  }
   114  
   115  func (m *memoryBroker) Subscribe(topic string, handler broker.Handler, opts ...broker.SubscribeOption) (broker.Subscriber, error) {
   116  	m.RLock()
   117  	if !m.connected {
   118  		m.RUnlock()
   119  		return nil, errors.New("not connected")
   120  	}
   121  	m.RUnlock()
   122  
   123  	var options broker.SubscribeOptions
   124  	for _, o := range opts {
   125  		o(&options)
   126  	}
   127  
   128  	sub := &memorySubscriber{
   129  		exit:    make(chan bool, 1),
   130  		id:      uuid.New().String(),
   131  		topic:   topic,
   132  		handler: handler,
   133  		opts:    options,
   134  	}
   135  
   136  	m.Lock()
   137  	m.Subscribers[topic] = append(m.Subscribers[topic], sub)
   138  	m.Unlock()
   139  
   140  	go func() {
   141  		<-sub.exit
   142  		m.Lock()
   143  		var newSubscribers []*memorySubscriber
   144  		for _, sb := range m.Subscribers[topic] {
   145  			if sb.id == sub.id {
   146  				continue
   147  			}
   148  			newSubscribers = append(newSubscribers, sb)
   149  		}
   150  		m.Subscribers[topic] = newSubscribers
   151  		m.Unlock()
   152  	}()
   153  
   154  	return sub, nil
   155  }
   156  
   157  func (m *memoryBroker) String() string {
   158  	return "memory"
   159  }
   160  
   161  func (m *memoryEvent) Topic() string {
   162  	return m.topic
   163  }
   164  
   165  func (m *memoryEvent) Message() *broker.Message {
   166  	return m.message
   167  }
   168  
   169  func (m *memoryEvent) Ack() error {
   170  	return nil
   171  }
   172  
   173  func (m *memorySubscriber) Options() broker.SubscribeOptions {
   174  	return m.opts
   175  }
   176  
   177  func (m *memorySubscriber) Topic() string {
   178  	return m.topic
   179  }
   180  
   181  func (m *memorySubscriber) Unsubscribe() error {
   182  	m.exit <- true
   183  	return nil
   184  }
   185  
   186  func NewBroker(opts ...broker.Option) broker.Broker {
   187  	var options broker.Options
   188  	rand.Seed(time.Now().UnixNano())
   189  	for _, o := range opts {
   190  		o(&options)
   191  	}
   192  
   193  	return &memoryBroker{
   194  		opts:        options,
   195  		Subscribers: make(map[string][]*memorySubscriber),
   196  	}
   197  }