diff --git a/src/CloudGaming/Api/CloudGaming.Api/Controllers/AppController.cs b/src/CloudGaming/Api/CloudGaming.Api/Controllers/AppController.cs
index 3c30d44..9d20e81 100644
--- a/src/CloudGaming/Api/CloudGaming.Api/Controllers/AppController.cs
+++ b/src/CloudGaming/Api/CloudGaming.Api/Controllers/AppController.cs
@@ -27,5 +27,16 @@ public class AppController : CloudGamingControllerBase
return appConfig;
}
+ ///
+ /// 清除本地缓存
+ ///
+ ///
+ [HttpGet]
+ public bool ClearCacheData()
+ {
+ AppConfigBLL appConfigBLL = new AppConfigBLL(ServiceProvider);
+ var appConfig = appConfigBLL.ClearCacheData();
+ return appConfig;
+ }
}
diff --git a/src/CloudGaming/Api/CloudGaming.Api/Controllers/HomeController.cs b/src/CloudGaming/Api/CloudGaming.Api/Controllers/HomeController.cs
index 20935e0..38418a1 100644
--- a/src/CloudGaming/Api/CloudGaming.Api/Controllers/HomeController.cs
+++ b/src/CloudGaming/Api/CloudGaming.Api/Controllers/HomeController.cs
@@ -24,7 +24,7 @@ public class HomeController : CloudGamingControllerBase
///
///
[HttpGet]
- [RedisCache(1, 0, 0)]
+ //[RedisCache(1, 0, 0)]
public async Task> GetHomeInfo()
{
EpgBLL epgBLL = new EpgBLL(ServiceProvider);
diff --git a/src/CloudGaming/Api/CloudGaming.Api/Program.cs b/src/CloudGaming/Api/CloudGaming.Api/Program.cs
index 4c36aad..1c804a0 100644
--- a/src/CloudGaming/Api/CloudGaming.Api/Program.cs
+++ b/src/CloudGaming/Api/CloudGaming.Api/Program.cs
@@ -159,7 +159,7 @@ if (type != null)
builder.Services.AddAutoMapper(mapperDomain);
#endregion
-builder.AddAppConfigClient();
+await builder.AddAppConfigClient();
//添加jwt验证
builder.AddJwtConfig();
#region 添加跨域
diff --git a/src/CloudGaming/Api/CloudGaming.ExtApi/Program.cs b/src/CloudGaming/Api/CloudGaming.ExtApi/Program.cs
index 2843f3c..6167435 100644
--- a/src/CloudGaming/Api/CloudGaming.ExtApi/Program.cs
+++ b/src/CloudGaming/Api/CloudGaming.ExtApi/Program.cs
@@ -104,7 +104,7 @@ builder.Services.AddSwaggerGen(c =>
c.ParameterFilter();
c.RequestBodyFilter();
});
-builder.AddAppConfigClient();
+await builder.AddAppConfigClient();
//添加游戏服务
builder.AddPlayGameServer();
builder.AddMonitorConfig();
diff --git a/src/CloudGaming/Api/CloudGaming.PayApi/Program.cs b/src/CloudGaming/Api/CloudGaming.PayApi/Program.cs
index 41fc814..516290a 100644
--- a/src/CloudGaming/Api/CloudGaming.PayApi/Program.cs
+++ b/src/CloudGaming/Api/CloudGaming.PayApi/Program.cs
@@ -85,7 +85,7 @@ builder.Services.AddSwaggerGen(c =>
c.ParameterFilter();
c.RequestBodyFilter();
});
-builder.AddAppConfigClient();
+await builder.AddAppConfigClient();
var app = builder.Build();
diff --git a/src/CloudGaming/Api/CloudGaming.Web/Program.cs b/src/CloudGaming/Api/CloudGaming.Web/Program.cs
index 7c2bdcf..0ad353c 100644
--- a/src/CloudGaming/Api/CloudGaming.Web/Program.cs
+++ b/src/CloudGaming/Api/CloudGaming.Web/Program.cs
@@ -34,7 +34,7 @@ if (type != null)
builder.Services.AddAutoMapper(mapperDomain);
#endregion
-builder.AddAppConfigClient();
+await builder.AddAppConfigClient();
builder.Services.AddRazorPages();
diff --git a/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppConfigurationExtend.cs b/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppConfigurationExtend.cs
index 32604da..f4bcfe6 100644
--- a/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppConfigurationExtend.cs
+++ b/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppConfigurationExtend.cs
@@ -2,14 +2,18 @@ using AgileConfig.Client;
using CloudGaming.Code.DataAccess;
using CloudGaming.Code.DataAccess.MultiTenantUtil;
+using CloudGaming.Code.Game;
using HuanMeng.DotNetCore.CacheHelper;
using HuanMeng.DotNetCore.Redis;
+using Refit;
+
using StackExchange.Redis;
using System.Collections.Concurrent;
using System.Collections.Frozen;
+using System.Net.Http.Json;
namespace CloudGaming.Code.AppExtend
@@ -34,6 +38,11 @@ namespace CloudGaming.Code.AppExtend
///
public static ConcurrentDictionary AppConfigs { get; set; } = new ConcurrentDictionary();
+ ///
+ /// 多语言配置
+ ///
+ public static ConcurrentDictionary> AppConfigLanguages { get; set; } = new ConcurrentDictionary>();
+
///
/// 获取配置项
///
@@ -103,19 +112,29 @@ namespace CloudGaming.Code.AppExtend
///
///
///
- public static IHostApplicationBuilder AddAppConfigClient(this WebApplicationBuilder builder)
+ public static async Task AddAppConfigClient(this WebApplicationBuilder builder)
{
var configClient = new ConfigClient(builder.Configuration);
builder.Host.UseAgileConfig(configClient, ConfigClient_ConfigChanged);
ConfigurationManager = builder.Configuration;
- AppConfigInit(builder.Configuration);
+ await AppConfigInit(builder.Configuration);
builder.Services.AddScoped();
builder.AddDataBase();
+ builder.AddAppService();
return builder;
}
-
+ ///
+ /// 初始化app服务
+ ///
+ ///
+ ///
+ public static IHostApplicationBuilder AddAppService(this WebApplicationBuilder builder)
+ {
+ builder.Services.AddHostedService();
+ return builder;
+ }
///
/// 获取配置项
@@ -226,6 +245,7 @@ namespace CloudGaming.Code.AppExtend
newAppConfig.GameConfig = appConfig.GameConfig;
newAppConfig.PrivacyAgreement = appConfig.PrivacyAgreement;
newAppConfig.UserAgreement = appConfig.UserAgreement;
+ newAppConfig.LanguageRequestUrl = appConfig.LanguageRequestUrl;
return newAppConfig;
}
@@ -269,7 +289,7 @@ namespace CloudGaming.Code.AppExtend
/// 初始化租户数据
///
///
- private static void AppConfigInit(IConfigurationManager configurationManager)
+ private static async Task AppConfigInit(IConfigurationManager configurationManager)
{
var tenants = configurationManager.GetSection("Tenants").Get>();
if (tenants != null)
@@ -277,18 +297,20 @@ namespace CloudGaming.Code.AppExtend
ConcurrentDictionary _AppConfigs = new ConcurrentDictionary();
if (tenants.Count > 0)
{
- tenants?.ForEach(t =>
+ foreach (var t in tenants)
{
-
if (!_AppConfigs.TryAdd(t.DomainName, t))
{
Console.WriteLine($"{t.DomainName}配置加载失败");
}
+ var list = await GetAppConfigLanguage(t.LanguageRequestUrl);
+ AppConfigLanguages.TryAdd(t.DomainName, list);
if (t.Name == "default")
{
_AppConfigs.TryAdd("default", t);
}
- });
+ }
+
if (!_AppConfigs.TryGetValue("default", out var x))
{
_AppConfigs.TryAdd("default", tenants[0]);
@@ -301,9 +323,59 @@ namespace CloudGaming.Code.AppExtend
AppConfigs = _AppConfigs;
}
}
+
+ ///
+ /// 获取项目的多语言
+ ///
+ ///
+ ///
+ private static async Task> GetAppConfigLanguage(string url)
+ {
+ if (string.IsNullOrEmpty(url))
+ {
+ return new List() { "zh" };
+ }
+ using HttpClient _httpClient = new HttpClient();
+ try
+ {
+ // 发送GET请求到指定的URL
+ var response = await _httpClient.GetFromJsonAsync>>>(url);
+
+ // 检查响应是否为null,以及响应码是否为200
+ if (response != null && response.Code == 200)
+ {
+ if (response.Data != null && response.Data.Count > 0)
+ {
+ var list = response.Data.Select(it => it["value"].ToString() ?? "").ToList();
+ return list;
+
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+
+ }
+ return new List() { "zh" };
+ }
#endregion
-
+ ///
+ /// 获取多语言
+ ///
+ ///
+ ///
+ public static List GetLanguages(this AppConfig appConfig)
+ {
+ if (appConfig != null)
+ {
+ if (AppConfigLanguages.TryGetValue(appConfig.DomainName, out var list))
+ {
+ return list;
+ }
+ }
+ return new List() { "zh" };
+ }
}
}
diff --git a/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppRequestConfig.cs b/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppRequestConfig.cs
index 74451ba..08f3b6a 100644
--- a/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppRequestConfig.cs
+++ b/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppRequestConfig.cs
@@ -11,7 +11,7 @@ namespace CloudGaming.Code.AppExtend
///
/// app 请求信息
///
- public class AppRequestConfig(HttpRequest httpRequest)
+ public class AppRequestConfig(HttpRequest? httpRequest)
{
private string channel { get; set; }
///
@@ -23,7 +23,7 @@ namespace CloudGaming.Code.AppExtend
{
if (string.IsNullOrEmpty(channel))
{
- if (!httpRequest.Headers.TryGetValue("Channel", out var _channel))
+ if (!(httpRequest?.Headers?.TryGetValue("Channel", out var _channel) ?? false))
{
_channel = "27001";
}
@@ -48,7 +48,7 @@ namespace CloudGaming.Code.AppExtend
{
if (string.IsNullOrEmpty(platform))
{
- if (!httpRequest.Headers.TryGetValue("Platform", out var _platform))
+ if (!(httpRequest?.Headers.TryGetValue("Platform", out var _platform) ?? false))
{
_platform = "android";
}
@@ -68,7 +68,7 @@ namespace CloudGaming.Code.AppExtend
{
if (string.IsNullOrEmpty(version))
{
- if (!httpRequest.Headers.TryGetValue("Version", out var _version))
+ if (!(httpRequest?.Headers.TryGetValue("Version", out var _version) ?? false))
{
_version = "1.0.0";
}
@@ -104,7 +104,7 @@ namespace CloudGaming.Code.AppExtend
{
if (string.IsNullOrEmpty(language))
{
- if (!httpRequest.Headers.TryGetValue("Language", out var _language))
+ if (!(httpRequest?.Headers.TryGetValue("Language", out var _language) ?? false))
{
_language = "zh";
}
diff --git a/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppService.cs b/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppService.cs
new file mode 100644
index 0000000..3b084fc
--- /dev/null
+++ b/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppService.cs
@@ -0,0 +1,40 @@
+using CloudGaming.Code.Game;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CloudGaming.Code.AppExtend;
+
+
+public class AppService(IServiceProvider scopeFactory) : IHostedService
+{
+
+ public Task StartAsync(CancellationToken cancellationToken)
+ {
+ var appConfigs = AppConfigurationExtend.AppConfigs.Where(it => it.Key != "default")
+ .Select(it => it.Value)
+ .ToList();
+
+ // 为每个项目启动一个独立的任务
+ foreach (var appConfig in appConfigs)
+ {
+ using var scope = scopeFactory.CreateScope();
+ var scopedProvider = scope.ServiceProvider;
+ var app = scopedProvider.GetRequiredService();
+ appConfig.ToAppConfig(app);
+ CloudGamingBase cloudGamingBase = new CloudGamingBase(scopedProvider);
+ //加载图片缓存
+ cloudGamingBase.Cache.AppImageCache.ReloadData();
+ }
+ return Task.CompletedTask;
+ }
+
+ public Task StopAsync(CancellationToken cancellationToken)
+ {
+
+ return Task.CompletedTask;
+ }
+}
diff --git a/src/CloudGaming/Code/CloudGaming.Code/Cache/CloudGamingCache.cs b/src/CloudGaming/Code/CloudGaming.Code/Cache/CloudGamingCache.cs
index af6c39b..4866a9e 100644
--- a/src/CloudGaming/Code/CloudGaming.Code/Cache/CloudGamingCache.cs
+++ b/src/CloudGaming/Code/CloudGaming.Code/Cache/CloudGamingCache.cs
@@ -1,5 +1,6 @@
using AutoMapper;
+using CloudGaming.Code.AppExtend;
using CloudGaming.Code.Cache.Special;
using CloudGaming.DtoModel;
using CloudGaming.DtoModel.Game;
@@ -8,8 +9,10 @@ using CloudGaming.DtoModel.RedemptionCode;
using CloudGaming.DtoModel.SevenSign;
using HuanMeng.DotNetCore.CacheHelper;
+using HuanMeng.DotNetCore.CacheHelper.Contract;
using System.Collections.Concurrent;
+using System.Globalization;
using System.Linq.Expressions;
namespace CloudGaming.Code.Cache;
@@ -42,25 +45,15 @@ public class CloudGamingCache
#endregion
- #region 图片缓存表
- private CommonDataEntityCache? _appImageCache;
-
- ///
- /// 图片缓存列表
- ///
- public List AppImageList => GetCacheList(ref _appImageCache);
-
- #endregion
#region 配置缓存表
- private CommonDataEntityCache? _appConfigCache;
-
+ private AppConfigEntityCache? _appConfigCache;
///
- /// 配置缓存列表
+ /// 系统配置缓存表
///
- public List AppConfigList
+ public AppConfigEntityCache AppConfigCache
{
get
{
@@ -68,7 +61,17 @@ public class CloudGamingCache
{
_appConfigCache = new AppConfigEntityCache(_gamingBase.Dao, _gamingBase.RedisCache, _gamingBase.Mapper, _gamingBase.AppConfig);
}
- return _appConfigCache.DataList ?? new List();
+ return _appConfigCache;
+ }
+ }
+ ///
+ /// 配置缓存列表
+ ///
+ public List AppConfigList
+ {
+ get
+ {
+ return AppConfigCache.DataList ?? new List();
}
}
@@ -119,20 +122,20 @@ public class CloudGamingCache
///
///
///
- private ImageEntityCache imageEntityCache;
+ private ImageEntityCache appImageCache;
///
/// 图片缓存
///
- public ImageEntityCache ImageEntityCache
+ public ImageEntityCache AppImageCache
{
get
{
- if (imageEntityCache == null)
+ if (appImageCache == null)
{
- imageEntityCache = new ImageEntityCache(_gamingBase.Dao, _gamingBase.AppConfig, _gamingBase.RedisCache, _gamingBase.AppRequestInfo);
+ appImageCache = new ImageEntityCache(_gamingBase.Dao, _gamingBase.AppConfig, _gamingBase.RedisCache, _gamingBase.AppRequestInfo.Language);
}
- return imageEntityCache;
+ return appImageCache;
}
}
#endregion
@@ -164,6 +167,7 @@ public class CloudGamingCache
{
get
{
+
return ProductCacheEntityCache.DataList ?? new List();
}
}
@@ -234,11 +238,8 @@ public class CloudGamingCache
}
#endregion
- #region 首页缓存表
-
- #endregion
}
///
@@ -246,10 +247,10 @@ public class CloudGamingCache
///
public static class CloudGamingCacheExtend
{
- private static readonly ConcurrentDictionary ExtCacheLockList = new ConcurrentDictionary();
- private static readonly ConcurrentDictionary GameCacheLockList = new ConcurrentDictionary();
- private static readonly ConcurrentDictionary AppCacheLockList = new ConcurrentDictionary();
- private static readonly ConcurrentDictionary UserCacheLockList = new ConcurrentDictionary();
+ public static readonly ConcurrentDictionary ExtCacheLockList = new ConcurrentDictionary();
+ public static readonly ConcurrentDictionary GameCacheLockList = new ConcurrentDictionary();
+ public static readonly ConcurrentDictionary AppCacheLockList = new ConcurrentDictionary();
+ public static readonly ConcurrentDictionary UserCacheLockList = new ConcurrentDictionary();
///
/// 命名空间与缓存映射
@@ -267,6 +268,89 @@ public static class CloudGamingCacheExtend
};
}
+ ///
+ /// 清除本地缓存
+ ///
+ ///
+ public static void ClearLocalDataCache(this CloudGamingBase cloudGamingBase)
+ {
+
+ foreach (var item in CloudGamingCacheExtend.ExtCacheLockList)
+ {
+ var c = cloudGamingBase.ToCacheBaseConfig(AppDataBaseType.Ext);
+ var t = item.Key;
+ Type cacheType = typeof(DataBaseEntityCache<>).MakeGenericType(t);
+ var shujuduixiang = Activator.CreateInstance(cacheType, c, item.Value, 36000, null);
+ var x = shujuduixiang as ICacheClearData;
+ if (x != null)
+ {
+ x.ClearData();
+ }
+ }
+
+ foreach (var item in CloudGamingCacheExtend.GameCacheLockList)
+ {
+ var c = cloudGamingBase.ToCacheBaseConfig(AppDataBaseType.Game);
+ var t = item.Key;
+ Type cacheType = typeof(DataBaseEntityCache<>).MakeGenericType(t);
+ var shujuduixiang = Activator.CreateInstance(cacheType, c, item.Value, 36000, null);
+ var x = shujuduixiang as ICacheClearData;
+ if (x != null)
+ {
+ x.ClearData();
+ }
+ }
+
+ foreach (var item in CloudGamingCacheExtend.AppCacheLockList)
+ {
+ var c = cloudGamingBase.ToCacheBaseConfig(AppDataBaseType.App);
+ var t = item.Key;
+ Type cacheType = typeof(DataBaseEntityCache<>).MakeGenericType(t);
+ var shujuduixiang = Activator.CreateInstance(cacheType, c, item.Value, 36000, null);
+ var x = shujuduixiang as ICacheClearData;
+ if (x != null)
+ {
+ x.ClearData();
+ }
+ }
+
+ foreach (var item in CloudGamingCacheExtend.UserCacheLockList)
+ {
+ var c = cloudGamingBase.ToCacheBaseConfig(AppDataBaseType.User);
+ var t = item.Key;
+ Type cacheType = typeof(DataBaseEntityCache<>).MakeGenericType(t);
+ var shujuduixiang = Activator.CreateInstance(cacheType, c, item.Value, 36000);
+ var x = shujuduixiang as ICacheClearData;
+ if (x != null)
+ {
+ x.ClearData();
+ }
+ }
+ cloudGamingBase.Cache.AppConfigCache.ClearLocalData();
+ cloudGamingBase.Cache.ProductCacheEntityCache.ClearLocalData();
+ cloudGamingBase.Cache.AppImageCache.ClearLocalData();
+ cloudGamingBase.Cache.GameEntityCache.ClearLocalData();
+ cloudGamingBase.Cache.RedemptionCodeEntityCache.ClearLocalData();
+ cloudGamingBase.Cache.SevenDayEntityCache.ClearLocalData();
+ }
+
+
+ ///
+ /// 重新加载本地缓存
+ ///
+ ///
+ public static void ReloadLocalDataCache(this CloudGamingBase cloudGamingBase)
+ {
+
+ cloudGamingBase.Cache.AppConfigCache.ReloadData();
+ cloudGamingBase.Cache.ProductCacheEntityCache.ReloadData();
+ cloudGamingBase.Cache.AppImageCache.ReloadData();
+ cloudGamingBase.Cache.GameEntityCache.ReloadData();
+ cloudGamingBase.Cache.RedemptionCodeEntityCache.ReloadData();
+ cloudGamingBase.Cache.SevenDayEntityCache.ReloadData();
+ }
+
+
///
/// 获取实体缓存
///
@@ -284,7 +368,7 @@ public static class CloudGamingCacheExtend
object cacheLock = GetOrAddCacheLock(typeLock, cacheList);
CacheBaseConfig cacheBaseConfig = cloudGamingBase.ToCacheBaseConfig(dbType);
- return new DataBaseEntityCache(cacheBaseConfig, cacheLock, expWhere: expWhere, cacheTime: cacheTime);
+ return new DataBaseEntityCache(cacheBaseConfig, cacheLock, cacheTime, expWhere);
}
///
diff --git a/src/CloudGaming/Code/CloudGaming.Code/Cache/DataBaseEntityCache.cs b/src/CloudGaming/Code/CloudGaming.Code/Cache/DataBaseEntityCache.cs
index 47f494e..9169ab5 100644
--- a/src/CloudGaming/Code/CloudGaming.Code/Cache/DataBaseEntityCache.cs
+++ b/src/CloudGaming/Code/CloudGaming.Code/Cache/DataBaseEntityCache.cs
@@ -7,48 +7,47 @@ using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
-namespace CloudGaming.Code.Cache
+namespace CloudGaming.Code.Cache;
+
+
+///
+///
+///
+///
+///
+///
+///
+///
+public class DataBaseEntityCache(CacheBaseConfig baseConfig, object lockObj, int cacheTime = 36000, Expression> expWhere = null)
+ : CommonDataEntityCache(lockObj, cacheTime) where T : class
{
///
- ///
+ /// 缓存的key
///
- ///
- ///
- ///
- ///
- ///
- public class DataBaseEntityCache(CacheBaseConfig baseConfig, object lockObj, int cacheTime = 36000, Expression> expWhere = null)
- : CommonDataEntityCache(lockObj, cacheTime) where T : class
+ public override string key
{
-
- ///
- /// 缓存的key
- ///
- public override string key
+ get
{
- get
- {
- return $"Cache:{baseConfig.AppConfig.Identifier}:CloudGaming:{typeof(T).Name}";
- }
- }
- ///
- ///
- ///
- ///
- public override List GetDataList()
- {
-
- var dbSet = baseConfig.DbContext.Set().AsNoTracking();
- if (dbSet == null)
- {
- return new List();
- }
- if (expWhere != null)
- {
- dbSet = dbSet.Where(expWhere);
- }
- return dbSet.ToList();
+ return $"Cache:{baseConfig.AppConfig.Identifier}:CloudGaming:{typeof(T).Name}";
}
}
+ ///
+ ///
+ ///
+ ///
+ public override List GetDataList()
+ {
+
+ var dbSet = baseConfig.DbContext.Set().AsNoTracking();
+ if (dbSet == null)
+ {
+ return new List();
+ }
+ if (expWhere != null)
+ {
+ dbSet = dbSet.Where(expWhere);
+ }
+ return dbSet.ToList();
+ }
}
diff --git a/src/CloudGaming/Code/CloudGaming.Code/Cache/Special/GameEntityCache.cs b/src/CloudGaming/Code/CloudGaming.Code/Cache/Special/GameEntityCache.cs
index d2809fa..26f6dc3 100644
--- a/src/CloudGaming/Code/CloudGaming.Code/Cache/Special/GameEntityCache.cs
+++ b/src/CloudGaming/Code/CloudGaming.Code/Cache/Special/GameEntityCache.cs
@@ -9,6 +9,7 @@ using CloudGaming.DtoModel.Game;
using CloudGaming.GameModel.Db.Db_Game;
using HuanMeng.DotNetCore.CacheHelper;
+using HuanMeng.DotNetCore.CacheHelper.Contract;
using HuanMeng.DotNetCore.Redis;
using Newtonsoft.Json;
@@ -25,7 +26,7 @@ namespace CloudGaming.Code.Cache.Special
///
/// 游戏缓存表
///
- public class GameEntityCache(DAO dao, IDatabase database, IMapper mapper, AppConfig appConfig) : CommonDataEntityCache(GameEntityCache.GameEntityCacheLock, 60 * 60 * 24 * 7)
+ public class GameEntityCache(DAO dao, IDatabase database, IMapper mapper, AppConfig appConfig) : CommonDataEntityCache(GameEntityCache.GameEntityCacheLock, 60 * 60 * 24 * 7), ICacheClearLocalData
{
public static object GameEntityCacheLock;
@@ -142,14 +143,7 @@ namespace CloudGaming.Code.Cache.Special
}
}
- //public Task> DataListAsync
- //{
- // get
- // {
- // return new List();
- // }
- //}
private Dictionary gameInfoDic;
///
/// 游戏详情
@@ -224,7 +218,7 @@ namespace CloudGaming.Code.Cache.Special
{
lock (GameEntityCacheLock)
{
- database.KeyDelete(key);
+ database.KeyDelete(RedisKey);
MemoryCacheHelper.DelCache(key);
_dataList = null;
gameInfoDic = null;
@@ -236,11 +230,20 @@ namespace CloudGaming.Code.Cache.Special
{
lock (lockObj)
{
- database.KeyDelete(key);
+ database.KeyDelete(RedisKey);
MemoryCacheHelper.DelCache(key);
_dataList = null;
+ gameInfoDic = null;
var x = DataList;
}
}
+
+ public bool ClearLocalData()
+ {
+ MemoryCacheHelper.DelCache(key);
+ _dataList = null;
+ gameInfoDic = null;
+ return true;
+ }
}
}
diff --git a/src/CloudGaming/Code/CloudGaming.Code/Cache/Special/ImageEntityCache.cs b/src/CloudGaming/Code/CloudGaming.Code/Cache/Special/ImageEntityCache.cs
index e6dc019..68b6050 100644
--- a/src/CloudGaming/Code/CloudGaming.Code/Cache/Special/ImageEntityCache.cs
+++ b/src/CloudGaming/Code/CloudGaming.Code/Cache/Special/ImageEntityCache.cs
@@ -1,210 +1,236 @@
+using Bogus;
+
using CloudGaming.Code.DataAccess;
+using Flurl;
+
using HuanMeng.DotNetCore.CacheHelper;
using HuanMeng.DotNetCore.CacheHelper.Contract;
+using Microsoft.Extensions.Caching.Memory;
+
+using SKIT.FlurlHttpClient.Wechat.TenpayV3.Models;
+
using StackExchange.Redis;
using System.Collections.Concurrent;
+using static SKIT.FlurlHttpClient.Wechat.TenpayV3.ExtendedSDK.Global.Models.QueryPartnerRefundsResponse.Types;
+using static SKIT.FlurlHttpClient.Wechat.TenpayV3.Models.CreateNewTaxControlFapiaoApplicationRequest.Types.Fapiao.Types;
+using static System.Net.Mime.MediaTypeNames;
+
namespace CloudGaming.Code.Cache.Special;
///
-/// 图片缓存表
+/// 图片缓存表
+/// 流程==》
+/// 1.先去本地内存中去找,如果没找打则去找本地缓存默认的图
+/// 2.如果本地默认的也没找到,则去redis中去找,如果redis中没找到当前语言,就去找redis默认的
///
-///
-///
-///
-///
-///
-public class ImageEntityCache(DAO dao, AppConfig appConfig, IDatabase database, AppRequestConfig appRequestConfig) : ICacheClearData, ICacheReloadData
+public class ImageEntityCache : ICacheClearData, ICacheReloadData, ICacheClearLocalData
{
+ private readonly DAO dao;
+ private readonly AppConfig appConfig;
+ private readonly IDatabase database;
///
- /// 是否加载过图片
+ /// 多语言列表
///
- public static bool IsLoadImage { get; set; } = false;
+ private List languages;
+ ///
+ /// 当前多语言
+ ///
+ private string languae;
///
/// 本地内存图片缓存key
///
- private string key = $"{appConfig.Identifier}:App:Image";
- ///
- /// redis图片缓存key
- ///
- private string redisKey = $"App:Image";
- ///
- /// 当前使用的图片key
- ///
- ConcurrentDictionary>? ImageData { get; set; }
+ private readonly string memoryCacheKey;
///
- ///
+ /// Redis图片缓存key
///
- ///
- ///
- public ConcurrentDictionary this[string language]
+ private readonly string redisKey = "cache:Image";
+
+ ///
+ /// 图片缓存数据
+ ///
+ private ConcurrentDictionary imageData;
+
+ public ImageEntityCache(DAO dao, AppConfig appConfig, IDatabase database, string language)
+ {
+ this.dao = dao;
+ this.appConfig = appConfig;
+ this.database = database;
+ this.languae = language;
+ languages = appConfig.GetLanguages();
+ if (!languages.Contains(languae))
+ {
+ languae = appConfig.DefaultLanguage;
+ }
+ if (string.IsNullOrEmpty(languae))
+ {
+ languae = appConfig.DefaultLanguage;
+ }
+ this.memoryCacheKey = $"{appConfig.Identifier}:App:Image:{languae}";
+
+ }
+ ///
+ /// 按语言和图片ID获取图片URL
+ ///
+ public string this[int imageId]
{
get
{
- if (string.IsNullOrEmpty(language))
- {
- language = appRequestConfig.Language;
- }
- if (ImageData != null && ImageData.TryGetValue(language, out var images))
- {
- return images;
- }
- ImageData = MemoryCacheHelper.GetCache>>(key);
- if (ImageData == null)
- {
- ImageData = new ConcurrentDictionary>();
- }
- if (!ImageData.TryGetValue(language, out images))
+ if (imageId == 0) return string.Empty;
+ if (this.imageData == null)
{
- ImageData.TryAdd(language, images = new ConcurrentDictionary());
- //内存中缓存
- MemoryCacheHelper.SetCache(key, ImageData, 60 * 60 * 24);
+ var t = MemoryCacheHelper.GetCache>(memoryCacheKey);
+ if (t == null)
+ {
+ t = new ConcurrentDictionary();
+ MemoryCacheHelper.SetCache(this.memoryCacheKey, t);
+ }
+ this.imageData = t;
}
- return images;
+ var images = this.imageData;
+ if (!images.TryGetValue(imageId, out var imageUrl))
+ {
+ imageUrl = LoadImageFromRedis(this.languae, imageId);
+ if (!string.IsNullOrEmpty(imageUrl))
+ {
+ images[imageId] = imageUrl;
+ }
+ }
+
+ return imageUrl ?? string.Empty;
}
}
- ///
- ///
- ///
- ///
- ///
- ///
- public string this[string language, int imageId]
+
+ private string LoadImageFromRedis(string language, int imageId)
{
- get
+ var redisValue = database.StringGet($"{redisKey}:{language}:{imageId}");
+ if (redisValue.IsNullOrEmpty)
{
- if (imageId == 0)
- {
- return "";
- }
- var _imageData = this[language];
- if (_imageData == null)
- {
- _imageData = new ConcurrentDictionary();
- }
- if (!_imageData.TryGetValue(imageId, out var imageUrl))
- {
- var imageValue = database.StringGet($"{redisKey}:{language}:{imageId}");
- if (imageValue.IsNullOrEmpty)
- {
- imageValue = database.StringGet($"{redisKey}:default:{imageId}");
- }
- if (!IsLoadImage && imageValue.IsNullOrEmpty)
- {
- if (!database.KeyExists(redisKey))
- {
- ImageData = LoadImage(dao, appConfig);
- MemoryCacheHelper.SetCache(key, ImageData, 60 * 60 * 24);
- IsLoadImage = true;
- _imageData = ImageData[language];
- if (!_imageData.TryGetValue(imageId, out imageUrl))
- {
- imageUrl = "";
- }
- return imageUrl;
- }
- }
- imageUrl = imageValue;
- _imageData.TryAdd(imageId, imageUrl);
- }
- return imageUrl;
+ redisValue = database.StringGet($"{redisKey}:default:{imageId}");
}
+ return redisValue;
}
- public ConcurrentDictionary> LoadImage(DAO dao, AppConfig appConfig)
+ private void LoadImagesFromDatabase()
{
- // 初始化_data字典
- ConcurrentDictionary> _data = new ConcurrentDictionary>();
-
- // 获取图像列表
- var imageList = dao.DaoExt.Context.T_App_Image
+ var isadd = database.StringGet>($"{redisKey}:language");
+ if (isadd != null && isadd.Count > 0)
+ {
+ foreach (var _language in isadd)
+ {
+ var mKey = $"{appConfig.Identifier}:App:Image:{_language}";
+ var imageRedis = database.StringGet>($"{redisKey}:language:{_language}");
+ //database.StringGet<>
+ var imagex = new ConcurrentDictionary(imageRedis ?? new Dictionary());
+ MemoryCacheHelper.SetCache(mKey, imagex);
+ }
+ return;
+ }
+ var data = new ConcurrentDictionary>();
+ var images = dao.DaoExt.Context.T_App_Image
.Where(it => !string.IsNullOrEmpty(it.Url))
.AsNoTracking()
.Select(it => new { it.ImageId, it.Language, it.Url })
.ToList();
-
// 设置默认语言
if (string.IsNullOrEmpty(appConfig.DefaultLanguage))
{
appConfig.DefaultLanguage = "zh";
}
-
// 创建默认语言的图像字典
- var defaultImage = imageList
+ var defaultImage = images
.Where(it => it.Language == appConfig.DefaultLanguage)
.GroupBy(it => it.ImageId)
.ToDictionary(group => group.Key, group => appConfig.AliyunConfig.ImagePrefix + group.Last().Url);
-
- // 遍历图像列表,填充_data字典
- foreach (var item in imageList)
+ if (defaultImage == null)
{
- // 尝试获取语言字典,如果不存在则创建
- if (!_data.TryGetValue(item.Language, out var languageImage))
+ defaultImage = new Dictionary();
+ }
+ foreach (var image in images)
+ {
+ if (string.IsNullOrEmpty(image.Url))
{
- languageImage = new ConcurrentDictionary();
- _data[item.Language] = languageImage;
+ continue;
}
-
- // 设置图像URL
- languageImage[item.ImageId] = appConfig.AliyunConfig.ImagePrefix + item.Url;
-
+ var languageCache = data.GetOrAdd(image.Language, _ => new ConcurrentDictionary());
+ var url = string.Empty;
+ if (image.Url.StartsWith("http://") || image.Url.StartsWith("https://"))
+ {
+ url = $"{image.Url}";
+ }
+ else
+ {
+ url = $"{appConfig.AliyunConfig.ImagePrefix}{image.Url}";
+ }
+ languageCache[image.ImageId] = url;
// 如果默认图像字典中没有此ImageId,加入默认图像字典
- if (!defaultImage.ContainsKey(item.ImageId))
+ if (!defaultImage.ContainsKey(image.ImageId))
{
- defaultImage[item.ImageId] = appConfig.AliyunConfig.ImagePrefix + item.Url;
+ defaultImage[image.ImageId] = url;
}
}
-
- // 更新默认语言的图像字典
- _data["default"] = new ConcurrentDictionary(defaultImage);
- foreach (var item in _data.Keys)
+ #region 保存默认图片
+ var defaultLanguageCache = new ConcurrentDictionary(defaultImage);
+ foreach (var kv in defaultLanguageCache)
{
- foreach (var image in _data[item])
+ database.StringSet($"{redisKey}:default:{kv.Key}", kv.Value);
+ }
+ //data.TryAdd("default", defaultLanguageCache);
+ #endregion
+ #region 保存其他图片
+ foreach (var _language in languages)
+ {
+ var mKey = $"{appConfig.Identifier}:App:Image:{_language}";
+ if (!data.TryGetValue(_language, out var d))
{
- string _redisKey = $"{redisKey}:{item}:{image.Key}";
- database.StringSet(_redisKey, image.Value, TimeSpan.FromDays(1));
+ d = defaultLanguageCache;
}
+ foreach (var kv in d)
+ {
+ database.StringSet($"{redisKey}:{_language}:{kv.Key}", kv.Value);
+ }
+ MemoryCacheHelper.SetCache(mKey, d, 60 * 60 * 24);
+ database.StringSet($"{redisKey}:language:{_language}", d);
}
- database.StringSet(redisKey, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromDays(1));
- return _data;
+ database.StringSet($"{redisKey}:language", languages);
+
+ #endregion
+ return;
}
- ///
- /// 读取图片
- ///
- ///
- ///
- public string this[int imageId]
- {
- get
- {
- var imageUrl = this[appRequestConfig.Language, imageId];
- return imageUrl;
- }
- }
- ///
- /// 清除缓存
- ///
- ///
- ///
public bool ClearData()
{
- throw new NotImplementedException();
+
+ foreach (var _language in languages)
+ {
+ var mKey = $"{appConfig.Identifier}:App:Image:{_language}";
+ MemoryCacheHelper.cache.Remove(mKey);
+ }
+
+
+ return true;
}
- ///
- /// 重新加载缓存
- ///
- ///
public void ReloadData()
{
- throw new NotImplementedException();
+ LoadImagesFromDatabase();
+ }
+
+ public bool ClearLocalData()
+ {
+ foreach (var _language in languages)
+ {
+ var mKey = $"{appConfig.Identifier}:App:Image:{_language}";
+ MemoryCacheHelper.cache.Remove(mKey);
+ }
+ imageData = null;
+ return true;
}
}
diff --git a/src/CloudGaming/Code/CloudGaming.Code/Config/AppConfigBLL.cs b/src/CloudGaming/Code/CloudGaming.Code/Config/AppConfigBLL.cs
index 47a6f58..bf135d7 100644
--- a/src/CloudGaming/Code/CloudGaming.Code/Config/AppConfigBLL.cs
+++ b/src/CloudGaming/Code/CloudGaming.Code/Config/AppConfigBLL.cs
@@ -1,3 +1,4 @@
+using CloudGaming.Code.Cache;
using CloudGaming.DtoModel;
using System;
@@ -48,6 +49,24 @@ namespace CloudGaming.Code.Config
return list.GetAppIsChecking(AppRequestInfo);
}
+ ///
+ /// 清除缓存
+ ///
+ ///
+ public bool ClearCacheData()
+ {
+ this.ClearLocalDataCache();
+ return true;
+ }
+ ///
+ /// 加载redis缓存
+ ///
+ ///
+ public bool ReloadLocalData()
+ {
+ this.ReloadLocalDataCache();
+ return true;
+ }
}
}
diff --git a/src/CloudGaming/Code/CloudGaming.Code/Filter/CustomResultFilter.cs b/src/CloudGaming/Code/CloudGaming.Code/Filter/CustomResultFilter.cs
index d115e2a..aa61198 100644
--- a/src/CloudGaming/Code/CloudGaming.Code/Filter/CustomResultFilter.cs
+++ b/src/CloudGaming/Code/CloudGaming.Code/Filter/CustomResultFilter.cs
@@ -88,7 +88,7 @@ public class CustomResultFilter : IResultFilter
}
}
}
- var dic = value.ToDictionaryOrList(apiPrefix, it => cloudGamingBase.Cache.ImageEntityCache[it]);
+ var dic = value.ToDictionaryOrList(apiPrefix, it => cloudGamingBase.Cache.AppImageCache[it]);
objectResult.Value = dic;
}
//else
diff --git a/src/CloudGaming/Code/CloudGaming.Code/Game/PlayGameExtend.cs b/src/CloudGaming/Code/CloudGaming.Code/Game/PlayGameExtend.cs
index b8c954e..9b943ac 100644
--- a/src/CloudGaming/Code/CloudGaming.Code/Game/PlayGameExtend.cs
+++ b/src/CloudGaming/Code/CloudGaming.Code/Game/PlayGameExtend.cs
@@ -21,7 +21,7 @@ namespace CloudGaming.Code.Game
{
///
- /// 初始化app
+ /// 初始化游戏服务
///
///
///
diff --git a/src/CloudGaming/Model/CloudGaming.AppConfigModel/AppConfig.cs b/src/CloudGaming/Model/CloudGaming.AppConfigModel/AppConfig.cs
index 55cd334..98bed38 100644
--- a/src/CloudGaming/Model/CloudGaming.AppConfigModel/AppConfig.cs
+++ b/src/CloudGaming/Model/CloudGaming.AppConfigModel/AppConfig.cs
@@ -85,6 +85,10 @@ namespace CloudGaming.AppConfigModel
///
public string PrivacyAgreement { get; set; }
+ ///
+ /// 多语言列表请求地址
+ ///
+ public string LanguageRequestUrl { get; set; }
///
/// 获取数据库连接字符串
///
diff --git a/src/CloudGaming/Utile/HuanMeng.DotNetCore/CacheHelper/CommonDataEntityCache.cs b/src/CloudGaming/Utile/HuanMeng.DotNetCore/CacheHelper/CommonDataEntityCache.cs
index 00353bd..4a87e45 100644
--- a/src/CloudGaming/Utile/HuanMeng.DotNetCore/CacheHelper/CommonDataEntityCache.cs
+++ b/src/CloudGaming/Utile/HuanMeng.DotNetCore/CacheHelper/CommonDataEntityCache.cs
@@ -105,7 +105,7 @@ public abstract class CommonDataEntityCache : ICacheClearData, ICacheReloadDa
///
/// 缓存扩展-
///
-public abstract class RedisDataEntityCache : CommonDataEntityCache where T : class
+public abstract class RedisDataEntityCache : CommonDataEntityCache, ICacheClearLocalData where T : class
{
public IDatabase database;
///
@@ -160,7 +160,7 @@ public abstract class RedisDataEntityCache : CommonDataEntityCache where T
database.StringSet(key, tempDataList, TimeSpan.FromSeconds(cacheTime));
}
}
- _dataList = JsonConvert.DeserializeObject>(JsonConvert.SerializeObject(tempDataList));
+ //_dataList = JsonConvert.DeserializeObject>(JsonConvert.SerializeObject(tempDataList));
database.KeyDeleteAsync($"lock:{key}").Wait();
}
else
@@ -214,4 +214,10 @@ public abstract class RedisDataEntityCache : CommonDataEntityCache where T
database.KeyDeleteAsync($"lock:{key}").Wait();
}
}
+
+ public bool ClearLocalData()
+ {
+ _dataList = null;
+ return true;
+ }
}
diff --git a/src/CloudGaming/Utile/HuanMeng.DotNetCore/CacheHelper/Contract/ICacheClearData.cs b/src/CloudGaming/Utile/HuanMeng.DotNetCore/CacheHelper/Contract/ICacheClearData.cs
index 9b90538..f7604e7 100644
--- a/src/CloudGaming/Utile/HuanMeng.DotNetCore/CacheHelper/Contract/ICacheClearData.cs
+++ b/src/CloudGaming/Utile/HuanMeng.DotNetCore/CacheHelper/Contract/ICacheClearData.cs
@@ -7,7 +7,7 @@ using System.Threading.Tasks;
namespace HuanMeng.DotNetCore.CacheHelper.Contract
{
///
- /// 清除缓存
+ /// 清除缓存
///
public interface ICacheClearData
{
diff --git a/src/CloudGaming/Utile/HuanMeng.DotNetCore/CacheHelper/Contract/ICacheClearLocalData.cs b/src/CloudGaming/Utile/HuanMeng.DotNetCore/CacheHelper/Contract/ICacheClearLocalData.cs
new file mode 100644
index 0000000..dade31f
--- /dev/null
+++ b/src/CloudGaming/Utile/HuanMeng.DotNetCore/CacheHelper/Contract/ICacheClearLocalData.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HuanMeng.DotNetCore.CacheHelper.Contract;
+
+///
+/// 清除缓存
+///
+public interface ICacheClearLocalData
+{
+ ///
+ /// 清除数据
+ ///
+ ///
+ bool ClearLocalData();
+}