Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions internal/infra/ws/servewebsockets.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ func (w WSHandler) websocketHandler(user auth.User, res http.ResponseWriter, req
api.LogApiError("User tried to connect to non existing room", nil, user.Profile.Id, req)
return
}

if len(room.PlayerProfiles()) >= room.Settings().MaxPlayers {
http.Error(res, feelbeaterror.RoomFull, feelbeaterror.StatusCode(feelbeaterror.RoomFull))
api.LogApiError("user rejected, room full", nil, user.Profile.Id, req)
return
}

conn, err := upgrader.Upgrade(res, req, nil)
if err != nil {
http.Error(res, feelbeaterror.Default, feelbeaterror.StatusCode(feelbeaterror.Default))
Expand Down
2 changes: 2 additions & 0 deletions internal/infra/ws/wshub.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ func (h *WSHub) run() {
close(h.register)
close(h.unregister)
close(h.rcv)

fblog.Info(component.Hub, "hub closed")
}()

for {
Expand Down
3 changes: 3 additions & 0 deletions internal/lib/feelbeaterror/errorcode.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@ const (
AuthFailed = "Authorization failed"
LoadingPlaylistFailed = "Playlist loading failed"
RoomNotFound = "Room not found"
RoomFull = "Room is full"
EncodingMessageFailed = "Encoding message failed"
)

func StatusCode(code ErrorCode) int {
switch code {
case RoomNotFound:
return http.StatusNotFound
case RoomFull:
return http.StatusForbidden
case AuthFailed:
return http.StatusForbidden
default:
Expand Down
5 changes: 5 additions & 0 deletions internal/lib/messages/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,8 @@ type SongState struct {
ImageUrl string `json:"imageUrl"`
DurationSec int `json:"durationSec"`
}

type PlayerLeftPayload struct {
Left string `json:"left"`
Admin string `json:"admin"`
}
62 changes: 39 additions & 23 deletions internal/lib/room/room.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,31 @@ import (
)

type Room struct {
id string
playlist lib.PlaylistData
owner lib.UserProfile
settings lib.RoomSettings
players map[string]Player
hub messages.Hub
snd chan messages.ServerMessage
rcv <-chan messages.ClientMessage
id string
playlist lib.PlaylistData
owner lib.UserProfile
settings lib.RoomSettings
players map[string]Player
hub messages.Hub
snd chan messages.ServerMessage
rcv <-chan messages.ClientMessage
onCleanup func(*Room)
}

type Player struct {
profile lib.UserProfile
}

func NewRoom(id string, playlist lib.PlaylistData, owner lib.UserProfile, settings lib.RoomSettings, hub messages.Hub) *Room {
func NewRoom(id string, playlist lib.PlaylistData, owner lib.UserProfile, settings lib.RoomSettings, hub messages.Hub, onCleanup func(*Room)) *Room {
return &Room{
id: id,
playlist: playlist,
owner: owner,
settings: settings,
players: make(map[string]Player),
hub: hub,
snd: make(chan messages.ServerMessage),
id: id,
playlist: playlist,
owner: owner,
settings: settings,
players: make(map[string]Player),
hub: hub,
snd: make(chan messages.ServerMessage),
onCleanup: onCleanup,
}
}

Expand Down Expand Up @@ -64,10 +66,6 @@ func (r *Room) Start() {
go r.processMessages()
}

func (r *Room) Stop() {
close(r.snd)
}

func (r *Room) Hub() messages.Hub {
return r.hub
}
Expand Down Expand Up @@ -124,13 +122,26 @@ func (r *Room) removePlayer(id string) {
for _, p := range r.players {
recipents = append(recipents, p.profile.Id)
}
if len(r.players) == 0 {
r.onCleanup(r)
r.cleanup()
return
}

if id == r.owner.Id {
r.owner = r.players[recipents[0]].profile
fblog.Info(component.Room, "admin transfered", "roomId", r.id, "from", id, "to", r.owner.Id)
}

fblog.Info(component.Room, "player leaves", "roomId", r.id, "playerId", id)

r.snd <- messages.ServerMessage{
To: recipents,
Type: messages.PlayerLeft,
Payload: id,
To: recipents,
Type: messages.PlayerLeft,
Payload: messages.PlayerLeftPayload{
Left: id,
Admin: r.owner.Id,
},
}
}

Expand All @@ -148,3 +159,8 @@ func (r *Room) sendToAllExcept(id string, messageType messages.ServerMessageType
Payload: payload,
}
}

func (r *Room) cleanup() {
close(r.snd)
fblog.Info(component.Room, "room stopping", "id", r.id)
}
26 changes: 20 additions & 6 deletions internal/lib/roomrepository/inmemoryroomrepository.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package roomrepository

import (
"sync"

"github.com/feelbeatapp/feelbeatserver/internal/infra/auth"
"github.com/feelbeatapp/feelbeatserver/internal/infra/fblog"
"github.com/feelbeatapp/feelbeatserver/internal/lib"
Expand All @@ -18,24 +20,32 @@ type InMemoryRoomRepository struct {
createHub func() messages.Hub
spotify SpotifyApi
rooms map[string]*room.Room
m sync.RWMutex
}

func NewInMemoryRoomRepository(spotify SpotifyApi, createHub func() messages.Hub) InMemoryRoomRepository {
return InMemoryRoomRepository{
func NewInMemoryRoomRepository(spotify SpotifyApi, createHub func() messages.Hub) *InMemoryRoomRepository {
return &InMemoryRoomRepository{
createHub: createHub,
spotify: spotify,
rooms: make(map[string]*room.Room),
}
}

func (r InMemoryRoomRepository) CreateRoom(user auth.User, settings lib.RoomSettings) (string, error) {
func (r *InMemoryRoomRepository) CreateRoom(user auth.User, settings lib.RoomSettings) (string, error) {
playlistData, err := r.spotify.FetchPlaylistData(settings.PlaylistId, user.Token)
if err != nil {
return "", err
}

newRoom := room.NewRoom(uuid.NewString(), playlistData, user.Profile, settings, r.createHub())
newRoom := room.NewRoom(uuid.NewString(), playlistData, user.Profile, settings, r.createHub(), func(room *room.Room) {
r.m.Lock()
delete(r.rooms, room.Id())
r.m.Unlock()
fblog.Info(component.RoomRepository, "removed room", "id", room.Id())
})
r.m.Lock()
r.rooms[newRoom.Id()] = newRoom
r.m.Unlock()

newRoom.Start()

Expand All @@ -44,15 +54,19 @@ func (r InMemoryRoomRepository) CreateRoom(user auth.User, settings lib.RoomSett
return newRoom.Id(), nil
}

func (r InMemoryRoomRepository) GetAllRooms() []*room.Room {
func (r *InMemoryRoomRepository) GetAllRooms() []*room.Room {
result := make([]*room.Room, 0)
r.m.RLock()
for _, room := range r.rooms {
result = append(result, room)
}
r.m.RUnlock()

return result
}

func (r InMemoryRoomRepository) GetRoom(id string) *room.Room {
func (r *InMemoryRoomRepository) GetRoom(id string) *room.Room {
defer r.m.RUnlock()
r.m.RLock()
return r.rooms[id]
}
Loading