diff --git a/broker/sse.go b/broker/sse.go index 1946bb4..7822442 100644 --- a/broker/sse.go +++ b/broker/sse.go @@ -4,6 +4,7 @@ import ( "fmt" "log/slog" "net/http" + "os" "time" ) @@ -20,22 +21,18 @@ type ( Broker struct { // Events are pushed to this channel by the main events-gathering routine Notifier NotifierChan - // New client connections - newClients chan NotifierChan - // Closed client connections - closingClients chan NotifierChan - // Client connections registry - clients map[NotifierChan]struct{} + log *slog.Logger } ) func NewBroker() (broker *Broker) { // Instantiate a broker return &Broker{ - Notifier: make(NotifierChan, 1), - newClients: make(chan NotifierChan), - closingClients: make(chan NotifierChan), - clients: make(map[NotifierChan]struct{}), + Notifier: make(NotifierChan, 100), + log: slog.New(slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{ + Level: slog.LevelDebug, + AddSource: true, + })), } } @@ -44,7 +41,6 @@ var Notifier *Broker // for use in different packages func init() { Notifier = NewBroker() - go Notifier.Listen() } func (broker *Broker) ServeHTTP(w http.ResponseWriter, r *http.Request) { @@ -59,9 +55,6 @@ func (broker *Broker) ServeHTTP(w http.ResponseWriter, r *http.Request) { } w.Header().Set("Access-Control-Allow-Origin", origin) w.Header().Set("Access-Control-Allow-Credentials", "true") - messageChan := make(NotifierChan, 10) // Buffered channel - broker.newClients <- messageChan - defer func() { broker.closingClients <- messageChan }() ctx := r.Context() // browser can close sse on its own; ping every 2s to prevent heartbeat := time.NewTicker(2 * time.Second) @@ -69,12 +62,14 @@ func (broker *Broker) ServeHTTP(w http.ResponseWriter, r *http.Request) { for { select { case <-ctx.Done(): + broker.log.Debug("broker: got ctx done") // Client disconnected return - case event := <-messageChan: + case event := <-broker.Notifier: + broker.log.Debug("got event", "event", event) _, err := fmt.Fprintf(w, "event: %s\ndata: %s\n\n", event.EventName, event.Payload) if err != nil { - fmt.Println(err) + broker.log.Error("failed to write event", "error", err) // Client disconnected return } @@ -82,38 +77,10 @@ func (broker *Broker) ServeHTTP(w http.ResponseWriter, r *http.Request) { case <-heartbeat.C: // Send SSE heartbeat comment if _, err := fmt.Fprint(w, ":\n\n"); err != nil { + broker.log.Error("failed to write heartbeat", "error", err) return // Client disconnected } w.(http.Flusher).Flush() } } } - -// Listen for new notifications and redistribute them to clients -func (broker *Broker) Listen() { - for { - select { - case s := <-broker.newClients: - // A new client has connected. - // Register their message channel - broker.clients[s] = struct{}{} - slog.Info("Client added", "clients listening", len(broker.clients)) - case s := <-broker.closingClients: - // A client has dettached and we want to - // stop sending them messages. - delete(broker.clients, s) - slog.Info("Client removed", "clients listening", len(broker.clients)) - case event := <-broker.Notifier: - // We got a new event from the outside! - // Send event to all connected clients - for clientMessageChan := range broker.clients { - select { - case clientMessageChan <- event: - case <-time.After(patience): - delete(broker.clients, clientMessageChan) - slog.Info("Client was removed", "clients listening", len(broker.clients)) - } - } - } - } -} diff --git a/components/base.html b/components/base.html index 3d8a9dc..a64febc 100644 --- a/components/base.html +++ b/components/base.html @@ -13,6 +13,12 @@
Hello {{.State.Username}};
Room created by {{.Room.CreatorName}};
diff --git a/handlers/elements.go b/handlers/elements.go index 061edbf..b6d2ca1 100644 --- a/handlers/elements.go +++ b/handlers/elements.go @@ -329,3 +329,19 @@ func HandleRemoveBot(w http.ResponseWriter, r *http.Request) { } notify(models.NotifyRoomUpdatePrefix+fi.Room.ID, "") } + +func HandleGetRoom(w http.ResponseWriter, r *http.Request) { + fi, err := getFullInfoByCtx(r.Context()) + if err != nil { + abortWithError(w, err.Error()) + return + } + tmpl, err := template.ParseGlob("components/*.html") + if err != nil { + abortWithError(w, err.Error()) + return + } + if err := tmpl.ExecuteTemplate(w, "room", fi); err != nil { + log.Error("failed to execute template", "error", err) + } +} diff --git a/main.go b/main.go index c453f13..12e7b48 100644 --- a/main.go +++ b/main.go @@ -92,6 +92,7 @@ func ListenToRequests(port string) *http.Server { mux.HandleFunc("GET /add-bot", handlers.HandleAddBot) mux.HandleFunc("GET /remove-bot", handlers.HandleRemoveBot) mux.HandleFunc("GET /mark-card", handlers.HandleMarkCard) + mux.HandleFunc("GET /room", handlers.HandleGetRoom) // special mux.HandleFunc("GET /renotify-bot", handlers.HandleRenotifyBot) // sse