Files
filefast/backend/internal/service/room_service.go
2026-03-28 15:43:18 +08:00

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
}