85 lines
2.0 KiB
Go
85 lines
2.0 KiB
Go
package service
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"math/rand/v2"
|
|
"time"
|
|
|
|
"filefast/backend/internal/model"
|
|
"filefast/backend/internal/store"
|
|
)
|
|
|
|
type RoomService struct {
|
|
store *store.MemoryStore
|
|
ttl time.Duration
|
|
}
|
|
|
|
func NewRoomService(store *store.MemoryStore, ttl time.Duration) *RoomService {
|
|
return &RoomService{
|
|
store: store,
|
|
ttl: ttl,
|
|
}
|
|
}
|
|
|
|
func (s *RoomService) CreateRoom(creatorDeviceID string) (model.Room, error) {
|
|
if creatorDeviceID == "" {
|
|
return model.Room{}, errors.New("creator_device_id is required")
|
|
}
|
|
|
|
now := time.Now()
|
|
for range 20 {
|
|
code := fmt.Sprintf("%04d", rand.IntN(10000))
|
|
if room, ok := s.store.GetRoom(code); ok && room.ExpiresAt.After(now) && room.Status != model.RoomStatusExpired {
|
|
continue
|
|
}
|
|
|
|
room := model.Room{
|
|
Code: code,
|
|
CreatorDeviceID: creatorDeviceID,
|
|
Status: model.RoomStatusWaiting,
|
|
CreatedAt: now,
|
|
ExpiresAt: now.Add(s.ttl),
|
|
}
|
|
return s.store.UpsertRoom(room), nil
|
|
}
|
|
|
|
return model.Room{}, errors.New("failed to allocate room code")
|
|
}
|
|
|
|
func (s *RoomService) JoinRoom(code, joinerDeviceID string) (model.Room, error) {
|
|
room, ok := s.store.GetRoom(code)
|
|
if !ok {
|
|
return model.Room{}, errors.New("room not found")
|
|
}
|
|
|
|
now := time.Now()
|
|
if !room.ExpiresAt.After(now) {
|
|
room.Status = model.RoomStatusExpired
|
|
s.store.UpsertRoom(room)
|
|
return model.Room{}, errors.New("room expired")
|
|
}
|
|
|
|
if room.Status != model.RoomStatusWaiting {
|
|
return model.Room{}, errors.New("room unavailable")
|
|
}
|
|
|
|
room.JoinerDeviceID = joinerDeviceID
|
|
room.Status = model.RoomStatusJoined
|
|
return s.store.UpsertRoom(room), nil
|
|
}
|
|
|
|
func (s *RoomService) CancelRoom(code, requesterID string) (model.Room, error) {
|
|
room, ok := s.store.GetRoom(code)
|
|
if !ok {
|
|
return model.Room{}, errors.New("room not found")
|
|
}
|
|
|
|
if room.CreatorDeviceID != requesterID {
|
|
return model.Room{}, errors.New("only creator can cancel room")
|
|
}
|
|
|
|
room.Status = model.RoomStatusCanceled
|
|
return s.store.UpsertRoom(room), nil
|
|
}
|