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
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:
|
|
}
|
|
}
|
|
})
|
|
}
|