Files
zogo/wsc/room.go
T

104 lines
2.2 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package wsc
import (
"encoding/json"
"sync"
"github.com/sirupsen/logrus"
)
// Room 消息房间,用于业务隔离和群组广播。
type Room struct {
name string
members map[string]*Session
mu sync.RWMutex
onEmpty func(name string) // 房间空时回调
}
func newRoom(name string) *Room {
return &Room{
name: name,
members: make(map[string]*Session),
}
}
func (r *Room) Name() string { return r.name }
func (r *Room) Len() int {
r.mu.RLock()
defer r.mu.RUnlock()
return len(r.members)
}
func (r *Room) Join(ctx *Context) {
r.mu.Lock()
r.members[ctx.SessionID] = ctx.session
r.mu.Unlock()
}
func (r *Room) Leave(ctx *Context) {
r.mu.Lock()
delete(r.members, ctx.SessionID)
empty := len(r.members) == 0
r.mu.Unlock()
if empty && r.onEmpty != nil {
r.onEmpty(r.name)
}
}
// Broadcast 向房间成员广播 Message(json.Marshal 后发原始字节)。
func (r *Room) Broadcast(excludeSessionID string, msg Message) error {
m := map[string]any{"action": msg.Action}
if len(msg.Payload) > 0 {
// Payload 已是 json.RawMessage,直接复用
m["payload"] = msg.Payload
}
raw, err := json.Marshal(m)
if err != nil {
return err
}
return r.broadcastRaw(excludeSessionID, raw)
}
// BroadcastRaw 向房间成员广播已序列化的消息(性能优化)。
func (r *Room) BroadcastRaw(excludeSessionID string, data map[string]any) error {
raw, err := json.Marshal(data)
if err != nil {
return err
}
return r.broadcastRaw(excludeSessionID, raw)
}
// broadcastRaw 向房间成员发送原始字节(锁外已序列化)。
func (r *Room) broadcastRaw(excludeSessionID string, raw []byte) error {
r.mu.RLock()
defer r.mu.RUnlock()
for id, s := range r.members {
if id == excludeSessionID {
continue
}
if err := s.sendRaw(raw); err != nil {
logrus.Errorf("[wsc] broadcast send failed: session=%s, err=%v", id[:8], err)
}
}
return nil
}
// BroadcastAll 向房间所有成员广播。
func (r *Room) BroadcastAll(msg Message) error {
return r.Broadcast("", msg)
}
// SendTo 向房间内指定成员发送消息。
func (r *Room) SendTo(sessionID string, msg Message) error {
r.mu.RLock()
s, ok := r.members[sessionID]
r.mu.RUnlock()
if !ok {
return nil
}
return s.writeJSON(msg)
}