Skip to content

Commit

Permalink
use memory cache instead dictionary
Browse files Browse the repository at this point in the history
  • Loading branch information
Scighost committed Jan 21, 2025
1 parent 5a80a31 commit 80e89f7
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 113 deletions.
42 changes: 29 additions & 13 deletions src/Starward/Features/GameSelector/GameSelector.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
using System.Numerics;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Vanara.PInvoke;
Expand Down Expand Up @@ -75,8 +76,9 @@ public GameSelector()

public void InitializeGameSelector()
{
InitializeGameIconsArea();
InitializeGameServerArea();
List<GameInfo> gameInfos = GetCachedGameInfos();
InitializeGameIconsArea(gameInfos);
InitializeGameServerArea(gameInfos);
InitializeInstalledGamesCommand.Execute(null);
}

Expand Down Expand Up @@ -116,14 +118,30 @@ private async void OnMainWindowStateChanged(object? _, MainWindowStateChangedMes



private List<GameInfo> GetCachedGameInfos()
{
try
{
string? json = AppSetting.CachedGameInfo;
if (!string.IsNullOrWhiteSpace(json))
{
return JsonSerializer.Deserialize<List<GameInfo>>(json) ?? [];
}
}
catch { }
return [];
}




#region Game Icon


/// <summary>
/// 初始化游戏图标区域
/// </summary>
private void InitializeGameIconsArea()
private void InitializeGameIconsArea(List<GameInfo> gameInfos)
{
try
{
Expand All @@ -139,7 +157,7 @@ private void InitializeGameIconsArea()
// 已知的 GameBiz
GameBizIcons.Add(new GameBizIcon(biz));
}
else if (_hoyoplayService.GetCachedGameInfo(biz) is GameInfo info)
else if (gameInfos.FirstOrDefault(x => x.GameBiz == biz) is GameInfo info)
{
// 由 HoYoPlay API 获取,但未适配的 GameBiz
GameBizIcons.Add(new GameBizIcon(info));
Expand All @@ -160,7 +178,7 @@ private void InitializeGameIconsArea()
CurrentGameBizIcon.IsSelected = true;
CurrentGameBiz = lastSelectedGameBiz;
}
else if (_hoyoplayService.GetCachedGameInfo(lastSelectedGameBiz) is GameInfo info)
else if (gameInfos.FirstOrDefault(x => x.GameBiz == lastSelectedGameBiz) is GameInfo info)
{
CurrentGameBizIcon = new GameBizIcon(info);
CurrentGameBizIcon.IsSelected = true;
Expand Down Expand Up @@ -496,17 +514,16 @@ private void Border_FullBackground_Tapped(object sender, Microsoft.UI.Xaml.Input
/// <summary>
/// 初始化游戏服务器选择区域
/// </summary>
private void InitializeGameServerArea()
private void InitializeGameServerArea(List<GameInfo> gameInfos)
{
try
{
var list = new List<GameBizDisplay>();
var infos = _hoyoplayService.GetCachedGameInfoList();

if (LanguageUtil.FilterLanguage(CultureInfo.CurrentUICulture.Name) is "zh-cn")
{
// 当前语言为简体中文时,游戏信息显示从中国官服获取的内容
foreach (var info in infos)
foreach (var info in gameInfos)
{
if (info.GameBiz.IsChinaServer() && !info.IsBilibiliServer())
{
Expand All @@ -517,7 +534,7 @@ private void InitializeGameServerArea()
else
{
// 当前语言不为简体中文时,游戏信息显示从国际服获取的内容
foreach (var info in infos)
foreach (var info in gameInfos)
{
if (info.GameBiz.IsGlobalServer())
{
Expand All @@ -541,7 +558,7 @@ private void InitializeGameServerArea()
};
item.Servers.Add(server);
}
else if (_hoyoplayService.GetCachedGameInfo(biz) is GameInfo info)
else if (gameInfos.FirstOrDefault(x => x.GameBiz == biz) is GameInfo info)
{
var server = new GameBizIcon(info)
{
Expand All @@ -566,9 +583,8 @@ private async Task UpdateGameInfoAsync()
{
try
{
_hoyoplayService.ClearCache();
await _hoyoplayService.UpdateGameInfoListAsync();
InitializeGameServerArea();
List<GameInfo> gameInfos = await _hoyoplayService.UpdateGameInfoListAsync();
InitializeGameServerArea(gameInfos);
foreach (GameBizIcon icon in GameBizIcons)
{
if (icon.GameBiz.IsKnown())
Expand Down
129 changes: 29 additions & 100 deletions src/Starward/Features/HoYoPlay/HoYoPlayService.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using Starward.Core;
using Starward.Core.HoYoPlay;
using Starward.Frameworks;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
Expand All @@ -25,114 +25,44 @@ public class HoYoPlayService

private readonly HttpClient _httpClient;

private readonly System.Timers.Timer _timer;
private readonly IMemoryCache _memoryCache;


public HoYoPlayService(ILogger<HoYoPlayService> logger, HoYoPlayClient client, HttpClient httpClient)
public HoYoPlayService(ILogger<HoYoPlayService> logger, HoYoPlayClient client, HttpClient httpClient, IMemoryCache memoryCache)
{
_logger = logger;
_client = client;
_httpClient = httpClient;
_timer = new System.Timers.Timer
{
AutoReset = true,
Enabled = true,
Interval = TimeSpan.FromMinutes(10).TotalMilliseconds,
};
_timer.Elapsed += (_, _) => ClearCache();
LoadCachedGameInfo();
_memoryCache = memoryCache;
}


private List<GameInfo> _gameInfoList = new();


private ConcurrentDictionary<GameId, GameInfo> _gameInfo = new();


private ConcurrentDictionary<GameId, GameBackgroundInfo> _gameBackground = new();


private ConcurrentDictionary<GameId, GameContent> _gameContent = new();


private ConcurrentDictionary<GameId, GamePackage> _gamePackage = new();


private ConcurrentDictionary<GameId, GameConfig> _gameConfig = new();


private ConcurrentDictionary<GameId, GameChannelSDK> _gameChannelSDK = new();


private void LoadCachedGameInfo()
{
try
{
string? json = AppSetting.CachedGameInfo;
if (!string.IsNullOrWhiteSpace(json))
{
var infos = JsonSerializer.Deserialize<List<GameInfo>>(json);
if (infos is not null)
{
_gameInfoList = infos;
foreach (var item in infos)
{
_gameInfo[item] = item;
}
}
}
}
catch { }
}



public void ClearCache()
{
_gameInfoList.Clear();
_gameInfo.Clear();
_gameBackground.Clear();
_gameContent.Clear();
_gamePackage.Clear();
_gameChannelSDK.Clear();
}



public async Task<GameInfo> GetGameInfoAsync(GameId gameId)
{
if (!_gameInfo.TryGetValue(gameId, out GameInfo? info))
if (!_memoryCache.TryGetValue($"{nameof(GameInfo)}_{gameId.Id}", out GameInfo? info))
{
string lang = CultureInfo.CurrentUICulture.Name;
var list = await _client.GetGameInfoAsync(LauncherId.FromGameId(gameId)!, lang);
foreach (var item in list)
{
_gameInfo[item] = item;
_memoryCache.Set($"{nameof(GameInfo)}_{item.Id}", item, TimeSpan.FromMinutes(10));
}
info = list.First(x => x == gameId);
info = list.FirstOrDefault(x => x == gameId);
}
return info;
}



public GameInfo? GetCachedGameInfo(GameBiz biz)
{
return _gameInfo.Values.FirstOrDefault(x => x.GameBiz == biz);
}



public List<GameInfo> GetCachedGameInfoList()
{
return _gameInfoList;
return info!;
}



public async Task<List<GameInfo>> UpdateGameInfoListAsync(CancellationToken cancellationToken = default)
{
if (_memoryCache is MemoryCache cache)
{
cache.Clear();
}
List<GameInfo> infos = new List<GameInfo>();
string lang = CultureInfo.CurrentUICulture.Name;
if (LanguageUtil.FilterLanguage(lang) is "zh-cn")
Expand All @@ -149,10 +79,9 @@ public async Task<List<GameInfo>> UpdateGameInfoListAsync(CancellationToken canc
{
infos.AddRange(await _client.GetGameInfoAsync(launcherId, lang, cancellationToken));
}
_gameInfoList = infos;
foreach (var item in infos)
{
_gameInfo[item] = item;
_memoryCache.Set($"{nameof(GameInfo)}_{item.Id}", item, TimeSpan.FromMinutes(10));
}
string json = JsonSerializer.Serialize(infos);
AppSetting.CachedGameInfo = json;
Expand Down Expand Up @@ -213,60 +142,60 @@ await Parallel.ForEachAsync(infos, async (info, _) =>

public async Task<GameBackgroundInfo> GetGameBackgroundAsync(GameId gameId)
{
if (!_gameBackground.TryGetValue(gameId, out GameBackgroundInfo? background))
if (!_memoryCache.TryGetValue($"{nameof(GameBackgroundInfo)}_{gameId.Id}", out GameBackgroundInfo? background))
{
string lang = CultureInfo.CurrentUICulture.Name;
var list = await _client.GetGameBackgroundAsync(LauncherId.FromGameId(gameId)!, lang);
foreach (var item in list)
{
_gameBackground[item.GameId] = item;
_memoryCache.Set($"{nameof(GameBackgroundInfo)}_{item.GameId.Id}", item, TimeSpan.FromMinutes(1));
}
background = list.First(x => x.GameId == gameId);
background = list.FirstOrDefault(x => x.GameId == gameId);
}
return background;
return background!;
}



public async Task<GameContent> GetGameContentAsync(GameId gameId)
{
if (!_gameContent.TryGetValue(gameId, out GameContent? content))
if (!_memoryCache.TryGetValue($"{nameof(GameContent)}_{gameId.Id}", out GameContent? content))
{
string lang = CultureInfo.CurrentUICulture.Name;
content = await _client.GetGameContentAsync(LauncherId.FromGameId(gameId)!, lang, gameId);
_gameContent[gameId] = content;
_memoryCache.Set($"{nameof(GameContent)}_{content.GameId.Id}", content, TimeSpan.FromMinutes(1));
}
return content;
return content!;
}



public async Task<GamePackage> GetGamePackageAsync(GameId gameId)
{
if (!_gamePackage.TryGetValue(gameId, out GamePackage? package))
if (!_memoryCache.TryGetValue($"{nameof(GamePackage)}_{gameId.Id}", out GamePackage? package))
{
string lang = CultureInfo.CurrentUICulture.Name;
var list = await _client.GetGamePackageAsync(LauncherId.FromGameId(gameId)!, lang);
foreach (var item in list)
{
_gamePackage[item.GameId] = item;
_memoryCache.Set($"{nameof(GamePackage)}_{item.GameId.Id}", item, TimeSpan.FromMinutes(1));
}
package = list.First(x => x.GameId == gameId);
package = list.FirstOrDefault(x => x.GameId == gameId);
}
return package;
return package!;
}



public async Task<GameConfig?> GetGameConfigAsync(GameId gameId)
{
if (!_gameConfig.TryGetValue(gameId, out GameConfig? config))
if (!_memoryCache.TryGetValue($"{nameof(GameConfig)}_{gameId.Id}", out GameConfig? config))
{
string lang = CultureInfo.CurrentUICulture.Name;
var list = await _client.GetGameConfigAsync(LauncherId.FromGameId(gameId)!, lang);
foreach (var item in list)
{
_gameConfig[item.GameId] = item;
_memoryCache.Set($"{nameof(GameConfig)}_{item.GameId.Id}", item, TimeSpan.FromMinutes(1));
}
config = list.FirstOrDefault(x => x.GameId == gameId);
}
Expand All @@ -293,13 +222,13 @@ public async Task<List<GameDeprecatedFile>> GetGameDeprecatedFilesAsync(GameId g

public async Task<GameChannelSDK?> GetGameChannelSDKAsync(GameId gameId)
{
if (!_gameChannelSDK.TryGetValue(gameId, out GameChannelSDK? sdk))
if (!_memoryCache.TryGetValue($"{nameof(GameChannelSDK)}_{gameId.Id}", out GameChannelSDK? sdk))
{
string lang = CultureInfo.CurrentUICulture.Name;
var list = await _client.GetGameChannelSDKAsync(LauncherId.FromGameId(gameId)!, lang);
foreach (var item in list)
{
_gameChannelSDK[item.GameId] = item;
_memoryCache.Set($"{nameof(GameChannelSDK)}_{item.GameId.Id}", item, TimeSpan.FromMinutes(1));
}
sdk = list.FirstOrDefault(x => x.GameId == gameId);
}
Expand Down
1 change: 1 addition & 0 deletions src/Starward/Frameworks/AppService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ private static void BuildServiceProvider()
Log.Information($"Welcome to Starward v{AppSetting.AppVersion}\r\nSystem: {Environment.OSVersion}\r\nCommand Line: {Environment.CommandLine}");

var sc = new ServiceCollection();
sc.AddMemoryCache();
sc.AddLogging(c => c.AddSerilog(Log.Logger));
sc.AddHttpClient().ConfigureHttpClientDefaults(config =>
{
Expand Down
1 change: 1 addition & 0 deletions src/Starward/Starward.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
<PackageReference Include="Dapper" Version="2.1.35" />
<PackageReference Include="H.NotifyIcon.WinUI" Version="2.2.0" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.1" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="9.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="9.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="9.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Ini" Version="9.0.1" />
Expand Down

0 comments on commit 80e89f7

Please sign in to comment.