using Renci.SshNet.Security; using StackExchange.Redis; using ServerCore; using ServerBase; namespace ServerCommon; public class UgcNpcTotalRankCache : CacheBase { public long TotalRankCount { get; set; } public List<(string guid, long score)> Ranks { get; set; } = new(); public string toBasicString() { return $"UgcNpcTotalRankCache - total:{TotalRankCount} / list: {Ranks}"; } } public class UgcNpcTotalRankCacheRequest : RedisRequestSharedBase { // in private readonly string m_rank_type; private DateTime m_date_time { get; set; } // out private UgcNpcTotalRankCache? m_total_rank_cache_nullable { get; set; } public UgcNpcTotalRankCacheRequest(UgcNpcRankType type, RedisConnector redisConnector) : base(type.ToString(), redisConnector) { m_rank_type = type.ToString(); m_date_time = DateTimeHelper.MinTime; } public UgcNpcTotalRankCacheRequest(UgcNpcRankType type, DateTime time, RedisConnector redisConnector) : base( type.ToString(), redisConnector) { m_rank_type = type.ToString(); m_date_time = time; } protected override string onMakeKey() { if (m_date_time == DateTimeHelper.MinTime) return $"rank:{m_rank_type}:total"; var date = m_date_time.ToString("yyyy-MM-dd"); return $"rank:{m_rank_type}:total:{date}"; } public override string toBasicString() => $"UgcNpcTotalRankCache: in[{m_rank_type}], out[{m_total_rank_cache_nullable?.toBasicString()}]"; public UgcNpcTotalRankCache? getTotalCache() => m_total_rank_cache_nullable; public async Task isExistKey() { try { var result = await onPrepareRequest(); if (result.isFail()) return false; var database = getDatabase(); var redis_value = await database.KeyExistsAsync(onMakeKey()); return redis_value; } catch (Exception e) { var error_code = ServerErrorCode.TryCatchException; var err_msg = $"Failed to get isExistKey from Redis !!! : : errorCode{error_code}, errMsg:{e.Message} - {nameof(isExistKey)}"; Log.getLogger().error(err_msg); } return false; } public async Task getRanks(int pageNum, int size) { var result = new Result(); string err_msg; var start = (long)pageNum * size; var end = start + size; try { result = await onPrepareRequest(); if (result.isFail()) return result; var database = getDatabase(); m_total_rank_cache_nullable = new(); var rank_key = onMakeKey(); if (string.IsNullOrEmpty(rank_key)) { m_total_rank_cache_nullable.TotalRankCount = 0; return result; } var total_count = await database.SortedSetLengthAsync(rank_key); if (total_count < start) { err_msg = $"Failed to get UgcNpcTotalRankCache from Redis !!! : out of range rank [{total_count}] - {pageNum} / {size}"; result.setFail(ServerErrorCode.UgcNpcRankOutOfRange, err_msg); Log.getLogger().error(result.toBasicString()); return result; } if (total_count < end) end = total_count; var redis_value = await database.SortedSetRangeByRankWithScoresAsync(getKey(), start, end, Order.Descending); m_total_rank_cache_nullable.TotalRankCount = total_count; foreach (var value in redis_value) { m_total_rank_cache_nullable.Ranks.Add((value.Element.ToString(), (long)value.Score)); } return result; } catch (Exception e) { var error_code = ServerErrorCode.TryCatchException; err_msg = $"Failed to get UgcNpcTotalRankCache from Redis !!! : : errorCode{error_code}, errMsg:{e.Message} - {nameof(getRanks)}"; result.setFail(error_code, err_msg); Log.getLogger().error(result.toBasicString()); } return result; } public async Task initRankScore(Dictionary ranks) { var result = new Result(); string err_msg; var redis_values = new SortedSetEntry[ranks.Count]; var idx = 0; foreach (var rank in ranks) { var value = new SortedSetEntry(rank.Key, rank.Value); redis_values[idx] = value; idx++; } try { result = await onPrepareRequest(); if (result.isFail()) return result; var database = getDatabase(); var transaction = database.CreateTransaction(); transaction.AddCondition(Condition.KeyNotExists(getKey())); _ = transaction.SortedSetAddAsync(getKey(), redis_values, When.Always); var is_success = await transaction.ExecuteAsync(); if (false == is_success) { err_msg = $"failed to sorted set!! : initRankScore - count[{ranks.Count}]"; result.setFail(ServerErrorCode.RedisSortedSetsWriteFailed, err_msg); Log.getLogger().error(result.toBasicString()); } } catch (Exception e) { var error_code = ServerErrorCode.TryCatchException; err_msg = $"Failed to get UgcNpcTotalRankCache from Redis !!! : : errorCode{error_code}, errMsg:{e.Message} - {nameof(setRankScore)}"; result.setFail(error_code, err_msg); Log.getLogger().error(err_msg); } return result; } public async Task initRankScore(string rankKey, long deltaCount) { var result = new Result(); string err_msg; try { result = await onPrepareRequest(); if (result.isFail()) return result; var database = getDatabase(); var redis_value = await database.SortedSetAddAsync(getKey(), rankKey, deltaCount, When.Always); } catch (Exception e) { var error_code = ServerErrorCode.TryCatchException; err_msg = $"Failed to get UgcNpcTotalRankCache from Redis !!! : : errorCode{error_code}, errMsg:{e.Message} - {nameof(setRankScore)}"; result.setFail(error_code, err_msg); Log.getLogger().error(err_msg); } return result; } public async Task setTtl() { var result = new Result(); string err_msg; try { result = await onPrepareRequest(); if (result.isFail()) return result; var database = getDatabase(); var expire_time = new TimeSpan(MetaHelper.GameConfigMeta.NpcRankingRetentionPeriod, 0,0); var redis_value = await database.KeyExpireAsync(getKey(), expire_time); } catch (Exception e) { var error_code = ServerErrorCode.TryCatchException; err_msg = $"Failed to get UgcNpcTotalRankCache from Redis !!! : : errorCode{error_code}, errMsg:{e.Message} - {nameof(setRankScore)}"; result.setFail(error_code, err_msg); Log.getLogger().error(err_msg); } return result; } public async Task setRankScore(string rankKey, long deltaCount) { var result = new Result(); string err_msg; try { result = await onPrepareRequest(); if (result.isFail()) return result; var database = getDatabase(); var redis_value = await database.SortedSetAddAsync(getKey(), rankKey, deltaCount, When.NotExists); if (false == redis_value) { _ = await database.SortedSetIncrementAsync(getKey(), rankKey, deltaCount); } } catch (Exception e) { var error_code = ServerErrorCode.TryCatchException; err_msg = $"Failed to get UgcNpcTotalRankCache from Redis !!! : : errorCode{error_code}, errMsg:{e.Message} - {nameof(setRankScore)}"; result.setFail(error_code, err_msg); Log.getLogger().error(err_msg); } return result; } }