82 lines
1.9 KiB
Go
82 lines
1.9 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"screenmark/screenmark/middleware"
|
|
"screenmark/screenmark/notifications"
|
|
"strconv"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
/*
|
|
* TODO: We have channels open every a user sends an image.
|
|
* We never close these channels.
|
|
*
|
|
* What is a reasonable default? Close the channel after 1 minute of inactivity?
|
|
*/
|
|
func CreateEventsHandler(notifier *notifications.Notifier[notifications.Notification]) http.HandlerFunc {
|
|
counter := 0
|
|
|
|
userSplitters := make(map[string]*notifications.ChannelSplitter[notifications.Notification])
|
|
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
_userId := r.Context().Value(middleware.USER_ID).(uuid.UUID)
|
|
if _userId == uuid.Nil {
|
|
w.WriteHeader(http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
userId := _userId.String()
|
|
|
|
w.Header().Set("Content-Type", "text/event-stream")
|
|
w.Header().Set("Cache-Control", "no-cache")
|
|
w.Header().Set("Connection", "keep-alive")
|
|
// w.(http.Flusher).Flush()
|
|
|
|
if _, exists := notifier.Listeners[userId]; !exists {
|
|
notifier.Create(userId)
|
|
}
|
|
|
|
userNotifications := notifier.Listeners[userId]
|
|
|
|
if _, exists := userSplitters[userId]; !exists {
|
|
splitter := notifications.NewChannelSplitter(userNotifications)
|
|
|
|
userSplitters[userId] = &splitter
|
|
splitter.Listen()
|
|
}
|
|
|
|
splitter := userSplitters[userId]
|
|
|
|
id := strconv.Itoa(counter)
|
|
counter += 1
|
|
|
|
notifications := splitter.Add(id)
|
|
defer splitter.Remove(id)
|
|
|
|
for {
|
|
select {
|
|
case <-r.Context().Done():
|
|
fmt.Fprint(w, "event: close\ndata: Connection closed\n\n")
|
|
w.(http.Flusher).Flush()
|
|
return
|
|
case msg := <-notifications:
|
|
|
|
msgString, err := json.Marshal(msg)
|
|
if err != nil {
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
fmt.Printf("Sending msg %s\n", msgString)
|
|
|
|
fmt.Fprintf(w, "event: data\ndata: %s\n\n", string(msgString))
|
|
w.(http.Flusher).Flush()
|
|
}
|
|
}
|
|
}
|
|
}
|