Skip to content

Sync develop into main#58

Merged
Sunja-An merged 24 commits intomainfrom
develop
Feb 8, 2026
Merged

Sync develop into main#58
Sunja-An merged 24 commits intomainfrom
develop

Conversation

@Sunja-An
Copy link
Copy Markdown
Contributor

@Sunja-An Sunja-An commented Feb 8, 2026

Summary

Included Changes

Test plan

  • 빌드 성공 확인 (go build ./...)
  • 기존 테스트 통과 확인
  • multi-team Redis 키 동작 확인

🤖 Generated with Claude Code

Sunja-An and others added 24 commits January 30, 2026 17:53
- Add Match Detection Scheduler for automatic Valorant match polling
- Add Tournament Result Service for aggregating game results
- Add Game Scheduler Service for managing game start times
- Add domain entities: MatchResult, MatchPlayerStat
- Add ports: MatchDetectionPort, MatchResultDatabasePort, GameEventPublisherPort
- Add adapters: Valorant API, RabbitMQ event publisher, Match result DB
- Update Game controller with scheduling and result query APIs
- Update Contest service with tournament result integration
- Add DB migration for match detection fields
- Update Swagger documentation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Docker Compose setup for k6, InfluxDB, Grafana
- Add Grafana dashboard and datasource provisioning
- Add Mock MySQL server for isolated load testing
- Add load test execution script (run.sh)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Redis container helper for testcontainer-based integration tests
- Enable automatic Redis instance creation and cleanup in tests

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change module path from GAMERS-BE to github.com/FOR-GAMERS/GAMERS-BE
- Update all import references across 144 files

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Prevent application crash when clearing applications fails,
as this is a non-critical cleanup operation.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use BIGINT UNSIGNED for PK/FK columns in match_results and
  match_player_stats tables to match spec and existing conventions
