package gamerobot import ( "context" "strings" "time" "hyapp/pkg/appcode" "hyapp/pkg/xerr" robotdomain "hyapp/services/robot-service/internal/domain/robot" ) // Repository 是 game-robot 用例层的持久化边界;账号资料仍归 user-service,robot-service 只保存“可被当成机器人使用”的登记事实。 type Repository interface { PickGameRobot(ctx context.Context, appCode string, gameID string, excludeUserIDs []int64, nowMS int64) (robotdomain.Robot, error) ListGameRobots(ctx context.Context, appCode string, gameID string, status string, pageSize int32, cursor string) ([]robotdomain.Robot, string, error) RegisterGameRobots(ctx context.Context, appCode string, gameID string, userIDs []int64, adminID int64, nowMS int64) ([]robotdomain.Robot, error) SetGameRobotStatus(ctx context.Context, appCode string, gameID string, userID int64, status string, nowMS int64) (robotdomain.Robot, error) DeleteGameRobot(ctx context.Context, appCode string, userID int64) error } // Service 封装游戏机器人池的读取、登记和随机挑选逻辑;game-service 只通过 RPC 调用这里,不再直接操作机器人表。 type Service struct { repo Repository now func() time.Time } func New(repo Repository) *Service { return &Service{repo: repo, now: time.Now} } func (s *Service) ListRobots(ctx context.Context, appCode string, gameID string, status string, pageSize int32, cursor string) ([]robotdomain.Robot, string, int64, error) { if s == nil || s.repo == nil { return nil, "", 0, xerr.New(xerr.Unavailable, "game robot repository is not configured") } app := appcode.Normalize(appCode) ctx = appcode.WithContext(ctx, app) items, next, err := s.repo.ListGameRobots(ctx, app, gameID, strings.TrimSpace(status), pageSize, cursor) return items, next, s.now().UnixMilli(), err } func (s *Service) RegisterRobots(ctx context.Context, appCode string, gameID string, userIDs []int64, adminID int64) ([]robotdomain.Robot, int64, error) { if s == nil || s.repo == nil { return nil, 0, xerr.New(xerr.Unavailable, "game robot repository is not configured") } if len(userIDs) == 0 { return nil, 0, xerr.New(xerr.InvalidArgument, "game robot user_ids is required") } app := appcode.Normalize(appCode) ctx = appcode.WithContext(ctx, app) nowMS := s.now().UnixMilli() items, err := s.repo.RegisterGameRobots(ctx, app, gameID, userIDs, adminID, nowMS) return items, nowMS, err } func (s *Service) PickRobot(ctx context.Context, appCode string, gameID string, matchID string, excludeUserIDs []int64, selectedAtMS int64) (robotdomain.Robot, int64, error) { if s == nil || s.repo == nil { return robotdomain.Robot{}, 0, xerr.New(xerr.Unavailable, "game robot repository is not configured") } if strings.TrimSpace(matchID) == "" { return robotdomain.Robot{}, 0, xerr.New(xerr.InvalidArgument, "game robot match_id is required") } app := appcode.Normalize(appCode) ctx = appcode.WithContext(ctx, app) nowMS := selectedAtMS if nowMS <= 0 { nowMS = s.now().UnixMilli() } item, err := s.repo.PickGameRobot(ctx, app, gameID, excludeUserIDs, nowMS) return item, nowMS, err } func (s *Service) SetRobotStatus(ctx context.Context, appCode string, gameID string, userID int64, status string) (robotdomain.Robot, int64, error) { if s == nil || s.repo == nil { return robotdomain.Robot{}, 0, xerr.New(xerr.Unavailable, "game robot repository is not configured") } if userID <= 0 { return robotdomain.Robot{}, 0, xerr.New(xerr.InvalidArgument, "game robot user_id is invalid") } app := appcode.Normalize(appCode) ctx = appcode.WithContext(ctx, app) nowMS := s.now().UnixMilli() item, err := s.repo.SetGameRobotStatus(ctx, app, gameID, userID, status, nowMS) return item, nowMS, err } func (s *Service) DeleteRobot(ctx context.Context, appCode string, userID int64) (int64, error) { if s == nil || s.repo == nil { return 0, xerr.New(xerr.Unavailable, "game robot repository is not configured") } if userID <= 0 { return 0, xerr.New(xerr.InvalidArgument, "game robot user_id is invalid") } app := appcode.Normalize(appCode) ctx = appcode.WithContext(ctx, app) nowMS := s.now().UnixMilli() return nowMS, s.repo.DeleteGameRobot(ctx, app, userID) }