83 lines
1.7 KiB
Go
83 lines
1.7 KiB
Go
|
|
package websocket
|
||
|
|
|
||
|
|
import "sync"
|
||
|
|
|
||
|
|
type Hub struct {
|
||
|
|
clients map[string]map[*Client]bool // companyID -> clients
|
||
|
|
broadcast chan *Event
|
||
|
|
register chan *Client
|
||
|
|
unregister chan *Client
|
||
|
|
mu sync.RWMutex
|
||
|
|
}
|
||
|
|
|
||
|
|
func NewHub() *Hub {
|
||
|
|
return &Hub{
|
||
|
|
clients: make(map[string]map[*Client]bool),
|
||
|
|
broadcast: make(chan *Event, 256),
|
||
|
|
register: make(chan *Client),
|
||
|
|
unregister: make(chan *Client),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (h *Hub) Run() {
|
||
|
|
for {
|
||
|
|
select {
|
||
|
|
case client := <-h.register:
|
||
|
|
h.mu.Lock()
|
||
|
|
if h.clients[client.companyID] == nil {
|
||
|
|
h.clients[client.companyID] = make(map[*Client]bool)
|
||
|
|
}
|
||
|
|
h.clients[client.companyID][client] = true
|
||
|
|
h.mu.Unlock()
|
||
|
|
|
||
|
|
case client := <-h.unregister:
|
||
|
|
h.mu.Lock()
|
||
|
|
if clients, ok := h.clients[client.companyID]; ok {
|
||
|
|
if _, exists := clients[client]; exists {
|
||
|
|
delete(clients, client)
|
||
|
|
close(client.send)
|
||
|
|
if len(clients) == 0 {
|
||
|
|
delete(h.clients, client.companyID)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
h.mu.Unlock()
|
||
|
|
|
||
|
|
case event := <-h.broadcast:
|
||
|
|
h.mu.RLock()
|
||
|
|
if event.CompanyID != "" {
|
||
|
|
h.broadcastToCompanyLocked(event.CompanyID, event)
|
||
|
|
} else {
|
||
|
|
for companyID := range h.clients {
|
||
|
|
h.broadcastToCompanyLocked(companyID, event)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
h.mu.RUnlock()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (h *Hub) broadcastToCompanyLocked(companyID string, event *Event) {
|
||
|
|
data, err := event.Marshal()
|
||
|
|
if err != nil {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
for client := range h.clients[companyID] {
|
||
|
|
select {
|
||
|
|
case client.send <- data:
|
||
|
|
default:
|
||
|
|
close(client.send)
|
||
|
|
delete(h.clients[companyID], client)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (h *Hub) Broadcast(event *Event) {
|
||
|
|
h.broadcast <- event
|
||
|
|
}
|
||
|
|
|
||
|
|
func (h *Hub) BroadcastToCompany(companyID string, event *Event) {
|
||
|
|
event.CompanyID = companyID
|
||
|
|
h.broadcast <- event
|
||
|
|
}
|