diff --git a/ArenaService/ArenaService/ArenaParticipant.cs b/ArenaService/ArenaService/ArenaParticipant.cs index 50af50f..4066e33 100644 --- a/ArenaService/ArenaService/ArenaParticipant.cs +++ b/ArenaService/ArenaService/ArenaParticipant.cs @@ -23,7 +23,8 @@ public ArenaParticipant( Address avatarAddr, int score, int rank, - AvatarState avatarState, + string nameWithHash, + int level, int portraitId, int winScore, int loseScore, @@ -36,8 +37,8 @@ public ArenaParticipant( LoseScore = loseScore; Cp = cp; PortraitId = portraitId; - NameWithHash = avatarState.NameWithHash; - Level = avatarState.level; + NameWithHash = nameWithHash; + Level = level; } public void Update(int winScore, int loseScore) diff --git a/ArenaService/ArenaService/ArenaWorker.cs b/ArenaService/ArenaService/ArenaWorker.cs index 79df974..69592ec 100644 --- a/ArenaService/ArenaService/ArenaWorker.cs +++ b/ArenaService/ArenaService/ArenaWorker.cs @@ -1,10 +1,4 @@ using System.Diagnostics; -using Bencodex.Types; -using Libplanet.Action.State; -using Libplanet.Crypto; -using Nekoyume.Model.Arena; -using Nekoyume.Module; -using Nekoyume.TableData; namespace ArenaService; @@ -66,6 +60,9 @@ public async Task PrepareArenaParticipants() var currentRoundData = await _rpcClient.GetRoundData(tip); var participants = await _rpcClient.GetArenaParticipantsState(tip, currentRoundData); var cacheKey = $"{currentRoundData.ChampionshipId}_{currentRoundData.Round}"; + var scoreCacheKey = $"{cacheKey}_score"; + var prevAddrAndScores = await _service.GetAvatarAddrAndScores(scoreCacheKey); + var prevArenaParticipants = await _service.GetArenaParticipantsAsync(cacheKey); var expiry = TimeSpan.FromMinutes(5); if (participants is null) { @@ -75,10 +72,17 @@ public async Task PrepareArenaParticipants() } var avatarAddrList = participants.AvatarAddresses; - var avatarAddrAndScoresWithRank = await _rpcClient.AvatarAddrAndScoresWithRank(tip, avatarAddrList, currentRoundData); - var result = await _rpcClient.GetArenaParticipants(tip, avatarAddrList, avatarAddrAndScoresWithRank); + // 최신상태의 아바타 주소, 점수를 조회 + var avatarAddrAndScores = await _rpcClient.GetAvatarAddrAndScores(tip, avatarAddrList, currentRoundData); + // 이전상태의 아바타 주소, 점수를 비교해서 추가되거나 점수가 변경된 대상만 찾음 + var filtered = avatarAddrAndScores.Except(prevAddrAndScores).ToList(); + // 전체목록의 랭킹 순서 처리 + var avatarAddrAndScoresWithRank = _rpcClient.AvatarAddrAndScoresWithRank(avatarAddrAndScores); + // 전체목록의 ArenaParticipant 업데이트 + var result = await _rpcClient.GetArenaParticipants(tip, filtered.Select(i => i.avatarAddr).ToList(), avatarAddrAndScoresWithRank, prevArenaParticipants); await _service.SetArenaParticipantsAsync(cacheKey, result, expiry); await _service.SetSeasonAsync(cacheKey, expiry); + await _service.SetAvatarAddrAndScores(scoreCacheKey, avatarAddrAndScores); sw.Stop(); _logger.LogInformation("[ArenaParticipantsWorker]Set Arena Cache[{CacheKey}]: {Elapsed}", cacheKey, sw.Elapsed); } diff --git a/ArenaService/ArenaService/IRedisArenaParticipantsService.cs b/ArenaService/ArenaService/IRedisArenaParticipantsService.cs index 7a1532d..c59c02e 100644 --- a/ArenaService/ArenaService/IRedisArenaParticipantsService.cs +++ b/ArenaService/ArenaService/IRedisArenaParticipantsService.cs @@ -8,6 +8,6 @@ public interface IRedisArenaParticipantsService Task SetArenaParticipantsAsync(string key, List value, TimeSpan? expiry = null); Task GetSeasonKeyAsync(); Task SetSeasonAsync(string value, TimeSpan? expiry = null); - Task> GetAvatarAddrAndScoresWithRank(string key); - Task SetAvatarAddrAndScoresWithRank(string key, List value, TimeSpan? expiry = null); + Task> GetAvatarAddrAndScores(string key); + Task SetAvatarAddrAndScores(string key, List<(Address avatarAddr, int score)> value, TimeSpan? expiry = null); } diff --git a/ArenaService/ArenaService/RedisArenaParticipantsService.cs b/ArenaService/ArenaService/RedisArenaParticipantsService.cs index c96d6d5..c3c54cc 100644 --- a/ArenaService/ArenaService/RedisArenaParticipantsService.cs +++ b/ArenaService/ArenaService/RedisArenaParticipantsService.cs @@ -1,4 +1,5 @@ using System.Text.Json; +using Libplanet.Crypto; using StackExchange.Redis; namespace ArenaService; @@ -43,18 +44,18 @@ public async Task SetSeasonAsync(string value, TimeSpan? expiry = null) await _db.StringSetAsync(SeasonKey, value, expiry); } - public async Task> GetAvatarAddrAndScoresWithRank(string key) + public async Task> GetAvatarAddrAndScores(string key) { RedisValue result = await _db.StringGetAsync(key); if (result.IsNull) { - return new List(); + return new List<(Address avatarAddr, int score)>(); } - return JsonSerializer.Deserialize>(result.ToString())!; + return JsonSerializer.Deserialize>(result.ToString())!; } - public async Task SetAvatarAddrAndScoresWithRank(string key, List value, TimeSpan? expiry = null) + public async Task SetAvatarAddrAndScores(string key, List<(Address avatarAddr, int score)> value, TimeSpan? expiry = null) { var serialized = JsonSerializer.Serialize(value); await _db.StringSetAsync(key, serialized, expiry);