diff --git a/Containerfile b/Containerfile index e66ba23..a9c85a3 100644 --- a/Containerfile +++ b/Containerfile @@ -30,8 +30,8 @@ RUN --mount=type=cache,target=/root/.cache/go-build \ CGO_ENABLED=${CGO_ENABLED} \ GOOS=${GOOS} \ GOARCH=${GOARCH} \ - go build -trimpath \ - -ldflags "-s -w -X main.BuildTime=${BUILD_TIME} -X main.Version=${VERSION}" \ + go build -a -installsuffix cgo -trimpath \ + -ldflags '-extldflags "-static" -s -w -X main.BuildTime=${BUILD_TIME} -X main.Version=${VERSION}' \ -o /out/${SERVICE} ./cmd/${SERVICE} && \ chmod +x /out/${SERVICE} diff --git a/cmd/results/main.go b/cmd/results/main.go index c89784a..bd8121f 100644 --- a/cmd/results/main.go +++ b/cmd/results/main.go @@ -29,4 +29,4 @@ func main() { log.Println("shutting down results server...") srv.Stop() log.Println("results server stopped") -} \ No newline at end of file +} diff --git a/cmd/task/main.go b/cmd/task/main.go index 5feae5b..b83947c 100644 --- a/cmd/task/main.go +++ b/cmd/task/main.go @@ -29,4 +29,4 @@ func main() { log.Println("shutting down task server...") srv.Stop() log.Println("task server stopped") -} \ No newline at end of file +} diff --git a/cmd/user/main.go b/cmd/user/main.go index 4f3ac4a..a58ef29 100644 --- a/cmd/user/main.go +++ b/cmd/user/main.go @@ -29,4 +29,4 @@ func main() { log.Println("shutting down user server...") srv.Stop() log.Println("user server stopped") -} \ No newline at end of file +} diff --git a/internal/migrate/config/config.go b/internal/migrate/config/config.go index 0d2a479..832197e 100644 --- a/internal/migrate/config/config.go +++ b/internal/migrate/config/config.go @@ -28,11 +28,11 @@ func Load() (*Config, error) { _ = godotenv.Load() return &Config{ - DBHost: getEnv("POSTGRES_HOST", "localhost"), - DBPort: mustGetInt("POSTGRES_PORT", 5432), //nolint:mnd // false-positive - DBUser: getEnv("POSTGRES_USERNAME", "postgres"), - DBPassword: getEnv("POSTGRES_PASSWORD", "postgres"), - DBName: getEnv("POSTGRES_DATABASE", "postgres"), + DBHost: getEnv("POSTGRES_HOST", "localhost"), + DBPort: mustGetInt("POSTGRES_PORT", 5432), //nolint:mnd // false-positive + DBUser: getEnv("POSTGRES_USERNAME", "postgres"), + DBPassword: getEnv("POSTGRES_PASSWORD", "postgres"), + DBName: getEnv("POSTGRES_DATABASE", "postgres"), }, nil } diff --git a/internal/results/domain/errors.go b/internal/results/domain/errors.go index c8a855c..662e1ab 100644 --- a/internal/results/domain/errors.go +++ b/internal/results/domain/errors.go @@ -8,4 +8,4 @@ var ( ErrDuplicateResult = errors.New("duplicate result") ErrCompetitionNotFound = errors.New("competition not found") ErrUserNotFound = errors.New("user not found") -) \ No newline at end of file +) diff --git a/internal/results/domain/result.go b/internal/results/domain/result.go index a1b6672..6c7fdf2 100644 --- a/internal/results/domain/result.go +++ b/internal/results/domain/result.go @@ -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, } -} \ No newline at end of file +} diff --git a/internal/results/handler/grpc/results.go b/internal/results/handler/grpc/results.go index b58e456..1b60464 100644 --- a/internal/results/handler/grpc/results.go +++ b/internal/results/handler/grpc/results.go @@ -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) diff --git a/internal/results/handler/grpc/results_test.go b/internal/results/handler/grpc/results_test.go index 667e7a6..73ae0ee 100644 --- a/internal/results/handler/grpc/results_test.go +++ b/internal/results/handler/grpc/results_test.go @@ -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) } diff --git a/internal/results/repository/postgres/result.go b/internal/results/repository/postgres/result.go index a3f7582..86b238d 100644 --- a/internal/results/repository/postgres/result.go +++ b/internal/results/repository/postgres/result.go @@ -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) diff --git a/internal/results/repository/result.go b/internal/results/repository/result.go index b6c7779..088a17d 100644 --- a/internal/results/repository/result.go +++ b/internal/results/repository/result.go @@ -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 -} \ No newline at end of file +} diff --git a/internal/results/service/result.go b/internal/results/service/result.go index b7efb00..969008c 100644 --- a/internal/results/service/result.go +++ b/internal/results/service/result.go @@ -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) -} \ No newline at end of file +} diff --git a/internal/results/service/result_test.go b/internal/results/service/result_test.go index d3e00df..fcc6640 100644 --- a/internal/results/service/result_test.go +++ b/internal/results/service/result_test.go @@ -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", diff --git a/internal/task/handler/grpc/handler.go b/internal/task/handler/grpc/handler.go index de6ff88..536a24b 100644 --- a/internal/task/handler/grpc/handler.go +++ b/internal/task/handler/grpc/handler.go @@ -3,8 +3,9 @@ package grpc import ( "context" - pb "datarush/pkg/api/task" "google.golang.org/protobuf/types/known/emptypb" + + pb "datarush/pkg/api/task" ) type TaskService interface { @@ -12,7 +13,10 @@ type TaskService interface { GetTask(ctx context.Context, req *pb.GetTaskRequest) (*pb.Task, error) EditTask(ctx context.Context, req *pb.Task) (*pb.Task, error) DeleteTask(ctx context.Context, req *pb.DeleteTaskRequest) (*emptypb.Empty, error) - ListCompetitionTasks(ctx context.Context, req *pb.ListCompetitionTasksRequest) (*pb.ListCompetitionTasksResponse, error) + ListCompetitionTasks( + ctx context.Context, + req *pb.ListCompetitionTasksRequest, + ) (*pb.ListCompetitionTasksResponse, error) GetTaskAttachments(ctx context.Context, req *pb.GetTaskAttachmentsRequest) (*pb.GetTaskAttachmentsResponse, error) } @@ -41,10 +45,16 @@ func (h *TaskHandler) DeleteTask(ctx context.Context, req *pb.DeleteTaskRequest) return h.service.DeleteTask(ctx, req) } -func (h *TaskHandler) ListCompetitionTasks(ctx context.Context, req *pb.ListCompetitionTasksRequest) (*pb.ListCompetitionTasksResponse, error) { +func (h *TaskHandler) ListCompetitionTasks( + ctx context.Context, + req *pb.ListCompetitionTasksRequest, +) (*pb.ListCompetitionTasksResponse, error) { return h.service.ListCompetitionTasks(ctx, req) } -func (h *TaskHandler) GetTaskAttachments(ctx context.Context, req *pb.GetTaskAttachmentsRequest) (*pb.GetTaskAttachmentsResponse, error) { +func (h *TaskHandler) GetTaskAttachments( + ctx context.Context, + req *pb.GetTaskAttachmentsRequest, +) (*pb.GetTaskAttachmentsResponse, error) { return h.service.GetTaskAttachments(ctx, req) -} \ No newline at end of file +} diff --git a/internal/task/repository/postgres/repository.go b/internal/task/repository/postgres/repository.go index 6fa0b10..cec043c 100644 --- a/internal/task/repository/postgres/repository.go +++ b/internal/task/repository/postgres/repository.go @@ -21,7 +21,8 @@ func (r *TaskRepository) CreateTask(ctx context.Context, t *task.Task) (*task.Ta VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING id, created_at, updated_at` var createdTask task.Task - err := r.db.QueryRowxContext(ctx, query, t.CompetitionId, t.Title, t.Description, t.InCompetitionPosition, t.MaxPoints, t.MaxAttempts, t.Type).StructScan(&createdTask) + err := r.db.QueryRowxContext(ctx, query, t.CompetitionId, t.Title, t.Description, t.InCompetitionPosition, t.MaxPoints, t.MaxAttempts, t.Type). + StructScan(&createdTask) if err != nil { return nil, err } @@ -46,7 +47,8 @@ func (r *TaskRepository) EditTask(ctx context.Context, t *task.Task) (*task.Task WHERE id = $7 RETURNING updated_at` var updatedTask task.Task - err := r.db.QueryRowxContext(ctx, query, t.Title, t.Description, t.InCompetitionPosition, t.MaxPoints, t.MaxAttempts, t.Type, t.Id).StructScan(&updatedTask) + err := r.db.QueryRowxContext(ctx, query, t.Title, t.Description, t.InCompetitionPosition, t.MaxPoints, t.MaxAttempts, t.Type, t.Id). + StructScan(&updatedTask) if err != nil { return nil, err } @@ -65,7 +67,11 @@ func (r *TaskRepository) ListCompetitionTasks(ctx context.Context, competitionID return tasks, err } -func (r *TaskRepository) GetTaskAttachments(ctx context.Context, taskID string, showPrivate bool) ([]*task.TaskAttachment, error) { +func (r *TaskRepository) GetTaskAttachments( + ctx context.Context, + taskID string, + showPrivate bool, +) ([]*task.TaskAttachment, error) { var attachments []*task.TaskAttachment query := "SELECT * FROM task_attachments WHERE task_id = $1" args := []interface{}{taskID} @@ -76,4 +82,4 @@ func (r *TaskRepository) GetTaskAttachments(ctx context.Context, taskID string, err := r.db.SelectContext(ctx, &attachments, query, args...) return attachments, err -} \ No newline at end of file +} diff --git a/internal/task/service/service.go b/internal/task/service/service.go index 23c39d7..ffaf70c 100644 --- a/internal/task/service/service.go +++ b/internal/task/service/service.go @@ -2,6 +2,7 @@ package service import ( "context" + pb "datarush/pkg/api/task" "google.golang.org/protobuf/types/known/emptypb" @@ -41,7 +42,10 @@ func (s *TaskService) DeleteTask(ctx context.Context, req *pb.DeleteTaskRequest) return &emptypb.Empty{}, err } -func (s *TaskService) ListCompetitionTasks(ctx context.Context, req *pb.ListCompetitionTasksRequest) (*pb.ListCompetitionTasksResponse, error) { +func (s *TaskService) ListCompetitionTasks( + ctx context.Context, + req *pb.ListCompetitionTasksRequest, +) (*pb.ListCompetitionTasksResponse, error) { tasks, err := s.repo.ListCompetitionTasks(ctx, req.CompetitionId) if err != nil { return nil, err @@ -49,7 +53,10 @@ func (s *TaskService) ListCompetitionTasks(ctx context.Context, req *pb.ListComp return &pb.ListCompetitionTasksResponse{Tasks: tasks}, nil } -func (s *TaskService) GetTaskAttachments(ctx context.Context, req *pb.GetTaskAttachmentsRequest) (*pb.GetTaskAttachmentsResponse, error) { +func (s *TaskService) GetTaskAttachments( + ctx context.Context, + req *pb.GetTaskAttachmentsRequest, +) (*pb.GetTaskAttachmentsResponse, error) { showPrivate := false if req.ShowPrivate != nil { showPrivate = *req.ShowPrivate @@ -59,4 +66,4 @@ func (s *TaskService) GetTaskAttachments(ctx context.Context, req *pb.GetTaskAtt return nil, err } return &pb.GetTaskAttachmentsResponse{Attachments: attachments}, nil -} \ No newline at end of file +} diff --git a/internal/task/service/service_test.go b/internal/task/service/service_test.go index 0035e8c..e77de82 100644 --- a/internal/task/service/service_test.go +++ b/internal/task/service/service_test.go @@ -7,8 +7,8 @@ import ( "datarush/internal/task/service/mocks" pb "datarush/pkg/api/task" - "go.uber.org/mock/gomock" "github.com/stretchr/testify/assert" + "go.uber.org/mock/gomock" "google.golang.org/protobuf/types/known/timestamppb" ) @@ -24,13 +24,13 @@ func TestTaskService(t *testing.T) { t.Run("CreateTask", func(t *testing.T) { task := &pb.Task{ - CompetitionId: "comp1", - Title: "Test Task", - Description: "This is a test task", + CompetitionId: "comp1", + Title: "Test Task", + Description: "This is a test task", InCompetitionPosition: 1, - MaxPoints: 100, - MaxAttempts: 10, - Type: pb.TaskType_TASK_TYPE_INPUT, + MaxPoints: 100, + MaxAttempts: 10, + Type: pb.TaskType_TASK_TYPE_INPUT, } mockRepo.EXPECT().CreateTask(ctx, task).Return(task, nil) @@ -44,16 +44,16 @@ func TestTaskService(t *testing.T) { taskID := "task1" req := &pb.GetTaskRequest{TaskId: taskID} expectedTask := &pb.Task{ - Id: taskID, - CompetitionId: "comp1", - Title: "Test Task", - Description: "This is a test task", + Id: taskID, + CompetitionId: "comp1", + Title: "Test Task", + Description: "This is a test task", InCompetitionPosition: 1, - MaxPoints: 100, - MaxAttempts: 10, - Type: pb.TaskType_TASK_TYPE_INPUT, - CreatedAt: timestamppb.Now(), - UpdatedAt: timestamppb.Now(), + MaxPoints: 100, + MaxAttempts: 10, + Type: pb.TaskType_TASK_TYPE_INPUT, + CreatedAt: timestamppb.Now(), + UpdatedAt: timestamppb.Now(), } mockRepo.EXPECT().GetTask(ctx, taskID).Return(expectedTask, nil) @@ -65,14 +65,14 @@ func TestTaskService(t *testing.T) { t.Run("EditTask", func(t *testing.T) { task := &pb.Task{ - Id: "task1", - CompetitionId: "comp1", - Title: "Updated Test Task", - Description: "This is an updated test task", + Id: "task1", + CompetitionId: "comp1", + Title: "Updated Test Task", + Description: "This is an updated test task", InCompetitionPosition: 1, - MaxPoints: 150, - MaxAttempts: 5, - Type: pb.TaskType_TASK_TYPE_CHECKER, + MaxPoints: 150, + MaxAttempts: 5, + Type: pb.TaskType_TASK_TYPE_CHECKER, } mockRepo.EXPECT().EditTask(ctx, task).Return(task, nil) @@ -137,4 +137,4 @@ func TestTaskService(t *testing.T) { assert.NoError(t, err) assert.Equal(t, expectedAttachments, resp.Attachments) }) -} \ No newline at end of file +} diff --git a/internal/user/handler/grpc/handler.go b/internal/user/handler/grpc/handler.go index 7b4a915..149369d 100644 --- a/internal/user/handler/grpc/handler.go +++ b/internal/user/handler/grpc/handler.go @@ -3,15 +3,19 @@ package grpc import ( "context" - pb "datarush/pkg/api/user" "google.golang.org/protobuf/types/known/emptypb" + + pb "datarush/pkg/api/user" ) type UserService interface { GetProfile(ctx context.Context, req *pb.GetProfileRequest) (*pb.User, error) RegisterForCompetition(ctx context.Context, req *pb.RegisterForCompetitionRequest) (*emptypb.Empty, error) UnregisterFromCompetition(ctx context.Context, req *pb.UnregisterFromCompetitionRequest) (*emptypb.Empty, error) - ListUserCompetitions(ctx context.Context, req *pb.ListUserCompetitionsRequest) (*pb.ListUserCompetitionsResponse, error) + ListUserCompetitions( + ctx context.Context, + req *pb.ListUserCompetitionsRequest, + ) (*pb.ListUserCompetitionsResponse, error) } type UserHandler struct { @@ -27,14 +31,23 @@ func (h *UserHandler) GetProfile(ctx context.Context, req *pb.GetProfileRequest) return h.service.GetProfile(ctx, req) } -func (h *UserHandler) RegisterForCompetition(ctx context.Context, req *pb.RegisterForCompetitionRequest) (*emptypb.Empty, error) { +func (h *UserHandler) RegisterForCompetition( + ctx context.Context, + req *pb.RegisterForCompetitionRequest, +) (*emptypb.Empty, error) { return h.service.RegisterForCompetition(ctx, req) } -func (h *UserHandler) UnregisterFromCompetition(ctx context.Context, req *pb.UnregisterFromCompetitionRequest) (*emptypb.Empty, error) { +func (h *UserHandler) UnregisterFromCompetition( + ctx context.Context, + req *pb.UnregisterFromCompetitionRequest, +) (*emptypb.Empty, error) { return h.service.UnregisterFromCompetition(ctx, req) } -func (h *UserHandler) ListUserCompetitions(ctx context.Context, req *pb.ListUserCompetitionsRequest) (*pb.ListUserCompetitionsResponse, error) { +func (h *UserHandler) ListUserCompetitions( + ctx context.Context, + req *pb.ListUserCompetitionsRequest, +) (*pb.ListUserCompetitionsResponse, error) { return h.service.ListUserCompetitions(ctx, req) -} \ No newline at end of file +} diff --git a/internal/user/middleware/auth.go b/internal/user/middleware/auth.go index e86be98..0d53090 100644 --- a/internal/user/middleware/auth.go +++ b/internal/user/middleware/auth.go @@ -49,4 +49,4 @@ func AuthInterceptor(jwtSecret string) grpc.UnaryServerInterceptor { return nil, status.Errorf(codes.Unauthenticated, "invalid token") } -} \ No newline at end of file +} diff --git a/internal/user/repository/postgres/repository.go b/internal/user/repository/postgres/repository.go index a47a956..e411b52 100644 --- a/internal/user/repository/postgres/repository.go +++ b/internal/user/repository/postgres/repository.go @@ -3,8 +3,9 @@ package postgres import ( "context" - "datarush/pkg/api/user" "github.com/jmoiron/sqlx" + + "datarush/pkg/api/user" ) type UserRepository struct { @@ -17,22 +18,42 @@ func NewUserRepository(db *sqlx.DB) *UserRepository { func (r *UserRepository) GetProfile(ctx context.Context, userID string) (*user.User, error) { var u user.User - err := r.db.GetContext(ctx, &u, "SELECT id, username, email, full_name, avatar_url FROM users WHERE id = $1", userID) + err := r.db.GetContext( + ctx, + &u, + "SELECT id, username, email, full_name, avatar_url FROM users WHERE id = $1", + userID, + ) return &u, err } func (r *UserRepository) RegisterForCompetition(ctx context.Context, userID, competitionID string) error { - _, err := r.db.ExecContext(ctx, "INSERT INTO user_competitions (user_id, competition_id) VALUES ($1, $2)", userID, competitionID) + _, err := r.db.ExecContext( + ctx, + "INSERT INTO user_competitions (user_id, competition_id) VALUES ($1, $2)", + userID, + competitionID, + ) return err } func (r *UserRepository) UnregisterFromCompetition(ctx context.Context, userID, competitionID string) error { - _, err := r.db.ExecContext(ctx, "DELETE FROM user_competitions WHERE user_id = $1 AND competition_id = $2", userID, competitionID) + _, err := r.db.ExecContext( + ctx, + "DELETE FROM user_competitions WHERE user_id = $1 AND competition_id = $2", + userID, + competitionID, + ) return err } func (r *UserRepository) ListUserCompetitions(ctx context.Context, userID string) ([]string, error) { var competitionIDs []string - err := r.db.SelectContext(ctx, &competitionIDs, "SELECT competition_id FROM user_competitions WHERE user_id = $1", userID) + err := r.db.SelectContext( + ctx, + &competitionIDs, + "SELECT competition_id FROM user_competitions WHERE user_id = $1", + userID, + ) return competitionIDs, err -} \ No newline at end of file +} diff --git a/internal/user/service/service.go b/internal/user/service/service.go index 5c2db7e..0c23b96 100644 --- a/internal/user/service/service.go +++ b/internal/user/service/service.go @@ -4,9 +4,10 @@ import ( "context" "errors" + "google.golang.org/protobuf/types/known/emptypb" + "datarush/internal/user/middleware" pb "datarush/pkg/api/user" - "google.golang.org/protobuf/types/known/emptypb" ) type UserRepository interface { @@ -28,7 +29,10 @@ func (s *UserService) GetProfile(ctx context.Context, req *pb.GetProfileRequest) return s.repo.GetProfile(ctx, req.UserId) } -func (s *UserService) RegisterForCompetition(ctx context.Context, req *pb.RegisterForCompetitionRequest) (*emptypb.Empty, error) { +func (s *UserService) RegisterForCompetition( + ctx context.Context, + req *pb.RegisterForCompetitionRequest, +) (*emptypb.Empty, error) { userID, ok := ctx.Value(middleware.UserIDKey{}).(string) if !ok { return nil, errors.New("user ID not found in context") @@ -38,7 +42,10 @@ func (s *UserService) RegisterForCompetition(ctx context.Context, req *pb.Regist return &emptypb.Empty{}, err } -func (s *UserService) UnregisterFromCompetition(ctx context.Context, req *pb.UnregisterFromCompetitionRequest) (*emptypb.Empty, error) { +func (s *UserService) UnregisterFromCompetition( + ctx context.Context, + req *pb.UnregisterFromCompetitionRequest, +) (*emptypb.Empty, error) { userID, ok := ctx.Value(middleware.UserIDKey{}).(string) if !ok { return nil, errors.New("user ID not found in context") @@ -48,10 +55,13 @@ func (s *UserService) UnregisterFromCompetition(ctx context.Context, req *pb.Unr return &emptypb.Empty{}, err } -func (s *UserService) ListUserCompetitions(ctx context.Context, req *pb.ListUserCompetitionsRequest) (*pb.ListUserCompetitionsResponse, error) { +func (s *UserService) ListUserCompetitions( + ctx context.Context, + req *pb.ListUserCompetitionsRequest, +) (*pb.ListUserCompetitionsResponse, error) { competitionIDs, err := s.repo.ListUserCompetitions(ctx, req.UserId) if err != nil { return nil, err } return &pb.ListUserCompetitionsResponse{CompetitionIds: competitionIDs}, nil -} \ No newline at end of file +} diff --git a/internal/user/service/service_test.go b/internal/user/service/service_test.go index 7d4fb5c..9d26c72 100644 --- a/internal/user/service/service_test.go +++ b/internal/user/service/service_test.go @@ -9,8 +9,8 @@ import ( "datarush/internal/user/service/mocks" pb "datarush/pkg/api/user" - "go.uber.org/mock/gomock" "github.com/stretchr/testify/assert" + "go.uber.org/mock/gomock" ) func TestUserService(t *testing.T) { @@ -98,4 +98,4 @@ func TestUserService(t *testing.T) { assert.Error(t, err) assert.Equal(t, expectedError, err) }) -} \ No newline at end of file +}