stillbox/pkg/gordio/nexus/nexus.go
2024-08-04 15:29:13 -04:00

91 lines
1.5 KiB
Go

package nexus
import (
"sync"
"dynatron.me/x/stillbox/pkg/gordio/calls"
"dynatron.me/x/stillbox/pkg/pb"
"github.com/rs/zerolog/log"
)
type Nexus struct {
sync.RWMutex
clients map[*client]struct{}
*wsManager
callCh chan *calls.Call
}
type Registry interface {
NewClient(Connection) Client
Register(Client)
Unregister(Client)
}
func New() *Nexus {
n := &Nexus{
clients: make(map[*client]struct{}),
callCh: make(chan *calls.Call),
}
n.wsManager = newWsManager(n)
return n
}
func (n *Nexus) Go(done <-chan struct{}) {
for {
select {
case call, ok := <-n.callCh:
log.Debug().Msg("call received from ch")
if !ok {
return
}
log.Debug().Msg("broadcasting call")
n.broadcastCallToClients(call)
case <-done:
return
}
}
}
func (n *Nexus) BroadcastCall(call *calls.Call) {
n.callCh <- call
log.Debug().Msg("call sent to ch")
}
func (n *Nexus) broadcastCallToClients(call *calls.Call) {
message := &pb.Message{
ToClientMessage: &pb.Message_Call{Call: call.ToPB()},
}
n.Lock()
defer n.Unlock()
for cl, _ := range n.clients {
log.Debug().Msg("sending")
if cl.Send(message) {
log.Debug().Msg("channel was closed")
// we already hold the lock, and the channel is closed anyway
delete(n.clients, cl)
}
}
}
func (n *Nexus) Register(c Client) {
n.Lock()
defer n.Unlock()
n.clients[c.(*client)] = struct{}{}
}
func (n *Nexus) Unregister(c Client) {
n.Lock()
defer n.Unlock()
cl := c.(*client)
delete(n.clients, cl)
}