|
@@ -1,8 +1,93 @@
|
|
|
package server
|
|
|
|
|
|
+import (
|
|
|
+ "log"
|
|
|
+ "sync"
|
|
|
+
|
|
|
+ "github.com/nats-io/nats.go"
|
|
|
+ "github.com/rotisserie/eris"
|
|
|
+ "sikey.com/websocket/utils/zlog"
|
|
|
+)
|
|
|
+
|
|
|
+const (
|
|
|
+ subject = "clients.message"
|
|
|
+ headerUserId = "userId"
|
|
|
+)
|
|
|
+
|
|
|
type Nats struct {
|
|
|
+ nc *nats.Conn
|
|
|
+
|
|
|
+ mutex sync.RWMutex
|
|
|
+ Subscribers map[string]*subscriber
|
|
|
+
|
|
|
+ ch chan *nats.Msg
|
|
|
+ Send chan map[string]*Message
|
|
|
+ Subscribe chan *subscriber
|
|
|
+ Unsubscribe chan *subscriber
|
|
|
+}
|
|
|
+
|
|
|
+type subscriber struct {
|
|
|
+ client *Client
|
|
|
+}
|
|
|
+
|
|
|
+func NewNats(addr string) *Nats {
|
|
|
+ nc, err := nats.Connect(addr)
|
|
|
+ if err != nil {
|
|
|
+ log.Fatalln(err)
|
|
|
+ }
|
|
|
+ // nc.Drain()
|
|
|
+
|
|
|
+ n := &Nats{
|
|
|
+ nc: nc,
|
|
|
+ mutex: sync.RWMutex{},
|
|
|
+ ch: make(chan *nats.Msg, 256),
|
|
|
+ Send: make(chan map[string]*Message),
|
|
|
+ Subscribers: make(map[string]*subscriber),
|
|
|
+ Subscribe: make(chan *subscriber),
|
|
|
+ Unsubscribe: make(chan *subscriber),
|
|
|
+ }
|
|
|
+
|
|
|
+ _, err = nc.ChanSubscribe(subject, n.ch)
|
|
|
+ if err != nil {
|
|
|
+ zlog.Error(eris.Wrap(err, "unable to start: "))
|
|
|
+ }
|
|
|
+
|
|
|
+ go n.run()
|
|
|
+ return n
|
|
|
}
|
|
|
|
|
|
-func NewNats() *Nats {
|
|
|
- return &Nats{}
|
|
|
+func (n *Nats) run() {
|
|
|
+ for {
|
|
|
+ select {
|
|
|
+ case message := <-n.Send:
|
|
|
+ for k, m := range message {
|
|
|
+ bytes := serializationMessage(m)
|
|
|
+ if err := n.nc.PublishMsg(&nats.Msg{
|
|
|
+ Subject: subject,
|
|
|
+ Data: bytes,
|
|
|
+ Header: nats.Header{headerUserId: []string{k}},
|
|
|
+ }); err != nil {
|
|
|
+ zlog.Error(eris.Wrapf(err, "unable to message send: %s", k))
|
|
|
+ }
|
|
|
+ }
|
|
|
+ case msg := <-n.ch:
|
|
|
+ userId := msg.Header.Get(headerUserId)
|
|
|
+ if userId == "" {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ n.mutex.RLock()
|
|
|
+ if s, ok := n.Subscribers[userId]; ok {
|
|
|
+ s.client.Send <- deserializeMessage(msg.Data)
|
|
|
+ }
|
|
|
+ n.mutex.RUnlock()
|
|
|
+ case s := <-n.Subscribe:
|
|
|
+ n.mutex.Lock()
|
|
|
+ n.Subscribers[s.client.UserId] = s
|
|
|
+ n.mutex.Unlock()
|
|
|
+ case s := <-n.Unsubscribe:
|
|
|
+ n.mutex.Lock()
|
|
|
+ delete(n.Subscribers, s.client.UserId)
|
|
|
+ n.mutex.Unlock()
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|