You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

78 lines
1.8 KiB
Go

package routes
import (
"log"
"github.com/aziis98/lupus-lite/events"
"github.com/aziis98/lupus-lite/util"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/websocket/v2"
)
type clientMessage struct {
Type string `json:"type"`
Event string `json:"event"`
}
type serverMessage struct {
Event string `json:"event"`
Data any `json:"data"`
}
// BindWebsocketToEventBus creates a WebSocket handler that can subscribe the socket to some events generated on the server, for example a message from the client like { type: "subscribe", event: "foo" } binds the connection to the event "foo" and forwards events and the associated data to client as JSON.
func BindWebsocketToEventBus(eb *events.EventBus) fiber.Handler {
return websocket.New(func(c *websocket.Conn) {
clientId := util.GenerateRandomString(10)
log.Printf("[%v] Connection started", clientId)
defer log.Printf("[%v] Connection closed", clientId)
listeners := []*events.Listener{}
defer func() {
for _, l := range listeners {
eb.Unsubscribe(l)
}
}()
done := make(chan error)
for {
var msg clientMessage
if err := c.ReadJSON(&msg); err != nil {
log.Printf(`[%v] Read error: %v`, clientId, err)
return
}
log.Printf("[%v] Received: %v", clientId, msg)
switch msg.Type {
case "subscribe":
newListener := eb.Subscribe(
msg.Event,
func(e interface{}) {
log.Printf(`[%v] Sent message`, clientId)
if err := c.WriteJSON(serverMessage{
Event: msg.Event,
Data: e,
}); err != nil {
log.Printf(`[%v] Write error: %v`, clientId, err)
done <- err
}
},
)
listeners = append(listeners, newListener)
default:
log.Printf("[%v] Unknown message type %q", clientId, msg.Type)
return
}
select {
case err := <-done:
if err != nil {
return
}
default:
}
}
})
}