103 lines
3.1 KiB
Go
103 lines
3.1 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"time"
|
|
|
|
roomeventsv1 "hyapp.local/api/proto/events/room/v1"
|
|
roomv1 "hyapp.local/api/proto/room/v1"
|
|
"hyapp/pkg/tencentim"
|
|
"hyapp/pkg/xerr"
|
|
"hyapp/services/room-service/internal/room/command"
|
|
"hyapp/services/room-service/internal/room/outbox"
|
|
"hyapp/services/room-service/internal/room/rank"
|
|
"hyapp/services/room-service/internal/room/state"
|
|
)
|
|
|
|
func (s *Service) requireRoomOpenForEntry(ctx context.Context, roomID string) error {
|
|
closed, err := s.isRoomClosed(ctx, roomID)
|
|
if err != nil || !closed {
|
|
return err
|
|
}
|
|
return xerr.New(xerr.RoomClosed, "room closed")
|
|
}
|
|
|
|
func (s *Service) isRoomClosed(ctx context.Context, roomID string) (bool, error) {
|
|
roomMeta, exists, err := s.repository.GetRoomMeta(ctx, roomID)
|
|
if err != nil || !exists {
|
|
return false, err
|
|
}
|
|
return isClosedRoomStatus(roomMeta.Status), nil
|
|
}
|
|
|
|
func isClosedRoomStatus(status string) bool {
|
|
value := strings.TrimSpace(status)
|
|
return value != "" && !strings.EqualFold(value, state.RoomStatusActive)
|
|
}
|
|
|
|
// CloseRoom 关闭房间,统一清理 presence、麦位、读模型状态和房间外事件。
|
|
func (s *Service) CloseRoom(ctx context.Context, req *roomv1.CloseRoomRequest) (*roomv1.CloseRoomResponse, error) {
|
|
ctx = contextFromMeta(ctx, req.GetMeta())
|
|
cmd := command.CloseRoom{
|
|
Base: baseFromMeta(req.GetMeta()),
|
|
Reason: strings.TrimSpace(req.GetReason()),
|
|
}
|
|
if cmd.Reason == "" {
|
|
cmd.Reason = "closed_by_owner"
|
|
}
|
|
|
|
result, err := s.mutateRoom(ctx, cmd, true, func(now time.Time, current *state.RoomState, _ *rank.LocalRank) (mutationResult, []outbox.Record, error) {
|
|
if current == nil {
|
|
return mutationResult{}, nil, xerr.New(xerr.NotFound, "room not found")
|
|
}
|
|
if current.Status == state.RoomStatusClosed {
|
|
return mutationResult{snapshot: current.ToProto()}, nil, nil
|
|
}
|
|
if current.Status != state.RoomStatusActive && current.Status != state.RoomStatusClosing {
|
|
return mutationResult{}, nil, xerr.New(xerr.Conflict, "room is not active")
|
|
}
|
|
if err := requireOwnerOrHostPresent(current, cmd.ActorUserID()); err != nil {
|
|
return mutationResult{}, nil, err
|
|
}
|
|
|
|
current.Status = state.RoomStatusClosed
|
|
current.OnlineUsers = map[int64]*state.RoomUserState{}
|
|
for index := range current.MicSeats {
|
|
current.ClearMicSession(index)
|
|
}
|
|
current.Version++
|
|
|
|
closedEvent, err := outbox.Build(current.RoomID, "RoomClosed", current.Version, now, &roomeventsv1.RoomClosed{
|
|
ActorUserId: cmd.ActorUserID(),
|
|
Reason: cmd.Reason,
|
|
})
|
|
if err != nil {
|
|
return mutationResult{}, nil, err
|
|
}
|
|
|
|
return mutationResult{
|
|
snapshot: current.ToProto(),
|
|
roomStatus: state.RoomStatusClosed,
|
|
syncEvent: &tencentim.RoomEvent{
|
|
EventID: closedEvent.EventID,
|
|
RoomID: current.RoomID,
|
|
EventType: "room_closed",
|
|
ActorUserID: cmd.ActorUserID(),
|
|
RoomVersion: current.Version,
|
|
Attributes: map[string]string{
|
|
"reason": cmd.Reason,
|
|
},
|
|
},
|
|
}, []outbox.Record{closedEvent}, nil
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &roomv1.CloseRoomResponse{
|
|
Result: commandResult(result.applied, result.snapshot.GetVersion(), s.clock.Now()),
|
|
Room: result.snapshot,
|
|
}, nil
|
|
}
|