style: reformatted all files
This commit is contained in:
@@ -8,4 +8,4 @@ var (
|
||||
ErrDuplicateResult = errors.New("duplicate result")
|
||||
ErrCompetitionNotFound = errors.New("competition not found")
|
||||
ErrUserNotFound = errors.New("user not found")
|
||||
)
|
||||
)
|
||||
|
||||
@@ -29,7 +29,18 @@ type Result struct {
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
||||
func NewResult(id uuid.UUID, competitionID uuid.UUID, userID uuid.UUID, score float64, rank *int, status ResultStatus, submissionID *uuid.UUID, metadata map[string]interface{}, createdAt time.Time, updatedAt time.Time) *Result {
|
||||
func NewResult(
|
||||
id uuid.UUID,
|
||||
competitionID uuid.UUID,
|
||||
userID uuid.UUID,
|
||||
score float64,
|
||||
rank *int,
|
||||
status ResultStatus,
|
||||
submissionID *uuid.UUID,
|
||||
metadata map[string]interface{},
|
||||
createdAt time.Time,
|
||||
updatedAt time.Time,
|
||||
) *Result {
|
||||
return &Result{
|
||||
ID: id,
|
||||
CompetitionID: competitionID,
|
||||
@@ -42,4 +53,4 @@ func NewResult(id uuid.UUID, competitionID uuid.UUID, userID uuid.UUID, score fl
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,9 +24,23 @@ type IResultService interface {
|
||||
GetResult(ctx context.Context, id uuid.UUID) (*domain.Result, error)
|
||||
UpdateResult(ctx context.Context, result *domain.Result) (*domain.Result, error)
|
||||
DeleteResult(ctx context.Context, id uuid.UUID) error
|
||||
ListResults(ctx context.Context, pageSize int32, pageToken int32, competitionID *uuid.UUID, userID *uuid.UUID, status *domain.ResultStatus, minScore *float64, maxScore *float64) (results []domain.Result, totalCount int32, nextPageToken int32, err error)
|
||||
ListResults(
|
||||
ctx context.Context,
|
||||
pageSize int32,
|
||||
pageToken int32,
|
||||
competitionID *uuid.UUID,
|
||||
userID *uuid.UUID,
|
||||
status *domain.ResultStatus,
|
||||
minScore *float64,
|
||||
maxScore *float64,
|
||||
) (results []domain.Result, totalCount int32, nextPageToken int32, err error)
|
||||
GetByCompetitionAndUser(ctx context.Context, competitionID uuid.UUID, userID uuid.UUID) (*domain.Result, error)
|
||||
GetLeaderboard(ctx context.Context, competitionID uuid.UUID, limit int32, offset int32) ([]domain.Result, int32, error)
|
||||
GetLeaderboard(
|
||||
ctx context.Context,
|
||||
competitionID uuid.UUID,
|
||||
limit int32,
|
||||
offset int32,
|
||||
) ([]domain.Result, int32, error)
|
||||
UpdateStatus(ctx context.Context, id uuid.UUID, status domain.ResultStatus) (*domain.Result, error)
|
||||
RecalculateRanks(ctx context.Context, competitionID uuid.UUID) error
|
||||
}
|
||||
@@ -43,7 +57,10 @@ type ResultsHandler struct {
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
func NewResultsHandler(s IResultService, userServiceAddr, submissionServiceAddr, taskServiceAddr string) *ResultsHandler {
|
||||
func NewResultsHandler(
|
||||
s IResultService,
|
||||
userServiceAddr, submissionServiceAddr, taskServiceAddr string,
|
||||
) *ResultsHandler {
|
||||
return &ResultsHandler{
|
||||
service: s,
|
||||
userServiceAddr: userServiceAddr,
|
||||
@@ -210,7 +227,11 @@ func (h *ResultsHandler) fetchTaskStatuses(ctx context.Context, competitionID, u
|
||||
return taskStatuses
|
||||
}
|
||||
|
||||
func (h *ResultsHandler) enrichUserResult(ctx context.Context, result *domain.Result, competitionID string) *pb.UserResult {
|
||||
func (h *ResultsHandler) enrichUserResult(
|
||||
ctx context.Context,
|
||||
result *domain.Result,
|
||||
competitionID string,
|
||||
) *pb.UserResult {
|
||||
userID := result.UserID.String()
|
||||
username := h.fetchUsername(ctx, userID)
|
||||
taskStatuses := h.fetchTaskStatuses(ctx, competitionID, userID)
|
||||
@@ -230,7 +251,10 @@ func (h *ResultsHandler) enrichUserResult(ctx context.Context, result *domain.Re
|
||||
return pbResult
|
||||
}
|
||||
|
||||
func (h *ResultsHandler) GetCompetitionResults(ctx context.Context, req *pb.GetCompetitionResultsRequest) (*pb.GetCompetitionResultsResponse, error) {
|
||||
func (h *ResultsHandler) GetCompetitionResults(
|
||||
ctx context.Context,
|
||||
req *pb.GetCompetitionResultsRequest,
|
||||
) (*pb.GetCompetitionResultsResponse, error) {
|
||||
competitionID, err := uuid.Parse(req.GetCompetitionId())
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "invalid competition id format: %v", err)
|
||||
@@ -267,7 +291,10 @@ func (h *ResultsHandler) GetCompetitionResults(ctx context.Context, req *pb.GetC
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (h *ResultsHandler) GetUserCompetitionResults(ctx context.Context, req *pb.GetUserCompetitionResultsRequest) (*pb.GetUserCompetitionResultsResponse, error) {
|
||||
func (h *ResultsHandler) GetUserCompetitionResults(
|
||||
ctx context.Context,
|
||||
req *pb.GetUserCompetitionResultsRequest,
|
||||
) (*pb.GetUserCompetitionResultsResponse, error) {
|
||||
competitionID, err := uuid.Parse(req.GetCompetitionId())
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "invalid competition id format: %v", err)
|
||||
@@ -294,7 +321,10 @@ func (h *ResultsHandler) GetUserCompetitionResults(ctx context.Context, req *pb.
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (h *ResultsHandler) RecalculateResults(ctx context.Context, req *pb.RecalculateResultsRequest) (*emptypb.Empty, error) {
|
||||
func (h *ResultsHandler) RecalculateResults(
|
||||
ctx context.Context,
|
||||
req *pb.RecalculateResultsRequest,
|
||||
) (*emptypb.Empty, error) {
|
||||
competitionID, err := uuid.Parse(req.GetCompetitionId())
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "invalid competition id format: %v", err)
|
||||
|
||||
@@ -53,28 +53,50 @@ func (m *MockResultService) DeleteResult(ctx context.Context, id uuid.UUID) erro
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (m *MockResultService) ListResults(ctx context.Context, pageSize int32, pageToken int32, competitionID *uuid.UUID, userID *uuid.UUID, status *domain.ResultStatus, minScore *float64, maxScore *float64) (results []domain.Result, totalCount int32, nextPageToken int32, err error) {
|
||||
func (m *MockResultService) ListResults(
|
||||
ctx context.Context,
|
||||
pageSize int32,
|
||||
pageToken int32,
|
||||
competitionID *uuid.UUID,
|
||||
userID *uuid.UUID,
|
||||
status *domain.ResultStatus,
|
||||
minScore *float64,
|
||||
maxScore *float64,
|
||||
) (results []domain.Result, totalCount int32, nextPageToken int32, err error) {
|
||||
if m.ListResultsFunc != nil {
|
||||
return m.ListResultsFunc(ctx, pageSize, pageToken, competitionID, userID, status, minScore, maxScore)
|
||||
}
|
||||
return nil, 0, 0, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (m *MockResultService) GetByCompetitionAndUser(ctx context.Context, competitionID uuid.UUID, userID uuid.UUID) (*domain.Result, error) {
|
||||
func (m *MockResultService) GetByCompetitionAndUser(
|
||||
ctx context.Context,
|
||||
competitionID uuid.UUID,
|
||||
userID uuid.UUID,
|
||||
) (*domain.Result, error) {
|
||||
if m.GetByCompetitionAndUserFunc != nil {
|
||||
return m.GetByCompetitionAndUserFunc(ctx, competitionID, userID)
|
||||
}
|
||||
return nil, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (m *MockResultService) GetLeaderboard(ctx context.Context, competitionID uuid.UUID, limit int32, offset int32) ([]domain.Result, int32, error) {
|
||||
func (m *MockResultService) GetLeaderboard(
|
||||
ctx context.Context,
|
||||
competitionID uuid.UUID,
|
||||
limit int32,
|
||||
offset int32,
|
||||
) ([]domain.Result, int32, error) {
|
||||
if m.GetLeaderboardFunc != nil {
|
||||
return m.GetLeaderboardFunc(ctx, competitionID, limit, offset)
|
||||
}
|
||||
return nil, 0, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (m *MockResultService) UpdateStatus(ctx context.Context, id uuid.UUID, status domain.ResultStatus) (*domain.Result, error) {
|
||||
func (m *MockResultService) UpdateStatus(
|
||||
ctx context.Context,
|
||||
id uuid.UUID,
|
||||
status domain.ResultStatus,
|
||||
) (*domain.Result, error) {
|
||||
if m.UpdateStatusFunc != nil {
|
||||
return m.UpdateStatusFunc(ctx, id, status)
|
||||
}
|
||||
|
||||
@@ -3,13 +3,14 @@ package postgres
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"datarush/internal/results/domain"
|
||||
"datarush/internal/results/repository"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"datarush/internal/results/domain"
|
||||
"datarush/internal/results/repository"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/lib/pq"
|
||||
"github.com/redis/go-redis/v9"
|
||||
@@ -257,8 +258,13 @@ func (r *ResultRepository) List(ctx context.Context, opts repository.ListResults
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
query := fmt.Sprintf(`SELECT id, competition_id, user_id, score, rank, status, submission_id, metadata, created_at, updated_at
|
||||
FROM results %s ORDER BY score DESC, created_at ASC LIMIT $%d OFFSET $%d`, where, argId, argId+1)
|
||||
query := fmt.Sprintf(
|
||||
`SELECT id, competition_id, user_id, score, rank, status, submission_id, metadata, created_at, updated_at
|
||||
FROM results %s ORDER BY score DESC, created_at ASC LIMIT $%d OFFSET $%d`,
|
||||
where,
|
||||
argId,
|
||||
argId+1,
|
||||
)
|
||||
args = append(args, opts.PageSize, opts.Page*opts.PageSize)
|
||||
|
||||
rows, err := r.db.QueryContext(ctx, query, args...)
|
||||
@@ -299,7 +305,11 @@ func (r *ResultRepository) List(ctx context.Context, opts repository.ListResults
|
||||
return results, total, nil
|
||||
}
|
||||
|
||||
func (r *ResultRepository) GetByCompetitionAndUser(ctx context.Context, competitionID uuid.UUID, userID uuid.UUID) (*domain.Result, error) {
|
||||
func (r *ResultRepository) GetByCompetitionAndUser(
|
||||
ctx context.Context,
|
||||
competitionID uuid.UUID,
|
||||
userID uuid.UUID,
|
||||
) (*domain.Result, error) {
|
||||
query := `SELECT id, competition_id, user_id, score, rank, status, submission_id, metadata, created_at, updated_at
|
||||
FROM results WHERE competition_id = $1 AND user_id = $2`
|
||||
row := r.db.QueryRowContext(ctx, query, competitionID, userID)
|
||||
@@ -334,7 +344,12 @@ func (r *ResultRepository) GetByCompetitionAndUser(ctx context.Context, competit
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
func (r *ResultRepository) GetLeaderboard(ctx context.Context, competitionID uuid.UUID, limit int, offset int) ([]domain.Result, int, error) {
|
||||
func (r *ResultRepository) GetLeaderboard(
|
||||
ctx context.Context,
|
||||
competitionID uuid.UUID,
|
||||
limit int,
|
||||
offset int,
|
||||
) ([]domain.Result, int, error) {
|
||||
if r.cacheEnabled {
|
||||
key := r.leaderboardCacheKey(competitionID, limit, offset)
|
||||
val, err := r.redisClient.Get(ctx, key).Result()
|
||||
@@ -404,7 +419,11 @@ func (r *ResultRepository) GetLeaderboard(ctx context.Context, competitionID uui
|
||||
return results, total, nil
|
||||
}
|
||||
|
||||
func (r *ResultRepository) UpdateStatus(ctx context.Context, id uuid.UUID, status domain.ResultStatus) (*domain.Result, error) {
|
||||
func (r *ResultRepository) UpdateStatus(
|
||||
ctx context.Context,
|
||||
id uuid.UUID,
|
||||
status domain.ResultStatus,
|
||||
) (*domain.Result, error) {
|
||||
query := `UPDATE results SET status = $1, updated_at = $2 WHERE id = $3`
|
||||
now := time.Now()
|
||||
res, err := r.db.ExecContext(ctx, query, status, now, id)
|
||||
|
||||
@@ -2,6 +2,7 @@ package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"datarush/internal/results/domain"
|
||||
|
||||
"github.com/google/uuid"
|
||||
@@ -27,4 +28,4 @@ type ResultRepository interface {
|
||||
GetLeaderboard(ctx context.Context, competitionID uuid.UUID, limit int, offset int) ([]domain.Result, int, error)
|
||||
UpdateStatus(ctx context.Context, id uuid.UUID, status domain.ResultStatus) (*domain.Result, error)
|
||||
RecalculateRanks(ctx context.Context, competitionID uuid.UUID) error
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,16 @@ func (s *Service) DeleteResult(ctx context.Context, id uuid.UUID) error {
|
||||
return s.repo.Delete(ctx, id)
|
||||
}
|
||||
|
||||
func (s *Service) ListResults(ctx context.Context, pageSize int32, pageToken int32, competitionID *uuid.UUID, userID *uuid.UUID, status *domain.ResultStatus, minScore *float64, maxScore *float64) ([]domain.Result, int32, int32, error) {
|
||||
func (s *Service) ListResults(
|
||||
ctx context.Context,
|
||||
pageSize int32,
|
||||
pageToken int32,
|
||||
competitionID *uuid.UUID,
|
||||
userID *uuid.UUID,
|
||||
status *domain.ResultStatus,
|
||||
minScore *float64,
|
||||
maxScore *float64,
|
||||
) ([]domain.Result, int32, int32, error) {
|
||||
opts := repository.ListResultsOptions{
|
||||
Page: int(pageToken),
|
||||
PageSize: int(pageSize),
|
||||
@@ -76,11 +85,20 @@ func (s *Service) ListResults(ctx context.Context, pageSize int32, pageToken int
|
||||
return results, int32(total), nextPageToken, nil
|
||||
}
|
||||
|
||||
func (s *Service) GetByCompetitionAndUser(ctx context.Context, competitionID uuid.UUID, userID uuid.UUID) (*domain.Result, error) {
|
||||
func (s *Service) GetByCompetitionAndUser(
|
||||
ctx context.Context,
|
||||
competitionID uuid.UUID,
|
||||
userID uuid.UUID,
|
||||
) (*domain.Result, error) {
|
||||
return s.repo.GetByCompetitionAndUser(ctx, competitionID, userID)
|
||||
}
|
||||
|
||||
func (s *Service) GetLeaderboard(ctx context.Context, competitionID uuid.UUID, limit int32, offset int32) ([]domain.Result, int32, error) {
|
||||
func (s *Service) GetLeaderboard(
|
||||
ctx context.Context,
|
||||
competitionID uuid.UUID,
|
||||
limit int32,
|
||||
offset int32,
|
||||
) ([]domain.Result, int32, error) {
|
||||
results, total, err := s.repo.GetLeaderboard(ctx, competitionID, int(limit), int(offset))
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
@@ -94,4 +112,4 @@ func (s *Service) UpdateStatus(ctx context.Context, id uuid.UUID, status domain.
|
||||
|
||||
func (s *Service) RecalculateRanks(ctx context.Context, competitionID uuid.UUID) error {
|
||||
return s.repo.RecalculateRanks(ctx, competitionID)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,21 +59,34 @@ func (m *MockRepository) List(ctx context.Context, opts repository.ListResultsOp
|
||||
return nil, 0, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (m *MockRepository) GetByCompetitionAndUser(ctx context.Context, competitionID uuid.UUID, userID uuid.UUID) (*domain.Result, error) {
|
||||
func (m *MockRepository) GetByCompetitionAndUser(
|
||||
ctx context.Context,
|
||||
competitionID uuid.UUID,
|
||||
userID uuid.UUID,
|
||||
) (*domain.Result, error) {
|
||||
if m.GetByCompetitionAndUserFunc != nil {
|
||||
return m.GetByCompetitionAndUserFunc(ctx, competitionID, userID)
|
||||
}
|
||||
return nil, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (m *MockRepository) GetLeaderboard(ctx context.Context, competitionID uuid.UUID, limit int, offset int) ([]domain.Result, int, error) {
|
||||
func (m *MockRepository) GetLeaderboard(
|
||||
ctx context.Context,
|
||||
competitionID uuid.UUID,
|
||||
limit int,
|
||||
offset int,
|
||||
) ([]domain.Result, int, error) {
|
||||
if m.GetLeaderboardFunc != nil {
|
||||
return m.GetLeaderboardFunc(ctx, competitionID, limit, offset)
|
||||
}
|
||||
return nil, 0, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (m *MockRepository) UpdateStatus(ctx context.Context, id uuid.UUID, status domain.ResultStatus) (*domain.Result, error) {
|
||||
func (m *MockRepository) UpdateStatus(
|
||||
ctx context.Context,
|
||||
id uuid.UUID,
|
||||
status domain.ResultStatus,
|
||||
) (*domain.Result, error) {
|
||||
if m.UpdateStatusFunc != nil {
|
||||
return m.UpdateStatusFunc(ctx, id, status)
|
||||
}
|
||||
@@ -423,20 +436,20 @@ func TestListResults(t *testing.T) {
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
pageSize int32
|
||||
pageToken int32
|
||||
competitionID *uuid.UUID
|
||||
userID *uuid.UUID
|
||||
status *domain.ResultStatus
|
||||
minScore *float64
|
||||
maxScore *float64
|
||||
repoResults []domain.Result
|
||||
repoTotal int
|
||||
repoError error
|
||||
expectError bool
|
||||
expectedTotal int32
|
||||
expectedNext int32
|
||||
name string
|
||||
pageSize int32
|
||||
pageToken int32
|
||||
competitionID *uuid.UUID
|
||||
userID *uuid.UUID
|
||||
status *domain.ResultStatus
|
||||
minScore *float64
|
||||
maxScore *float64
|
||||
repoResults []domain.Result
|
||||
repoTotal int
|
||||
repoError error
|
||||
expectError bool
|
||||
expectedTotal int32
|
||||
expectedNext int32
|
||||
}{
|
||||
{
|
||||
name: "successful list with filters",
|
||||
|
||||
Reference in New Issue
Block a user