aboutsummaryrefslogtreecommitdiff
path: root/wrms.go
diff options
context:
space:
mode:
authorFlorian Fischer <florian.fischer@muhq.space>2023-07-31 10:19:29 +0200
committerFlorian Fischer <florian.fischer@muhq.space>2023-07-31 10:19:29 +0200
commitc162743200466b6d8d9e52d5666e1220c9cf67a2 (patch)
treefd458021881272f89de72b894ef736cb1ec44652 /wrms.go
parent0a42119281e829793c69efe76429c057f521d912 (diff)
downloadWRMS-c162743200466b6d8d9e52d5666e1220c9cf67a2.tar.gz
WRMS-c162743200466b6d8d9e52d5666e1220c9cf67a2.zip
move song and connection code into separate files
Diffstat (limited to 'wrms.go')
-rw-r--r--wrms.go177
1 files changed, 0 insertions, 177 deletions
diff --git a/wrms.go b/wrms.go
index c606822..247ede8 100644
--- a/wrms.go
+++ b/wrms.go
@@ -1,10 +1,6 @@
package main
import (
- "context"
- "encoding/json"
- "fmt"
- "net/http"
"sync"
"sync/atomic"
@@ -13,50 +9,6 @@ import (
"github.com/google/uuid"
)
-type Song struct {
- Title string `json:"title"`
- Artist string `json:"artist"`
- Source string `json:"source"`
- Uri string `json:"uri"`
- Weight float64 `json:"weight"`
- Album string `json:"album"`
- Year int `json:"year"`
- index int `json:"-"` // used by heap.Interface
- Upvotes map[uuid.UUID]struct{} `json:"upvotes"`
- Downvotes map[uuid.UUID]struct{} `json:"downvotes"`
-}
-
-func NewSong(title, artist, source, uri string) *Song {
- return &Song{
- Title: title,
- Artist: artist,
- Source: source,
- Uri: uri,
- Upvotes: map[uuid.UUID]struct{}{},
- Downvotes: map[uuid.UUID]struct{}{},
- }
-}
-
-func NewDetailedSong(title, artist, source, uri, album string, year int) *Song {
- s := NewSong(title, artist, source, uri)
- s.Album = album
- s.Year = year
- return s
-}
-
-func NewSongFromJson(data []byte) (*Song, error) {
- var s Song
- err := json.Unmarshal(data, &s)
- if err != nil {
- llog.Error("Failed to parse song data %s with %s", string(data), err)
- return nil, err
- }
-
- s.Upvotes = map[uuid.UUID]struct{}{}
- s.Downvotes = map[uuid.UUID]struct{}{}
- return &s, nil
-}
-
type Event struct {
Event string `json:"cmd"`
Id uint64 `json:"id"`
@@ -84,135 +36,6 @@ func (wrms *Wrms) newNotification(notification string) Event {
return wrms.newEvent(notification, nil)
}
-type Connection struct {
- wrms *Wrms
- Id uuid.UUID
- nr uint64
- closing atomic.Bool
- refs atomic.Int64
- Events chan Event
- w http.ResponseWriter
- flusher http.Flusher
- ctx context.Context
- cancel func()
- nextEvent uint64
-}
-
-const EVENT_BUFFER_SIZE = 3
-
-func (wrms *Wrms) newConnection(id uuid.UUID,
- w http.ResponseWriter,
- ctx context.Context,
- cncl func()) *Connection {
- // prepare the flusher
- flusher, ok := w.(http.Flusher)
- if !ok {
- llog.Fatal("Flusher type assertion failed")
- }
-
- conn := &Connection{
- wrms: wrms,
- Id: id,
- nr: wrms.nextConnNr.Add(1),
- Events: make(chan Event, EVENT_BUFFER_SIZE),
- w: w,
- flusher: flusher,
- ctx: ctx,
- cancel: cncl,
- }
-
- wrms.addConn(conn)
- return conn
-}
-
-func (c *Connection) Send(ev Event) {
- llog.DDebug("Sending %v to %v", ev, c.Id)
- // Connection is closing -> not write to it
- if c.closing.Load() {
- return
- }
- // Register us as sender
- c.refs.Add(1)
- // Send the event
- c.Events <- ev
- // Deregister us as sender
- c.refs.Add(-1)
-}
-
-func (conn *Connection) _send(evs []interface{}) error {
- for _, ev := range evs {
- data, err := json.Marshal(ev)
- if err != nil {
- llog.Warning("Encoding the initial command %v failed with %s", ev, err)
- return err
- }
-
- sdata := string(data)
- llog.Debug("Sending ev %s to %s", sdata, conn.Id)
- fmt.Fprintf(conn.w, "data: %s\n\n", sdata)
- conn.flusher.Flush()
- }
-
- return nil
-}
-
-func (conn *Connection) _sendEv(ev Event) error {
- return conn._send([]interface{}{ev})
-}
-
-func (conn *Connection) serve() {
- // Map to store future events to send them in order
- toSend := make(map[uint64]*Event)
-
- for {
- var ev Event
- // We have the next event -> send it
- if toSend[conn.nextEvent] != nil {
- ev = *toSend[conn.nextEvent]
- delete(toSend, conn.nextEvent)
- // We have not received the next event yet -> receive a new event
- } else {
- llog.DDebug("%v: Awaiting event %d", conn.Id, conn.nextEvent)
- select {
- case ev = <-conn.Events:
- case <-conn.ctx.Done():
- return
- }
- // We received a future object -> store it and continue
- if ev.Id > conn.nextEvent {
- llog.DDebug("%v: Received future event %d", conn.Id, ev.Id)
- toSend[ev.Id] = &ev
- continue
- }
- }
-
- // increment the expected event id
- if ev.Id == conn.nextEvent {
- conn.nextEvent++
- }
-
- conn._sendEv(ev)
- }
-}
-
-func (c *Connection) Close() {
- llog.Info("Closing connection %s", c.Id)
- // Remove the closing connection from the map
- wrms.delConn(c)
- // Announce that the connection is going to be closed
- c.closing.Store(true)
-
- // Consume all events from the registered senders
- for c.refs.Load() > 0 {
- select {
- case <-c.Events:
- default:
- }
- }
-
- close(c.Events)
-}
-
type Wrms struct {
Connections sync.Map
nextConnNr atomic.Uint64