- Add ForceDetectionStatus domain method to encapsulate forced state
  transitions instead of directly mutating DetectionStatus field

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Feat: Tournament Match Detection & Auto Result Recording
- Skip .env file loading when GIN_MODE=release (production)
- Add golang-migrate CLI and Makefile to Docker image for container migrations
- Add make package to Alpine runtime stage
- Remove outdated ERD_DIAGRAM.md

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Feat: Tournament Match Detection & Production Docker Improvements (#43)
Fix: fixing 24 Migration failed
Fix: fixing 24 Migration failed and Cloudflare r2 env added
Set cookie domain via COOKIE_DOMAIN env var (e.g. ".gamers.io.kr") to allow
frontend (gamers.io.kr) to access cookies set by backend (api.gamers.io.kr).
Add WEB_URL to CORS AllowOrigins so cross-origin requests with credentials work.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fix: Cross-subdomain cookie sharing and CORS for production
- Add CachedDiscordBotClient decorator with 5-min TTL for bot guilds and guild channels
- Parallelize independent Discord API calls using errgroup in GetAvailableGuilds and GetAvailableGuildTextChannels
- Add Discord cache Redis key utility functions
- Wire CachedDiscordBotClient into Discord dependency graph

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…ient

Resolves 502 Bad Gateway on POST /api/users/valorant by adding exponential
backoff retries (max 3), structured logging for all failure paths, and
proper error differentiation (404/429/other) instead of silently discarding
the upstream error.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Feat: Optimize Discord API performance with Redis caching and parallel execution
Include Role in JWT Claims so RequireAdmin middleware can verify
admin access directly from the token instead of querying the database
on every request.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Feat: Add user role to JWT claims (#54)
Resolves conflict in team_redis_adapter.go by keeping both:
- develop's IncrementFinalizedTeamCount/GetFinalizedTeamCount methods
- main's multi-team ClearTeam(contestID, teamID) signature from PR #57

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@Sunja-An Sunja-An merged commit 212c31c into main Feb 8, 2026
2 checks passed
@Sunja-An Sunja-An self-assigned this Feb 8, 2026
@Sunja-An Sunja-An added the 🎉 DEPLOY New feature or request label Feb 8, 2026
@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello @Sunja-An, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request synchronizes the main branch with the latest state of develop, integrating a suite of new functionalities and critical fixes. The core purpose is to enhance the platform's capabilities by introducing automated tournament match detection, improving Discord API interaction performance through caching, and refining authentication mechanisms. It also sets up robust load testing tools and improves the production deployment environment, ensuring a more stable and scalable application.

Highlights

Changelog
  • .gitignore
    • Added new entries for load-test/mock-mysql/mock-mysql and docs/TOURNAMENT_MATCH_DETECTION_SPEC.md.
  • cmd/server.go
    • Updated import paths to use github.com/FOR-GAMERS/GAMERS-BE.
    • Added logic to skip .env file loading in release mode.
    • Modified router.NewRouter to accept WEB_URL for dynamic CORS configuration.
    • Removed authInterceptor.SetUserQueryPort as user roles are now directly in JWT.
    • Added gameDeps.GameTeamRepository to contestDeps.ContestService and set gameDeps.TournamentResultService.SetContestDBPort.
  • db/migrations/000024_add_match_detection_fields.down.sql
    • Added new migration file to drop match_player_stats and match_results tables.
    • Conditionally dropped columns (scheduled_start_time, detection_window_minutes, detected_match_id, detection_status) and indexes from the games table.
  • db/migrations/000024_add_match_detection_fields.up.sql
    • Added new migration file to introduce scheduled_start_time, detection_window_minutes, detected_match_id, and detection_status columns to the games table.
    • Created new indexes (idx_games_detection, idx_games_scheduled) on the games table.
    • Created new tables: match_results and match_player_stats for storing match outcomes and player statistics.
  • docker/Dockerfile
    • Installed golang-migrate CLI within the builder stage.
    • Added make to Alpine packages in the final image.
    • Copied the migrate binary and Makefile to the final image for easier migration management.
  • docs/ERD_DIAGRAM.md
    • Removed this documentation file.
  • docs/docs.go
    • Added new API endpoints and DTO definitions for match detection and tournament results to Swagger documentation.
  • docs/swagger.json
    • Updated Swagger JSON with new API endpoints and DTO definitions for match detection and tournament results.
  • docs/swagger.yaml
    • Updated Swagger YAML with new API endpoints and DTO definitions for match detection and tournament results.
  • env/.env.example
    • Reordered environment variables for better organization.
    • Added COOKIE_DOMAIN and ENV variables for cookie management and environment detection.
  • go.mod
    • Updated the module path from GAMERS-BE to github.com/FOR-GAMERS/GAMERS-BE.
  • internal/auth/application/auth_service.go
    • Modified GenerateTokenPair calls to include user.Role in JWT claims.
  • internal/auth/application/port/query/auth_user_query_port.go
    • Updated import path.
  • internal/auth/application/port/refresh_token_cache_port.go
    • Updated import path.
  • internal/auth/infra/persistence/adapter/refresh_token_cache_adapter.go
    • Updated import paths.
  • internal/auth/middleware/auth_middleware.go
    • Removed UserQueryPort interface and SetUserQueryPort method.
    • Updated RequireAdmin to use userRole directly from the context, eliminating a database query.
    • Added GetUserRoleFromContext helper function.
  • internal/auth/presentation/auth_controller.go
    • Updated import paths.
  • internal/auth/provider.go
    • Updated import paths.
  • internal/banner/application/banner_service.go
    • Updated import paths.
  • internal/banner/application/dto/banner_dto.go
    • Updated import path.
  • internal/banner/application/port/banner_port.go
    • Updated import path.
  • internal/banner/domain/banner.go
    • Updated import path.
  • internal/banner/infra/persistence/adapter/banner_adapter.go
    • Updated import paths.
  • internal/banner/presentation/banner_controller.go
    • Updated import paths.
  • internal/banner/provider.go
    • Updated import paths.
  • internal/comment/application/comment_service.go
    • Updated import paths.
  • internal/comment/application/dto/comment_dto.go
    • Updated import paths.
  • internal/comment/application/port/comment_database_port.go
    • Updated import paths.
  • internal/comment/domain/comment.go
    • Updated import path.
  • internal/comment/infra/persistence/adapter/comment_database_adapter.go
    • Updated import paths.
  • internal/comment/presentation/comment_controller.go
    • Updated import paths.
  • internal/comment/provider.go
    • Updated import paths.
  • internal/contest/application/contest_application_service.go
    • Updated import paths.
  • internal/contest/application/contest_service.go
    • Added gameApplication and gamePort imports.
    • Extended TournamentGeneratorPort with ShuffleAndAllocateTeamsWithResult.
    • Added teamDBPort and gameTeamDBPort to ContestService struct and constructor.
    • Removed tournament bracket generation from SaveContest to be triggered later.
    • Refactored StartContest into startTournamentContest and startNonTournamentContest to handle tournament-specific logic, including team allocation and clearing applications.
  • internal/contest/application/dto/application_dto.go
    • Updated import path.
  • internal/contest/application/dto/contest_dto.go
    • Updated import paths.
  • internal/contest/application/port/contest_database_port.go
    • Updated import paths.
  • internal/contest/application/port/contest_member_database_port.go
    • Updated import paths.
  • internal/contest/domain/contest.go
    • Updated import paths.
  • internal/contest/domain/contest_member.go
    • Updated import path.
  • internal/contest/infra/adapter/discord_validation_adapter.go
    • Updated import paths.
  • internal/contest/infra/persistence/adapter/contest_application_redis_adapter.go
    • Updated import paths.
  • internal/contest/infra/persistence/adapter/contest_database_adapter.go
    • Updated import paths.
  • internal/contest/infra/persistence/adapter/contest_member_database_adapter.go
    • Updated import paths.
  • internal/contest/infra/persistence/adapter/event_publisher_rabbitmq_adapter.go
    • Updated import paths.
  • internal/contest/presentation/contest_application_controller.go
    • Updated import paths.
  • internal/contest/presentation/contest_controller.go
    • Updated import paths.
  • internal/contest/provider.go
    • Added gameTeamRepository to ProvideContestDependenciesFull and passed it to NewContestServiceFull.
  • internal/discord/application/discord_validation_service.go
    • Added golang.org/x/sync/errgroup import for parallel execution.
    • Parallelized fetching user guilds and bot guilds in GetAvailableGuilds for improved performance.
    • Parallelized bot-in-guild validation and user-in-guild check in GetAvailableGuildTextChannels.
  • internal/discord/application/port/discord_bot_port.go
    • Updated import path.
  • internal/discord/infra/discord_bot_cached_client.go
    • Added new file implementing CachedDiscordBotClient to wrap DiscordBotPort with Redis caching for guild and channel data, improving performance for repeated lookups.
  • internal/discord/infra/discord_bot_client.go
    • Updated import path.
  • internal/discord/infra/persistence/adapter/discord_token_redis_adapter.go
    • Updated import paths.
  • internal/discord/presentation/discord_controller.go
    • Updated import paths.
  • internal/discord/provider.go
    • Instantiated CachedDiscordBotClient to wrap DiscordBotClient for Redis caching.
  • internal/game/application/dto/contest_result_dto.go
    • Added new file defining DTOs for tournament contest results, including ContestResultResponse, RoundResult, GameResult, GameTeamResult, MatchResultSummary, and TeamSummary.
  • internal/game/application/dto/game_dto.go
    • Updated import path.
  • internal/game/application/dto/game_team_dto.go
    • Updated import path.
  • internal/game/application/dto/schedule_game_dto.go
    • Added new file defining DTOs for scheduling games and manual match results, including ScheduleGameRequest, ScheduleGameResponse, ManualResultRequest, MatchResultResponse, and PlayerStatResponse.
  • internal/game/application/dto/team_dto.go
    • Updated import paths.
  • internal/game/application/game_scheduler_service.go
    • Added new file defining GameSchedulerService for cron-triggered game activation and match detection, utilizing Redis distributed locks to prevent concurrent execution across instances.
  • internal/game/application/game_service.go
    • Added ScheduleGame method to set scheduled start time and detection window for a game.
    • Added GetDetectionStatus method to retrieve a game's detection status.
  • internal/game/application/game_team_service.go
    • Updated import paths.
  • internal/game/application/match_detection_service.go
    • Added new file defining MatchDetectionService to handle Valorant match detection, including DetectMatchForGame, SubmitManualResult, GetMatchResult, and GetMatchResultWithStats.
  • internal/game/application/port/game_database_port.go
    • Added GetGamesReadyToStart and GetGamesInDetection methods for scheduler queries.
  • internal/game/application/port/game_event_publisher_port.go
    • Added new file defining game event types and interfaces for publishing game events to RabbitMQ.
  • internal/game/application/port/game_team_database_port.go
    • Updated import path.
  • internal/game/application/port/match_detection_port.go
    • Added new file defining interfaces and DTOs for Valorant match data, including ValorantMatch, ValorantMatchDetail, ValorantTeamData, and ValorantPlayerData.
  • internal/game/application/port/match_result_database_port.go
    • Added new file defining the interface for match result persistence.
  • internal/game/application/port/team_database_port.go
    • Updated import path.
  • internal/game/application/port/team_event_publisher_port.go
    • Added TeamEventTypeContestTeamsReady event type.
    • Added ContestTeamsReadyEvent struct and PublishContestTeamsReadyEvent method.
  • internal/game/application/port/team_redis_port.go
    • Added IncrementFinalizedTeamCount and GetFinalizedTeamCount methods for contest-wide team readiness tracking.
  • internal/game/application/team_persistence_handler.go
    • Updated import paths.
  • internal/game/application/team_service.go
    • Added logic to FinalizeTeam to increment the finalized team count and publish a ContestTeamsReadyEvent when all teams in a contest are ready.
  • internal/game/application/tournament_result_service.go
    • Added new file defining TournamentResultService for retrieving tournament results and building ContestResultResponse.
  • internal/game/application/tournament_service.go
    • Updated import paths.
  • internal/game/domain/game.go
    • Added DetectionStatus enum and related methods (CanTransitionDetectionTo, TransitionDetectionTo, SetSchedule, IsReadyToActivate, IsDetectionWindowExpired, GetDetectionWindowEnd, ActivateForDetection, MarkDetected, MarkDetectionFailed, MarkManualResult, ForceDetectionStatus, FinishGame, IsDetecting) to manage the state of match detection for tournament games.
  • internal/game/domain/game_team.go
    • Updated import path.
  • internal/game/domain/match_player_stat.go
    • Added new file defining MatchPlayerStat struct and constructor for storing individual player statistics from detected matches.
  • internal/game/domain/match_result.go
    • Added new file defining MatchResult struct and constructor for storing detailed results of detected Valorant matches.
  • internal/game/domain/team.go
    • Updated import path.
  • internal/game/infra/persistence/adapter/game_database_adapter.go
    • Implemented GetGamesReadyToStart and GetGamesInDetection methods for fetching games based on their scheduled time and detection status.
  • internal/game/infra/persistence/adapter/game_event_publisher_rabbitmq_adapter.go
    • Added new file implementing GameEventPublisherRabbitMQAdapter for publishing game-related events to RabbitMQ.
  • internal/game/infra/persistence/adapter/game_team_database_adapter.go
    • Updated import paths.
  • internal/game/infra/persistence/adapter/match_detection_valorant_adapter.go
    • Added new file implementing MatchDetectionValorantAdapter to interact with the Henrik Dev Valorant API for fetching match data.
  • internal/game/infra/persistence/adapter/match_result_database_adapter.go
    • Added new file implementing MatchResultDatabaseAdapter for persisting match results and player statistics to the database.
  • internal/game/infra/persistence/adapter/team_consumer_rabbitmq_adapter.go
    • Updated import paths.
  • internal/game/infra/persistence/adapter/team_database_adapter.go
    • Updated import paths.
  • internal/game/infra/persistence/adapter/team_event_publisher_rabbitmq_adapter.go
    • Implemented PublishContestTeamsReadyEvent method to publish events when all teams in a contest are finalized.
  • internal/game/infra/persistence/adapter/team_persistence_publisher_rabbitmq_adapter.go
    • Updated import paths.
  • internal/game/infra/persistence/adapter/team_redis_adapter.go
    • Implemented IncrementFinalizedTeamCount and GetFinalizedTeamCount methods for Redis-based tracking of finalized teams.
  • internal/game/presentation/game_controller.go
    • Added matchDetectionSvc and tournamentResultSvc to GameController struct and constructor.
    • Registered new routes for match detection and tournament results, including /api/contests/{contestId}/games/{gameId}/schedule, /api/contests/{contestId}/games/{gameId}/result, /api/contests/{contestId}/games/{gameId}/detect, /api/contests/{contestId}/games/{gameId}/detection-status, /api/contests/{contestId}/games/{gameId}/result/stats, and /api/contests/{id}/result.
    • Implemented ScheduleGame, SubmitManualResult, GetDetectionStatus, GetMatchResult, GetMatchResultWithStats, TriggerDetection, and GetContestResult handlers.
  • internal/game/presentation/game_team_controller.go
    • Updated import paths.
  • internal/game/presentation/team_controller.go
    • Updated import paths.
  • internal/game/provider.go
    • Added GameTeamRepository, GameSchedulerService, MatchDetectionService, TournamentResultService to Dependencies.
    • Instantiated matchResultDatabaseAdapter, gameEventPublisher, matchDetectionAdapter, matchDetectionService, gameSchedulerService, tournamentResultService, and passed them to relevant services and controllers.
  • internal/global/common/handler/controller_helper.go
    • Updated import paths.
  • internal/global/common/router/router.go
    • Updated NewRouter to accept webURL and dynamically add it to AllowOrigins for CORS, supporting cross-subdomain cookie sharing.
  • internal/global/exception/game_error_status.go
    • Added new error statuses related to match detection, such as ErrInvalidDetectionStatusTransition, ErrScheduledTimeInPast, ErrGameNotActive, ErrDetectionNotFailed, ErrMatchResultNotFound, ErrMatchResultAlreadyExists, ErrWinnerTeamNotInGame, ErrMissingValorantAccount, ErrDetectionWindowExpired, and ErrSchedulerLockFailed.
  • internal/global/exception/valorant_error_status.go
    • Added ErrValorantApiRateLimit for handling Valorant API rate limit errors.
  • internal/global/middleware/error_handler.go
    • Updated import path.
  • internal/global/security/jwt/application/jwt_token_service.go
    • Modified Generate and GenerateTokenPair methods to include the user's role in JWT claims.
  • internal/global/security/jwt/domain/token.go
    • Updated import path.
  • internal/global/security/jwt/domain/token_strategy.go
    • Added Role field to the Claims struct and role parameter to the Generate method.
  • internal/global/security/jwt/infra/access_token_strategy.go
    • Modified Generate method to include the user's role in access token JWT claims.
  • internal/global/security/jwt/infra/refresh_token_strategy.go
    • Modified Generate method to include the user's role in refresh token JWT claims.
  • internal/global/security/jwt/provider.go
    • Updated import paths.
  • internal/global/utils/redis_key_utils.go
    • Added new Redis key utility functions for Discord bot caching, including GetDiscordBotGuildsKey and GetDiscordGuildChannelsKey.
  • internal/notification/application/dto/notification_dto.go
    • Updated import path.
  • internal/notification/application/notification_service.go
    • Updated import paths.
  • internal/notification/application/port/notification_port.go
    • Updated import path.
  • internal/notification/application/sse_manager.go
    • Updated import paths.
  • internal/notification/infra/persistence/adapter/notification_database_adapter.go
    • Updated import path.
  • internal/notification/infra/sse/sse_client.go
    • Updated import path.
  • internal/notification/presentation/notification_controller.go
    • Updated import paths.
  • internal/notification/provider.go
    • Updated import paths.
  • internal/oauth2/application/discord_service.go
    • Updated import paths.
    • Modified HandleDiscordCallback to retrieve and include userRole in JWT generation, ensuring role-based authorization is available immediately after OAuth2 login.
  • internal/oauth2/application/port/oauth2_database_port.go
    • Updated import path.
  • internal/oauth2/application/port/oauth2_user_port.go
    • Added FindById method to retrieve user information by ID.
  • internal/oauth2/infra/discord/config.go
    • Updated import path.
  • internal/oauth2/infra/discord/discord_client.go
    • Updated import path.
  • internal/oauth2/infra/persistence/adapter/oauth2_database_adapter.go
    • Updated import paths.
  • internal/oauth2/infra/state/state_manager.go
    • Updated import path.
  • internal/oauth2/presentation/discord_controller.go
    • Updated import paths.
    • Added cookieDomain to DiscordController struct and constructor.
    • Used cookieDomain for setting cookies and adjusted SameSite attribute to SameSiteNoneMode for secure contexts to enable cross-subdomain cookie sharing.
  • internal/oauth2/provider.go
    • Passed cookieDomain to NewDiscordController during dependency injection.
  • internal/point/application/dto/valorant_dto.go
    • Updated import path.
  • internal/point/application/port/valorant_score_table_database_port.go
    • Updated import path.
  • internal/point/application/valorant_service.go
    • Updated import paths.
  • internal/point/infra/persistence/adapter/valorant_score_table_database_adapter.go
    • Updated import paths.
  • internal/point/presentation/valorant_controller.go
    • Updated import paths.
  • internal/point/provider.go
    • Updated import paths.
  • internal/storage/application/dto/storage_dto.go
    • Updated import path.
  • internal/storage/application/port/storage_port.go
    • Updated import path.
  • internal/storage/application/storage_service.go
    • Updated import paths.
  • internal/storage/domain/storage.go
    • Updated import path.
  • internal/storage/infra/r2_storage_adapter.go
    • Updated import path.
  • internal/storage/presentation/storage_controller.go
    • Updated import paths.
  • internal/storage/provider.go
    • Updated import paths.
  • internal/user/application/port/command/user_command_port.go
    • Updated import path.
  • internal/user/application/port/port/user_query_port.go
    • Updated import path.
  • internal/user/application/port/user_database_port.go
    • Updated import path.
  • internal/user/application/user_service.go
    • Updated import paths.
  • internal/user/domain/user.go
    • Updated import paths.
  • internal/user/infra/persistence/adapter/oauth2_user_adapter.go
    • Added FindById method to retrieve user information by ID.
  • internal/user/infra/persistence/adapter/user_database_adapter.go
    • Updated import paths.
  • internal/user/infra/persistence/command/user_command_adapter.go
    • Updated import paths.
  • internal/user/infra/persistence/query/auth_user_query_adapter.go
    • Updated import paths.
  • internal/user/infra/persistence/query/user_query_adapter.go
    • Updated import paths.
  • internal/user/presentation/user_controller.go
    • Updated import paths.
  • internal/user/provider.go
    • Updated import paths.
  • internal/valorant/application/valorant_user_service.go
    • Updated import paths.
  • internal/valorant/infra/valorant_api_client.go
    • Added maxRetries field and implemented retry logic with exponential backoff for GetMMRByName and findPeakRank to handle Valorant API rate limits and transient errors.
    • Added specific error handling for ErrValorantApiRateLimit.
  • internal/valorant/presentation/valorant_user_controller.go
    • Updated import paths.
  • internal/valorant/provider.go
    • Updated import paths.
  • load-test/docker-compose.yaml
    • Added new Docker Compose configuration for setting up k6 load testing environment, including InfluxDB and Grafana.
  • load-test/grafana/dashboards/k6-load-test.json
    • Added new Grafana dashboard definition for visualizing k6 load test results with various metrics like response time, error rate, and custom scenario-specific metrics.
  • load-test/grafana/provisioning/dashboards/dashboard.yaml
    • Added new Grafana provisioning file to automatically load the k6 load test dashboard.
  • load-test/grafana/provisioning/datasources/influxdb.yaml
    • Added new Grafana provisioning file to configure InfluxDB as a data source for k6 metrics.
  • load-test/mock-mysql/go.mod
    • Added new Go module file for the mock MySQL server.
  • load-test/mock-mysql/go.sum
    • Added new Go sum file for the mock MySQL server dependencies.
  • load-test/mock-mysql/main.go
    • Added new file for a mock MySQL server using dolthub/go-mysql-server to simulate database interactions during load testing, including schema creation and seed data insertion.
  • load-test/mock-mysql/schema.go
    • Added new file defining the database schema and seed data generation logic for the mock MySQL server, creating users, contests, teams, and team members.
  • load-test/run.sh
    • Added new shell script for orchestrating k6 load tests, allowing execution of various scenarios (e.g., team-invite, application, contest-start, tournament-create, full-flow, team-query) and managing the Docker Compose environment.
  • scripts/force-migration.go
    • Updated import path.
  • test/contest/application/contest_service_test.go
    • Updated import paths.
    • Added ShuffleAndAllocateTeamsWithResult to MockTournamentGeneratorPort.
    • Updated TestContestService_SaveContest_WithTournamentBracketGeneration to pass teamDBPort and gameTeamDBPort to NewContestServiceFull.
  • test/contest/domain/contest_member_test.go
    • Updated import paths.
  • test/contest/domain/contest_test.go
    • Updated import paths.
  • test/contest/infra/persistence/contest_application_redis_benchmark_test.go
    • Updated import paths.
  • test/contest/infra/persistence/contest_database_adapter_test.go
    • Updated import paths.
  • test/contest/infra/persistence/contest_member_benchmark_test.go
    • Updated import paths.
  • test/contest/infra/persistence/contest_member_database_adapter_test.go
    • Updated import paths.
  • test/contest/integration/contest_integration_test.go
    • Updated import paths.
  • test/contest/integration/tournament_flow_test.go
    • Updated import paths.
    • Implemented GetGamesReadyToStart and GetGamesInDetection for InMemoryGameAdapter.
    • Updated SetupTest to pass teamAdapter and gameTeamAdapter to NewContestServiceFull.
  • test/contest/presentation/contest_application_controller_test.go
    • Updated import paths.
  • test/contest/presentation/contest_controller_test.go
    • Updated import paths.
  • test/global/support/redis_container.go
    • Added new file for setting up a Redis container using Testcontainers for integration tests.
Activity
  • The pull request aims to synchronize the develop branch with main, integrating all recent changes.
  • A specific conflict in team_redis_adapter.go was addressed, ensuring compatibility between multi-team Redis fixes and existing develop functionalities.
  • The PR incorporates several new features, including a comprehensive tournament match detection system and automatic result recording.
  • Performance improvements were made to Discord API interactions through the implementation of Redis caching and parallel execution.
  • Security was enhanced by adding user roles to JWT claims, enabling DB-free admin authorization.
  • Improvements to the production environment include cross-subdomain cookie sharing, CORS fixes, and general Docker and environment optimizations.
  • New load testing infrastructure using k6 and Grafana has been added, along with support for Redis Testcontainers in integration tests.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

develop 브랜치를 main으로 동기화하는 중요한 PR입니다. 많은 기능이 추가되고 리팩토링이 이루어졌네요. JWT에 사용자 역할을 포함시켜 RequireAdmin 미들웨어에서 데이터베이스 조회를 제거한 점은 성능 향상에 큰 도움이 되는 훌륭한 개선입니다. Discord API 호출 시 errgroup을 사용한 병렬 처리와 Redis를 이용한 캐싱 데코레이터 패턴 적용으로 응답 속도를 개선한 점도 인상적입니다. 새로 추가된 경기 자동 감지 및 스케줄링 기능은 분산 락을 사용하여 여러 인스턴스 환경에서도 안전하게 동작하도록 설계된 점이 좋습니다. 전반적으로 코드 품질을 높이고 시스템 안정성과 성능을 개선하기 위한 고민이 많이 엿보이는 좋은 변경사항들입니다. 몇 가지 추가 개선 제안을 코멘트로 남겼습니다.

Comment on lines +180 to +196
for _, m := range members {
user, err := s.userQueryPort.FindById(m.UserID)
if err != nil {
log.Printf("[MatchDetection] Failed to find user %d: %v", m.UserID, err)
continue
}
if !user.HasValorantLinked() {
log.Printf("[MatchDetection] User %d (team %d) has no Valorant account linked, skipping", m.UserID, teamID)
continue
}
accounts = append(accounts, ValorantAccountInfo{
UserID: m.UserID,
TeamID: teamID,
Name: *user.RiotName,
Tag: *user.RiotTag,
})
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

getTeamValorantAccounts 함수 내에서 루프를 돌며 각 팀 멤버에 대해 s.userQueryPort.FindById를 호출하고 있습니다. 이는 N명의 팀원이 있을 경우 N번의 데이터베이스 쿼리를 발생시키는 N+1 쿼리 문제입니다. 부하가 많은 상황에서 심각한 성능 저하를 유발할 수 있습니다.

개선을 위해 UserQueryPort에 여러 ID를 한 번에 조회할 수 있는 FindByIds와 같은 메서드를 추가하고, 이를 사용하여 모든 팀원의 정보를 단일 쿼리로 가져오는 것을 권장합니다.

Comment on lines 31 to 88
func (c *ValorantApiClient) GetMMRByName(region, name, tag string) (*port.ValorantMMRData, error) {
// Get current MMR
mmrResp, err := c.client.GetMMRByNameV2(govapi.GetMMRByNameV2Params{
Affinity: region,
Name: name,
Tag: tag,
})
var mmrResp *govapi.GetMMRByNameV2Response
var err error

for attempt := 0; attempt <= c.maxRetries; attempt++ {
if attempt > 0 {
backoff := time.Duration(1<<uint(attempt-1)) * time.Second
log.Printf("[ValorantAPI] Retry attempt %d for GetMMRByName(%s#%s), waiting %v",
attempt, name, tag, backoff)
time.Sleep(backoff)
}

mmrResp, err = c.client.GetMMRByNameV2(govapi.GetMMRByNameV2Params{
Affinity: region,
Name: name,
Tag: tag,
})
if err == nil && mmrResp != nil && mmrResp.Status == 200 {
break
}

if mmrResp != nil && mmrResp.Status == 404 {
log.Printf("[ValorantAPI] Player not found: %s#%s in region %s", name, tag, region)
return nil, exception.ErrValorantPlayerNotFound
}

if mmrResp != nil && mmrResp.Status == 429 {
log.Printf("[ValorantAPI] Rate limited on GetMMRByName(%s#%s), attempt %d/%d",
name, tag, attempt, c.maxRetries)
continue
}

if err != nil {
log.Printf("[ValorantAPI] Error on GetMMRByName(%s#%s): %v (attempt %d/%d)",
name, tag, err, attempt, c.maxRetries)
} else if mmrResp != nil {
log.Printf("[ValorantAPI] Non-200 status %d on GetMMRByName(%s#%s) (attempt %d/%d)",
mmrResp.Status, name, tag, attempt, c.maxRetries)
}
}

if err != nil {
log.Printf("[ValorantAPI] All retries exhausted for GetMMRByName(%s#%s), last error: %v", name, tag, err)
return nil, exception.ErrValorantApiError
}

if mmrResp.Status != 200 {
if mmrResp.Status == 404 {
return nil, exception.ErrValorantPlayerNotFound
if mmrResp == nil || mmrResp.Status != 200 {
status := 0
if mmrResp != nil {
status = mmrResp.Status
}
if status == 429 {
log.Printf("[ValorantAPI] Rate limit exhausted for GetMMRByName(%s#%s) after %d retries",
name, tag, c.maxRetries)
return nil, exception.ErrValorantApiRateLimit
}
log.Printf("[ValorantAPI] Failed GetMMRByName(%s#%s), final status: %d", name, tag, status)
return nil, exception.ErrValorantApiError
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

valorant_api_client.gomatch_detection_valorant_adapter.go 두 파일에 Valorant API 호출을 위한 재시도 로직이 중복으로 구현되어 있습니다. 이 로직은 지수 백오프를 포함하여 잘 구현되었지만, 코드가 중복되어 유지보수성을 저해할 수 있습니다.

이 재시도 로직을 공통 유틸리티 함수나 Valorant API 클라이언트를 감싸는 래퍼(wrapper)로 추상화하는 것을 고려해 보세요. 이렇게 하면 코드 중복을 줄이고, 재시도 정책을 한 곳에서 일관되게 관리할 수 있습니다. 예를 들어, API 호출 함수를 인자로 받는 withRetry 헬퍼 함수를 만들 수 있습니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🎉 DEPLOY New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant