package core import ( "encoding/json" "sync" "github.com/gorilla/websocket" "go.mongodb.org/mongo-driver/bson/primitive" "repositories.action2quare.com/ayo/gocommon" "repositories.action2quare.com/ayo/gocommon/wshandler" ) type connWithFriends struct { c *websocket.Conn friends []*friendDoc initialized bool } type connections struct { connLock sync.Mutex conns map[primitive.ObjectID]*connWithFriends wsh *wshandler.WebsocketHandler redison *gocommon.RedisonHandler } func (cs *connections) new(accid primitive.ObjectID, conn *websocket.Conn) { cs.connLock.Lock() defer cs.connLock.Unlock() cs.conns[accid] = &connWithFriends{ c: conn, initialized: false, } } func (cs *connections) delete(accid primitive.ObjectID) { cs.connLock.Lock() defer cs.connLock.Unlock() delete(cs.conns, accid) } func (cs *connections) conn(accid primitive.ObjectID) *websocket.Conn { cs.connLock.Lock() defer cs.connLock.Unlock() if cf, ok := cs.conns[accid]; ok { return cf.c } return nil } func (cs *connections) addFriend(accid primitive.ObjectID, fdoc *friendDoc) bool { cs.connLock.Lock() defer cs.connLock.Unlock() if cf, ok := cs.conns[accid]; ok { if cf.initialized { cf.friends = append(cf.friends, fdoc) return true } } return false } func (cs *connections) initFriends(accid primitive.ObjectID, fdocs []*friendDoc) { cs.connLock.Lock() defer cs.connLock.Unlock() if cf, ok := cs.conns[accid]; ok { cf.friends = fdocs cf.initialized = true } } func (cs *connections) clearFriends(accid primitive.ObjectID) (out []*friendDoc) { cs.connLock.Lock() defer cs.connLock.Unlock() if cf, ok := cs.conns[accid]; ok { out = cf.friends cf.friends = nil cf.initialized = false } return } func (cs *connections) writeMessage(acc primitive.ObjectID, src any) { cs.connLock.Lock() defer cs.connLock.Unlock() conn := cs.conns[acc] if conn == nil { return } if bt, err := json.Marshal(src); err == nil { cs.wsh.WriteDirectMessage(conn.c, websocket.TextMessage, bt) } } func (cs *connections) ClientConnected(conn *websocket.Conn, callby *wshandler.Sender) { cs.new(callby.Accid, conn) cs.redison.JSONSet(callby.Accid.Hex(), "$", map[string]any{}, gocommon.RedisonSetOptionNX) } func (cs *connections) ClientDisconnected(msg string, callby *wshandler.Sender) { cs.redison.JSONDel(callby.Accid.Hex(), "$") cs.delete(callby.Accid) } func makeConnections(redison *gocommon.RedisonHandler, wsh *wshandler.WebsocketHandler) *connections { return &connections{ conns: make(map[primitive.ObjectID]*connWithFriends), wsh: wsh, redison: redison, } }