This is to prevent users that aren't connected to the socket (somehow), to not fill up memory with buffered messages we'll never need.
74 lines
1.5 KiB
Go
74 lines
1.5 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
)
|
|
|
|
type Notifier[TNotification any] struct {
|
|
bufferSize int
|
|
|
|
Listeners map[string]chan TNotification
|
|
|
|
AllowedKeys map[string]bool
|
|
}
|
|
|
|
func (n *Notifier[TNotification]) Create(id string) error {
|
|
if _, exists := n.Listeners[id]; exists {
|
|
return errors.New("This listener already exists")
|
|
}
|
|
|
|
if _, exists := n.AllowedKeys[id]; !exists {
|
|
return errors.New("This key cannot be used to create a listener")
|
|
}
|
|
|
|
n.Listeners[id] = make(chan TNotification, n.bufferSize)
|
|
|
|
return nil
|
|
}
|
|
|
|
var ChannelFullErr = errors.New("Channel is full")
|
|
|
|
// Ensures the listener exists before sending
|
|
func (n *Notifier[TNotification]) SendAndCreate(id string, notification TNotification) error {
|
|
if _, exists := n.Listeners[id]; !exists {
|
|
if err := n.Create(id); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
ch := n.Listeners[id]
|
|
|
|
select {
|
|
case ch <- notification:
|
|
return nil
|
|
default:
|
|
return ChannelFullErr
|
|
}
|
|
}
|
|
|
|
func (n *Notifier[TNotification]) Delete(id string) error {
|
|
if _, exists := n.Listeners[id]; !exists {
|
|
return errors.New("This listener does not exists")
|
|
}
|
|
|
|
delete(n.Listeners, id)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (n *Notifier[TNotification]) AddKey(id string) {
|
|
n.AllowedKeys[id] = true
|
|
}
|
|
|
|
func (n *Notifier[TNotification]) RemoveKey(id string) {
|
|
delete(n.AllowedKeys, id)
|
|
}
|
|
|
|
func NewNotifier[TNotification any](bufferSize int) Notifier[TNotification] {
|
|
return Notifier[TNotification]{
|
|
bufferSize: bufferSize,
|
|
Listeners: make(map[string]chan TNotification),
|
|
AllowedKeys: make(map[string]bool),
|
|
}
|
|
}
|