Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ public interface IRoomRepository
Task<Room?> GetAsync(string roomCode);
Task<IReadOnlyList<Room>> GetAllAsync(CancellationToken ct);
Task CreateAsync(Room room);
Task UpdateAsync(Room room);
Task<bool> IncrementPlayerCountAsync(string roomCode);
Task CloseAsync(string roomCode);
}
15 changes: 13 additions & 2 deletions PushAndPull/Server/Application/UseCase/Room/JoinRoomUseCase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,18 @@ public async Task ExecuteAsync(JoinRoomCommand request)
throw new InvalidOperationException("INVALID_PASSWORD");
}

room.Join();
await _roomRepository.UpdateAsync(room);
room.Join(); // 도메인 선행 검증 (FULL_ROOM)

var success = await _roomRepository.IncrementPlayerCountAsync(request.RoomCode);
if (!success)
{
var roomAfterAttempt = await _roomRepository.GetAsync(request.RoomCode);
if (roomAfterAttempt == null)
throw new RoomNotFoundException(request.RoomCode);
if (roomAfterAttempt.Status != RoomStatus.Active)
throw new RoomNotActiveException(request.RoomCode);

throw new InvalidOperationException("FULL_ROOM");
}
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Net.Http.Json;
using System.Text.Json;
using Server.Application.Port.Output;
using Server.Domain.Exception.Auth;
Expand Down Expand Up @@ -85,13 +86,8 @@ private string BuildSteamApiUrl(string ticket)
private static async Task<SteamAuthResponse> ParseResponseAsync(
HttpResponseMessage response)
{
var json = await response.Content.ReadAsStringAsync();

var steamResponse = JsonSerializer.Deserialize<SteamAuthResponse>(
json,
JsonOptions
);

var steamResponse = await response.Content.ReadFromJsonAsync<SteamAuthResponse>(JsonOptions);

if (steamResponse?.Response.Params == null)
throw new SteamApiException("INVALID_RESPONSE");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,13 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)

entity.HasIndex(x => x.Status)
.HasDatabaseName("idx_room_status");

entity.HasIndex(x => new { x.Status, x.IsPrivate })
.HasDatabaseName("idx_room_status_private");

entity.HasIndex(x => new { x.Status, x.CreatedAt })
.HasDatabaseName("idx_room_status_created_at");

entity.Property(x => x.CreatedAt)
.HasColumnName("created_at")
.HasColumnType("timestamptz");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,21 +36,26 @@ public async Task CreateAsync(Room room)
await _context.SaveChangesAsync();
}

public async Task UpdateAsync(Room room)
public async Task<bool> IncrementPlayerCountAsync(string roomCode)
{
_context.Rooms.Update(room);
await _context.SaveChangesAsync();
var updated = await _context.Rooms
.Where(x => x.RoomCode == roomCode
&& x.Status == RoomStatus.Active
&& x.CurrentPlayers < x.MaxPlayers)
.ExecuteUpdateAsync(s => s
.SetProperty(x => x.CurrentPlayers, x => x.CurrentPlayers + 1));

return updated > 0;
}

// 주의: 이 메서드는 Room.Close()의 로직(Status = Closed, ExpiresAt = UtcNow)을 직접 반영하고 있습니다.
// Room.Close()에 새로운 비즈니스 로직이 추가될 경우 이 메서드도 함께 수정해야 합니다.
public async Task CloseAsync(string roomCode)
{
var room = await _context.Rooms
.FirstOrDefaultAsync(x => x.RoomCode == roomCode);

if (room == null)
return;

room.Close();
await _context.SaveChangesAsync();
await _context.Rooms
.Where(x => x.RoomCode == roomCode)
.ExecuteUpdateAsync(s => s
.SetProperty(x => x.Status, RoomStatus.Closed)
.SetProperty(x => x.ExpiresAt, DateTimeOffset.UtcNow));
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;

#nullable disable

namespace Server.Migrations
{
/// <inheritdoc />
public partial class AddRoomStatusCreatedAtIndex : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateIndex(
name: "idx_room_status_created_at",
schema: "room",
table: "room",
columns: new[] { "status", "created_at" });
}

/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "idx_room_status_created_at",
schema: "room",
table: "room");
}
}
}
Loading
Loading