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 }