From f25e28a7b201d6f4e221d7e98739de90980f74f3 Mon Sep 17 00:00:00 2001 From: Sean-mn Date: Wed, 4 Mar 2026 12:10:22 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20=EB=A0=88=EB=B2=A8=20=EC=BA=90?= =?UTF-8?q?=EC=8B=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../UseCase/Player/GetPlayerLevelUseCase.cs | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/PaperMania/Server/Application/UseCase/Player/GetPlayerLevelUseCase.cs b/PaperMania/Server/Application/UseCase/Player/GetPlayerLevelUseCase.cs index 40f8bf6..3073509 100644 --- a/PaperMania/Server/Application/UseCase/Player/GetPlayerLevelUseCase.cs +++ b/PaperMania/Server/Application/UseCase/Player/GetPlayerLevelUseCase.cs @@ -1,10 +1,12 @@ using Server.Api.Dto.Response; using Server.Application.Exceptions; using Server.Application.Port.Input.Player; +using Server.Application.Port.Output.Cache; using Server.Application.Port.Output.Persistence; using Server.Application.Port.Output.StaticData; using Server.Application.UseCase.Player.Command; using Server.Application.UseCase.Player.Result; +using Server.Infrastructure.Cache; namespace Server.Application.UseCase.Player; @@ -12,34 +14,38 @@ public class GetPlayerLevelUseCase : IGetPlayerLevelUseCase { private readonly IDataRepository _repository; private readonly ILevelDefinitionStore _store; + private readonly ICacheAsideService _cache; public GetPlayerLevelUseCase( IDataRepository repository, - ILevelDefinitionStore store + ILevelDefinitionStore store, + ICacheAsideService cache ) { _repository = repository; _store = store; + _cache = cache; } public async Task ExecuteAsync(GetPlayerLevelCommand request, CancellationToken ct) { - var data = await _repository.FindByUserIdAsync(request.UserId, ct) - ?? throw new RequestException( - ErrorStatusCode.NotFound, - "PLAYER_NOT_FOUND", - new { UserId = request.UserId }); + var player = await _cache.GetOrSetAsync( + CacheKey.Profile.ByUserId(request.UserId), + async (token) => await _repository.FindByUserIdAsync(request.UserId, token), + TimeSpan.FromDays(30), + ct + ); - var levelDef = _store.GetLevelDefinition(data.Level) + var levelDef = _store.GetLevelDefinition(player.Level) ?? throw new RequestException( ErrorStatusCode.NotFound, "LEVEL_NOT_FOUND", - new { Level = data.Level }); + new { Level = player.Level }); return new GetPlayerLevelResult( - data.Level, - data.Exp, + player.Level, + player.Exp, levelDef.MaxExp ); } From a7069cf1fca7d1184aa839c80cf869938814ef4e Mon Sep 17 00:00:00 2001 From: Sean-mn Date: Wed, 4 Mar 2026 12:15:20 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20=EB=8B=A8=EC=9C=84=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Application/Player/GetPlayerLevelUseCaseTests.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/PaperMania/Server.Tests/Application/Player/GetPlayerLevelUseCaseTests.cs b/PaperMania/Server.Tests/Application/Player/GetPlayerLevelUseCaseTests.cs index 9832ac0..f8772b9 100644 --- a/PaperMania/Server.Tests/Application/Player/GetPlayerLevelUseCaseTests.cs +++ b/PaperMania/Server.Tests/Application/Player/GetPlayerLevelUseCaseTests.cs @@ -2,6 +2,7 @@ using Moq; using Server.Api.Dto.Response; using Server.Application.Exceptions; +using Server.Application.Port.Output.Cache; using Server.Application.Port.Output.Persistence; using Server.Application.Port.Output.StaticData; using Server.Application.UseCase.Player; @@ -15,9 +16,10 @@ public class GetPlayerLevelUseCaseTests { private readonly Mock _repositoryMock = new(); private readonly Mock _levelStoreMock = new(); + private readonly Mock _cacheMock = new(); private GetPlayerLevelUseCase CreateUseCase() => - new(_repositoryMock.Object, _levelStoreMock.Object); + new(_repositoryMock.Object, _levelStoreMock.Object, _cacheMock.Object); [Fact] public async Task ExecuteAsync_Should_Throw_When_Player_Not_Found() From 42cc1bef1fbc57c34696b23ed816fba3c96f3d54 Mon Sep 17 00:00:00 2001 From: Sean-mn Date: Wed, 4 Mar 2026 12:24:03 +0900 Subject: [PATCH 3/3] =?UTF-8?q?fix:=20=EB=A0=88=EB=B2=A8=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Player/GetPlayerLevelUseCaseTests.cs | 25 +++++++++++-------- .../UseCase/Player/GetPlayerLevelUseCase.cs | 5 ++++ 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/PaperMania/Server.Tests/Application/Player/GetPlayerLevelUseCaseTests.cs b/PaperMania/Server.Tests/Application/Player/GetPlayerLevelUseCaseTests.cs index f8772b9..38c227b 100644 --- a/PaperMania/Server.Tests/Application/Player/GetPlayerLevelUseCaseTests.cs +++ b/PaperMania/Server.Tests/Application/Player/GetPlayerLevelUseCaseTests.cs @@ -21,12 +21,21 @@ public class GetPlayerLevelUseCaseTests private GetPlayerLevelUseCase CreateUseCase() => new(_repositoryMock.Object, _levelStoreMock.Object, _cacheMock.Object); + private void SetupCache(PlayerData? returnValue) + { + _cacheMock + .Setup(x => x.GetOrSetAsync( + It.IsAny(), + It.IsAny>>(), + It.IsAny(), + It.IsAny())) + .ReturnsAsync(returnValue); + } + [Fact] public async Task ExecuteAsync_Should_Throw_When_Player_Not_Found() { - _repositoryMock - .Setup(x => x.FindByUserIdAsync(It.IsAny(), It.IsAny())) - .ReturnsAsync((PlayerData?)null); + SetupCache(null); var useCase = CreateUseCase(); var command = new GetPlayerLevelCommand(1); @@ -42,9 +51,7 @@ public async Task ExecuteAsync_Should_Throw_When_Level_Not_Found() { var gameData = PlayerData.Create(1, "Player"); - _repositoryMock - .Setup(x => x.FindByUserIdAsync(1, It.IsAny())) - .ReturnsAsync(gameData); + SetupCache(gameData); _levelStoreMock .Setup(x => x.GetLevelDefinition(It.IsAny())) @@ -63,11 +70,9 @@ public async Task ExecuteAsync_Should_Throw_When_Level_Not_Found() public async Task ExecuteAsync_Should_Return_Level_Info_When_Success() { var gameData = PlayerData.Create(1, "Player"); - var levelDefinition = new LevelDefinition(1,100, 50); + var levelDefinition = new LevelDefinition(1, 100, 50); - _repositoryMock - .Setup(x => x.FindByUserIdAsync(1, It.IsAny())) - .ReturnsAsync(gameData); + SetupCache(gameData); _levelStoreMock .Setup(x => x.GetLevelDefinition(1)) diff --git a/PaperMania/Server/Application/UseCase/Player/GetPlayerLevelUseCase.cs b/PaperMania/Server/Application/UseCase/Player/GetPlayerLevelUseCase.cs index 3073509..fd179df 100644 --- a/PaperMania/Server/Application/UseCase/Player/GetPlayerLevelUseCase.cs +++ b/PaperMania/Server/Application/UseCase/Player/GetPlayerLevelUseCase.cs @@ -36,6 +36,11 @@ public async Task ExecuteAsync(GetPlayerLevelCommand reque TimeSpan.FromDays(30), ct ); + + if (player == null) + throw new RequestException( + ErrorStatusCode.NotFound, + "PLAYER_NOT_FOUND"); var levelDef = _store.GetLevelDefinition(player.Level) ?? throw new RequestException(