添加清除缓存
This commit is contained in:
parent
d16a678b8b
commit
898153e42f
|
|
@ -27,5 +27,16 @@ public class AppController : CloudGamingControllerBase
|
||||||
return appConfig;
|
return appConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 清除本地缓存
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpGet]
|
||||||
|
public bool ClearCacheData()
|
||||||
|
{
|
||||||
|
AppConfigBLL appConfigBLL = new AppConfigBLL(ServiceProvider);
|
||||||
|
var appConfig = appConfigBLL.ClearCacheData();
|
||||||
|
return appConfig;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ public class HomeController : CloudGamingControllerBase
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[RedisCache(1, 0, 0)]
|
//[RedisCache(1, 0, 0)]
|
||||||
public async Task<List<EpgCategoryDto>> GetHomeInfo()
|
public async Task<List<EpgCategoryDto>> GetHomeInfo()
|
||||||
{
|
{
|
||||||
EpgBLL epgBLL = new EpgBLL(ServiceProvider);
|
EpgBLL epgBLL = new EpgBLL(ServiceProvider);
|
||||||
|
|
|
||||||
|
|
@ -159,7 +159,7 @@ if (type != null)
|
||||||
builder.Services.AddAutoMapper(mapperDomain);
|
builder.Services.AddAutoMapper(mapperDomain);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
builder.AddAppConfigClient();
|
await builder.AddAppConfigClient();
|
||||||
//添加jwt验证
|
//添加jwt验证
|
||||||
builder.AddJwtConfig();
|
builder.AddJwtConfig();
|
||||||
#region 添加跨域
|
#region 添加跨域
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@ builder.Services.AddSwaggerGen(c =>
|
||||||
c.ParameterFilter<LowercaseParameterFilter>();
|
c.ParameterFilter<LowercaseParameterFilter>();
|
||||||
c.RequestBodyFilter<LowercaseRequestFilter>();
|
c.RequestBodyFilter<LowercaseRequestFilter>();
|
||||||
});
|
});
|
||||||
builder.AddAppConfigClient();
|
await builder.AddAppConfigClient();
|
||||||
//添加游戏服务
|
//添加游戏服务
|
||||||
builder.AddPlayGameServer();
|
builder.AddPlayGameServer();
|
||||||
builder.AddMonitorConfig();
|
builder.AddMonitorConfig();
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,7 @@ builder.Services.AddSwaggerGen(c =>
|
||||||
c.ParameterFilter<LowercaseParameterFilter>();
|
c.ParameterFilter<LowercaseParameterFilter>();
|
||||||
c.RequestBodyFilter<LowercaseRequestFilter>();
|
c.RequestBodyFilter<LowercaseRequestFilter>();
|
||||||
});
|
});
|
||||||
builder.AddAppConfigClient();
|
await builder.AddAppConfigClient();
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ if (type != null)
|
||||||
builder.Services.AddAutoMapper(mapperDomain);
|
builder.Services.AddAutoMapper(mapperDomain);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
builder.AddAppConfigClient();
|
await builder.AddAppConfigClient();
|
||||||
|
|
||||||
builder.Services.AddRazorPages();
|
builder.Services.AddRazorPages();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,18 @@ using AgileConfig.Client;
|
||||||
|
|
||||||
using CloudGaming.Code.DataAccess;
|
using CloudGaming.Code.DataAccess;
|
||||||
using CloudGaming.Code.DataAccess.MultiTenantUtil;
|
using CloudGaming.Code.DataAccess.MultiTenantUtil;
|
||||||
|
using CloudGaming.Code.Game;
|
||||||
|
|
||||||
using HuanMeng.DotNetCore.CacheHelper;
|
using HuanMeng.DotNetCore.CacheHelper;
|
||||||
using HuanMeng.DotNetCore.Redis;
|
using HuanMeng.DotNetCore.Redis;
|
||||||
|
|
||||||
|
using Refit;
|
||||||
|
|
||||||
using StackExchange.Redis;
|
using StackExchange.Redis;
|
||||||
|
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Frozen;
|
using System.Collections.Frozen;
|
||||||
|
using System.Net.Http.Json;
|
||||||
|
|
||||||
|
|
||||||
namespace CloudGaming.Code.AppExtend
|
namespace CloudGaming.Code.AppExtend
|
||||||
|
|
@ -34,6 +38,11 @@ namespace CloudGaming.Code.AppExtend
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static ConcurrentDictionary<string, AppConfig> AppConfigs { get; set; } = new ConcurrentDictionary<string, AppConfig>();
|
public static ConcurrentDictionary<string, AppConfig> AppConfigs { get; set; } = new ConcurrentDictionary<string, AppConfig>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 多语言配置
|
||||||
|
/// </summary>
|
||||||
|
public static ConcurrentDictionary<string, List<string>> AppConfigLanguages { get; set; } = new ConcurrentDictionary<string, List<string>>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取配置项
|
/// 获取配置项
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -103,19 +112,29 @@ namespace CloudGaming.Code.AppExtend
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="builder"></param>
|
/// <param name="builder"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static IHostApplicationBuilder AddAppConfigClient(this WebApplicationBuilder builder)
|
public static async Task<IHostApplicationBuilder> AddAppConfigClient(this WebApplicationBuilder builder)
|
||||||
{
|
{
|
||||||
|
|
||||||
var configClient = new ConfigClient(builder.Configuration);
|
var configClient = new ConfigClient(builder.Configuration);
|
||||||
builder.Host.UseAgileConfig(configClient, ConfigClient_ConfigChanged);
|
builder.Host.UseAgileConfig(configClient, ConfigClient_ConfigChanged);
|
||||||
ConfigurationManager = builder.Configuration;
|
ConfigurationManager = builder.Configuration;
|
||||||
AppConfigInit(builder.Configuration);
|
await AppConfigInit(builder.Configuration);
|
||||||
builder.Services.AddScoped<AppConfig>();
|
builder.Services.AddScoped<AppConfig>();
|
||||||
builder.AddDataBase();
|
builder.AddDataBase();
|
||||||
|
builder.AddAppService();
|
||||||
return builder;
|
return builder;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化app服务
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="builder"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IHostApplicationBuilder AddAppService(this WebApplicationBuilder builder)
|
||||||
|
{
|
||||||
|
builder.Services.AddHostedService<AppService>();
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取配置项
|
/// 获取配置项
|
||||||
|
|
@ -226,6 +245,7 @@ namespace CloudGaming.Code.AppExtend
|
||||||
newAppConfig.GameConfig = appConfig.GameConfig;
|
newAppConfig.GameConfig = appConfig.GameConfig;
|
||||||
newAppConfig.PrivacyAgreement = appConfig.PrivacyAgreement;
|
newAppConfig.PrivacyAgreement = appConfig.PrivacyAgreement;
|
||||||
newAppConfig.UserAgreement = appConfig.UserAgreement;
|
newAppConfig.UserAgreement = appConfig.UserAgreement;
|
||||||
|
newAppConfig.LanguageRequestUrl = appConfig.LanguageRequestUrl;
|
||||||
return newAppConfig;
|
return newAppConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -269,7 +289,7 @@ namespace CloudGaming.Code.AppExtend
|
||||||
/// 初始化租户数据
|
/// 初始化租户数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="configurationManager"></param>
|
/// <param name="configurationManager"></param>
|
||||||
private static void AppConfigInit(IConfigurationManager configurationManager)
|
private static async Task AppConfigInit(IConfigurationManager configurationManager)
|
||||||
{
|
{
|
||||||
var tenants = configurationManager.GetSection("Tenants").Get<List<AppConfig>>();
|
var tenants = configurationManager.GetSection("Tenants").Get<List<AppConfig>>();
|
||||||
if (tenants != null)
|
if (tenants != null)
|
||||||
|
|
@ -277,18 +297,20 @@ namespace CloudGaming.Code.AppExtend
|
||||||
ConcurrentDictionary<string, AppConfig> _AppConfigs = new ConcurrentDictionary<string, AppConfig>();
|
ConcurrentDictionary<string, AppConfig> _AppConfigs = new ConcurrentDictionary<string, AppConfig>();
|
||||||
if (tenants.Count > 0)
|
if (tenants.Count > 0)
|
||||||
{
|
{
|
||||||
tenants?.ForEach(t =>
|
foreach (var t in tenants)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!_AppConfigs.TryAdd(t.DomainName, t))
|
if (!_AppConfigs.TryAdd(t.DomainName, t))
|
||||||
{
|
{
|
||||||
Console.WriteLine($"{t.DomainName}配置加载失败");
|
Console.WriteLine($"{t.DomainName}配置加载失败");
|
||||||
}
|
}
|
||||||
|
var list = await GetAppConfigLanguage(t.LanguageRequestUrl);
|
||||||
|
AppConfigLanguages.TryAdd(t.DomainName, list);
|
||||||
if (t.Name == "default")
|
if (t.Name == "default")
|
||||||
{
|
{
|
||||||
_AppConfigs.TryAdd("default", t);
|
_AppConfigs.TryAdd("default", t);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
if (!_AppConfigs.TryGetValue("default", out var x))
|
if (!_AppConfigs.TryGetValue("default", out var x))
|
||||||
{
|
{
|
||||||
_AppConfigs.TryAdd("default", tenants[0]);
|
_AppConfigs.TryAdd("default", tenants[0]);
|
||||||
|
|
@ -301,9 +323,59 @@ namespace CloudGaming.Code.AppExtend
|
||||||
AppConfigs = _AppConfigs;
|
AppConfigs = _AppConfigs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取项目的多语言
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="url"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static async Task<List<string>> GetAppConfigLanguage(string url)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(url))
|
||||||
|
{
|
||||||
|
return new List<string>() { "zh" };
|
||||||
|
}
|
||||||
|
using HttpClient _httpClient = new HttpClient();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 发送GET请求到指定的URL
|
||||||
|
var response = await _httpClient.GetFromJsonAsync<BaseResponse<List<Dictionary<string, object>>>>(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<string>() { "zh" };
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取多语言
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="appConfig"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static List<string> GetLanguages(this AppConfig appConfig)
|
||||||
|
{
|
||||||
|
if (appConfig != null)
|
||||||
|
{
|
||||||
|
if (AppConfigLanguages.TryGetValue(appConfig.DomainName, out var list))
|
||||||
|
{
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new List<string>() { "zh" };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ namespace CloudGaming.Code.AppExtend
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// app 请求信息
|
/// app 请求信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AppRequestConfig(HttpRequest httpRequest)
|
public class AppRequestConfig(HttpRequest? httpRequest)
|
||||||
{
|
{
|
||||||
private string channel { get; set; }
|
private string channel { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -23,7 +23,7 @@ namespace CloudGaming.Code.AppExtend
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(channel))
|
if (string.IsNullOrEmpty(channel))
|
||||||
{
|
{
|
||||||
if (!httpRequest.Headers.TryGetValue("Channel", out var _channel))
|
if (!(httpRequest?.Headers?.TryGetValue("Channel", out var _channel) ?? false))
|
||||||
{
|
{
|
||||||
_channel = "27001";
|
_channel = "27001";
|
||||||
}
|
}
|
||||||
|
|
@ -48,7 +48,7 @@ namespace CloudGaming.Code.AppExtend
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(platform))
|
if (string.IsNullOrEmpty(platform))
|
||||||
{
|
{
|
||||||
if (!httpRequest.Headers.TryGetValue("Platform", out var _platform))
|
if (!(httpRequest?.Headers.TryGetValue("Platform", out var _platform) ?? false))
|
||||||
{
|
{
|
||||||
_platform = "android";
|
_platform = "android";
|
||||||
}
|
}
|
||||||
|
|
@ -68,7 +68,7 @@ namespace CloudGaming.Code.AppExtend
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(version))
|
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";
|
_version = "1.0.0";
|
||||||
}
|
}
|
||||||
|
|
@ -104,7 +104,7 @@ namespace CloudGaming.Code.AppExtend
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(language))
|
if (string.IsNullOrEmpty(language))
|
||||||
{
|
{
|
||||||
if (!httpRequest.Headers.TryGetValue("Language", out var _language))
|
if (!(httpRequest?.Headers.TryGetValue("Language", out var _language) ?? false))
|
||||||
{
|
{
|
||||||
_language = "zh";
|
_language = "zh";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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>();
|
||||||
|
appConfig.ToAppConfig(app);
|
||||||
|
CloudGamingBase cloudGamingBase = new CloudGamingBase(scopedProvider);
|
||||||
|
//加载图片缓存
|
||||||
|
cloudGamingBase.Cache.AppImageCache.ReloadData();
|
||||||
|
}
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task StopAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
|
|
||||||
|
using CloudGaming.Code.AppExtend;
|
||||||
using CloudGaming.Code.Cache.Special;
|
using CloudGaming.Code.Cache.Special;
|
||||||
using CloudGaming.DtoModel;
|
using CloudGaming.DtoModel;
|
||||||
using CloudGaming.DtoModel.Game;
|
using CloudGaming.DtoModel.Game;
|
||||||
|
|
@ -8,8 +9,10 @@ using CloudGaming.DtoModel.RedemptionCode;
|
||||||
using CloudGaming.DtoModel.SevenSign;
|
using CloudGaming.DtoModel.SevenSign;
|
||||||
|
|
||||||
using HuanMeng.DotNetCore.CacheHelper;
|
using HuanMeng.DotNetCore.CacheHelper;
|
||||||
|
using HuanMeng.DotNetCore.CacheHelper.Contract;
|
||||||
|
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
using System.Globalization;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
|
|
||||||
namespace CloudGaming.Code.Cache;
|
namespace CloudGaming.Code.Cache;
|
||||||
|
|
@ -42,25 +45,15 @@ public class CloudGamingCache
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 图片缓存表
|
|
||||||
|
|
||||||
private CommonDataEntityCache<T_App_Image>? _appImageCache;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 图片缓存列表
|
|
||||||
/// </summary>
|
|
||||||
public List<T_App_Image> AppImageList => GetCacheList(ref _appImageCache);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 配置缓存表
|
#region 配置缓存表
|
||||||
|
|
||||||
private CommonDataEntityCache<AppConfigCache>? _appConfigCache;
|
private AppConfigEntityCache? _appConfigCache;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 配置缓存列表
|
/// 系统配置缓存表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<AppConfigCache> AppConfigList
|
public AppConfigEntityCache AppConfigCache
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
|
@ -68,7 +61,17 @@ public class CloudGamingCache
|
||||||
{
|
{
|
||||||
_appConfigCache = new AppConfigEntityCache(_gamingBase.Dao, _gamingBase.RedisCache, _gamingBase.Mapper, _gamingBase.AppConfig);
|
_appConfigCache = new AppConfigEntityCache(_gamingBase.Dao, _gamingBase.RedisCache, _gamingBase.Mapper, _gamingBase.AppConfig);
|
||||||
}
|
}
|
||||||
return _appConfigCache.DataList ?? new List<AppConfigCache>();
|
return _appConfigCache;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 配置缓存列表
|
||||||
|
/// </summary>
|
||||||
|
public List<AppConfigCache> AppConfigList
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return AppConfigCache.DataList ?? new List<AppConfigCache>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -119,20 +122,20 @@ public class CloudGamingCache
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private ImageEntityCache imageEntityCache;
|
private ImageEntityCache appImageCache;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 图片缓存
|
/// 图片缓存
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ImageEntityCache ImageEntityCache
|
public ImageEntityCache AppImageCache
|
||||||
{
|
{
|
||||||
get
|
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
|
#endregion
|
||||||
|
|
@ -164,6 +167,7 @@ public class CloudGamingCache
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
|
||||||
return ProductCacheEntityCache.DataList ?? new List<ProductCache>();
|
return ProductCacheEntityCache.DataList ?? new List<ProductCache>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -234,11 +238,8 @@ public class CloudGamingCache
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 首页缓存表
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -246,10 +247,10 @@ public class CloudGamingCache
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class CloudGamingCacheExtend
|
public static class CloudGamingCacheExtend
|
||||||
{
|
{
|
||||||
private static readonly ConcurrentDictionary<Type, object> ExtCacheLockList = new ConcurrentDictionary<Type, object>();
|
public static readonly ConcurrentDictionary<Type, object> ExtCacheLockList = new ConcurrentDictionary<Type, object>();
|
||||||
private static readonly ConcurrentDictionary<Type, object> GameCacheLockList = new ConcurrentDictionary<Type, object>();
|
public static readonly ConcurrentDictionary<Type, object> GameCacheLockList = new ConcurrentDictionary<Type, object>();
|
||||||
private static readonly ConcurrentDictionary<Type, object> AppCacheLockList = new ConcurrentDictionary<Type, object>();
|
public static readonly ConcurrentDictionary<Type, object> AppCacheLockList = new ConcurrentDictionary<Type, object>();
|
||||||
private static readonly ConcurrentDictionary<Type, object> UserCacheLockList = new ConcurrentDictionary<Type, object>();
|
public static readonly ConcurrentDictionary<Type, object> UserCacheLockList = new ConcurrentDictionary<Type, object>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 命名空间与缓存映射
|
/// 命名空间与缓存映射
|
||||||
|
|
@ -267,6 +268,89 @@ public static class CloudGamingCacheExtend
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 清除本地缓存
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cloudGamingBase"></param>
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 重新加载本地缓存
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cloudGamingBase"></param>
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取实体缓存
|
/// 获取实体缓存
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -284,7 +368,7 @@ public static class CloudGamingCacheExtend
|
||||||
object cacheLock = GetOrAddCacheLock(typeLock, cacheList);
|
object cacheLock = GetOrAddCacheLock(typeLock, cacheList);
|
||||||
CacheBaseConfig cacheBaseConfig = cloudGamingBase.ToCacheBaseConfig(dbType);
|
CacheBaseConfig cacheBaseConfig = cloudGamingBase.ToCacheBaseConfig(dbType);
|
||||||
|
|
||||||
return new DataBaseEntityCache<T>(cacheBaseConfig, cacheLock, expWhere: expWhere, cacheTime: cacheTime);
|
return new DataBaseEntityCache<T>(cacheBaseConfig, cacheLock, cacheTime, expWhere);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -7,48 +7,47 @@ using System.Linq.Expressions;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace CloudGaming.Code.Cache
|
namespace CloudGaming.Code.Cache;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="baseConfig"></param>
|
||||||
|
/// <param name="lockObj"></param>
|
||||||
|
/// <param name="cacheTime"></param>
|
||||||
|
/// <param name="expWhere"></param>
|
||||||
|
public class DataBaseEntityCache<T>(CacheBaseConfig baseConfig, object lockObj, int cacheTime = 36000, Expression<Func<T, bool>> expWhere = null)
|
||||||
|
: CommonDataEntityCache<T>(lockObj, cacheTime) where T : class
|
||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
/// 缓存的key
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T"></typeparam>
|
public override string key
|
||||||
/// <param name="baseConfig"></param>
|
|
||||||
/// <param name="lockObj"></param>
|
|
||||||
/// <param name="cacheTime"></param>
|
|
||||||
/// <param name="expWhere"></param>
|
|
||||||
public class DataBaseEntityCache<T>(CacheBaseConfig baseConfig, object lockObj, int cacheTime = 36000, Expression<Func<T, bool>> expWhere = null)
|
|
||||||
: CommonDataEntityCache<T>(lockObj, cacheTime) where T : class
|
|
||||||
{
|
{
|
||||||
|
get
|
||||||
/// <summary>
|
|
||||||
/// 缓存的key
|
|
||||||
/// </summary>
|
|
||||||
public override string key
|
|
||||||
{
|
{
|
||||||
get
|
return $"Cache:{baseConfig.AppConfig.Identifier}:CloudGaming:{typeof(T).Name}";
|
||||||
{
|
|
||||||
return $"Cache:{baseConfig.AppConfig.Identifier}:CloudGaming:{typeof(T).Name}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public override List<T> GetDataList()
|
|
||||||
{
|
|
||||||
|
|
||||||
var dbSet = baseConfig.DbContext.Set<T>().AsNoTracking();
|
|
||||||
if (dbSet == null)
|
|
||||||
{
|
|
||||||
return new List<T>();
|
|
||||||
}
|
|
||||||
if (expWhere != null)
|
|
||||||
{
|
|
||||||
dbSet = dbSet.Where(expWhere);
|
|
||||||
}
|
|
||||||
return dbSet.ToList();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override List<T> GetDataList()
|
||||||
|
{
|
||||||
|
|
||||||
|
var dbSet = baseConfig.DbContext.Set<T>().AsNoTracking();
|
||||||
|
if (dbSet == null)
|
||||||
|
{
|
||||||
|
return new List<T>();
|
||||||
|
}
|
||||||
|
if (expWhere != null)
|
||||||
|
{
|
||||||
|
dbSet = dbSet.Where(expWhere);
|
||||||
|
}
|
||||||
|
return dbSet.ToList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ using CloudGaming.DtoModel.Game;
|
||||||
using CloudGaming.GameModel.Db.Db_Game;
|
using CloudGaming.GameModel.Db.Db_Game;
|
||||||
|
|
||||||
using HuanMeng.DotNetCore.CacheHelper;
|
using HuanMeng.DotNetCore.CacheHelper;
|
||||||
|
using HuanMeng.DotNetCore.CacheHelper.Contract;
|
||||||
using HuanMeng.DotNetCore.Redis;
|
using HuanMeng.DotNetCore.Redis;
|
||||||
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
@ -25,7 +26,7 @@ namespace CloudGaming.Code.Cache.Special
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 游戏缓存表
|
/// 游戏缓存表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class GameEntityCache(DAO dao, IDatabase database, IMapper mapper, AppConfig appConfig) : CommonDataEntityCache<GameInfo>(GameEntityCache.GameEntityCacheLock, 60 * 60 * 24 * 7)
|
public class GameEntityCache(DAO dao, IDatabase database, IMapper mapper, AppConfig appConfig) : CommonDataEntityCache<GameInfo>(GameEntityCache.GameEntityCacheLock, 60 * 60 * 24 * 7), ICacheClearLocalData
|
||||||
{
|
{
|
||||||
public static object GameEntityCacheLock;
|
public static object GameEntityCacheLock;
|
||||||
|
|
||||||
|
|
@ -142,14 +143,7 @@ namespace CloudGaming.Code.Cache.Special
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//public Task<List<GameInfo>> DataListAsync
|
|
||||||
//{
|
|
||||||
// get
|
|
||||||
// {
|
|
||||||
|
|
||||||
// return new List<GameInfo>();
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
private Dictionary<string, GameInfo> gameInfoDic;
|
private Dictionary<string, GameInfo> gameInfoDic;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 游戏详情
|
/// 游戏详情
|
||||||
|
|
@ -224,7 +218,7 @@ namespace CloudGaming.Code.Cache.Special
|
||||||
{
|
{
|
||||||
lock (GameEntityCacheLock)
|
lock (GameEntityCacheLock)
|
||||||
{
|
{
|
||||||
database.KeyDelete(key);
|
database.KeyDelete(RedisKey);
|
||||||
MemoryCacheHelper.DelCache(key);
|
MemoryCacheHelper.DelCache(key);
|
||||||
_dataList = null;
|
_dataList = null;
|
||||||
gameInfoDic = null;
|
gameInfoDic = null;
|
||||||
|
|
@ -236,11 +230,20 @@ namespace CloudGaming.Code.Cache.Special
|
||||||
{
|
{
|
||||||
lock (lockObj)
|
lock (lockObj)
|
||||||
{
|
{
|
||||||
database.KeyDelete(key);
|
database.KeyDelete(RedisKey);
|
||||||
MemoryCacheHelper.DelCache(key);
|
MemoryCacheHelper.DelCache(key);
|
||||||
_dataList = null;
|
_dataList = null;
|
||||||
|
gameInfoDic = null;
|
||||||
var x = DataList;
|
var x = DataList;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool ClearLocalData()
|
||||||
|
{
|
||||||
|
MemoryCacheHelper.DelCache(key);
|
||||||
|
_dataList = null;
|
||||||
|
gameInfoDic = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,210 +1,236 @@
|
||||||
|
using Bogus;
|
||||||
|
|
||||||
using CloudGaming.Code.DataAccess;
|
using CloudGaming.Code.DataAccess;
|
||||||
|
|
||||||
|
using Flurl;
|
||||||
|
|
||||||
using HuanMeng.DotNetCore.CacheHelper;
|
using HuanMeng.DotNetCore.CacheHelper;
|
||||||
using HuanMeng.DotNetCore.CacheHelper.Contract;
|
using HuanMeng.DotNetCore.CacheHelper.Contract;
|
||||||
|
|
||||||
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
|
|
||||||
|
using SKIT.FlurlHttpClient.Wechat.TenpayV3.Models;
|
||||||
|
|
||||||
using StackExchange.Redis;
|
using StackExchange.Redis;
|
||||||
|
|
||||||
using System.Collections.Concurrent;
|
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;
|
namespace CloudGaming.Code.Cache.Special;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 图片缓存表
|
/// 图片缓存表
|
||||||
|
/// 流程==》
|
||||||
|
/// 1.先去本地内存中去找,如果没找打则去找本地缓存默认的图
|
||||||
|
/// 2.如果本地默认的也没找到,则去redis中去找,如果redis中没找到当前语言,就去找redis默认的
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dao"></param>
|
public class ImageEntityCache : ICacheClearData, ICacheReloadData, ICacheClearLocalData
|
||||||
/// <param name="appConfig"></param>
|
|
||||||
/// <param name="database"></param>
|
|
||||||
/// <param name="mapper"></param>
|
|
||||||
/// <param name="appRequestConfig"></param>
|
|
||||||
public class ImageEntityCache(DAO dao, AppConfig appConfig, IDatabase database, AppRequestConfig appRequestConfig) : ICacheClearData, ICacheReloadData
|
|
||||||
{
|
{
|
||||||
|
private readonly DAO dao;
|
||||||
|
private readonly AppConfig appConfig;
|
||||||
|
private readonly IDatabase database;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否加载过图片
|
/// 多语言列表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static bool IsLoadImage { get; set; } = false;
|
private List<string> languages;
|
||||||
|
/// <summary>
|
||||||
|
/// 当前多语言
|
||||||
|
/// </summary>
|
||||||
|
private string languae;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 本地内存图片缓存key
|
/// 本地内存图片缓存key
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private string key = $"{appConfig.Identifier}:App:Image";
|
private readonly string memoryCacheKey;
|
||||||
/// <summary>
|
|
||||||
/// redis图片缓存key
|
|
||||||
/// </summary>
|
|
||||||
private string redisKey = $"App:Image";
|
|
||||||
/// <summary>
|
|
||||||
/// 当前使用的图片key
|
|
||||||
/// </summary>
|
|
||||||
ConcurrentDictionary<string, ConcurrentDictionary<int, string>>? ImageData { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
/// Redis图片缓存key
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="language"></param>
|
private readonly string redisKey = "cache:Image";
|
||||||
/// <returns></returns>
|
|
||||||
public ConcurrentDictionary<int, string> this[string language]
|
/// <summary>
|
||||||
|
/// 图片缓存数据
|
||||||
|
/// </summary>
|
||||||
|
private ConcurrentDictionary<int, string> 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}";
|
||||||
|
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 按语言和图片ID获取图片URL
|
||||||
|
/// </summary>
|
||||||
|
public string this[int imageId]
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(language))
|
|
||||||
{
|
|
||||||
language = appRequestConfig.Language;
|
|
||||||
}
|
|
||||||
if (ImageData != null && ImageData.TryGetValue(language, out var images))
|
|
||||||
{
|
|
||||||
return images;
|
|
||||||
}
|
|
||||||
ImageData = MemoryCacheHelper.GetCache<ConcurrentDictionary<string, ConcurrentDictionary<int, string>>>(key);
|
|
||||||
if (ImageData == null)
|
|
||||||
{
|
|
||||||
ImageData = new ConcurrentDictionary<string, ConcurrentDictionary<int, string>>();
|
|
||||||
|
|
||||||
}
|
if (imageId == 0) return string.Empty;
|
||||||
if (!ImageData.TryGetValue(language, out images))
|
if (this.imageData == null)
|
||||||
{
|
{
|
||||||
ImageData.TryAdd(language, images = new ConcurrentDictionary<int, string>());
|
var t = MemoryCacheHelper.GetCache<ConcurrentDictionary<int, string>>(memoryCacheKey);
|
||||||
//内存中缓存
|
if (t == null)
|
||||||
MemoryCacheHelper.SetCache(key, ImageData, 60 * 60 * 24);
|
{
|
||||||
|
t = new ConcurrentDictionary<int, string>();
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
private string LoadImageFromRedis(string language, int imageId)
|
||||||
/// </summary>
|
|
||||||
/// <param name="language"></param>
|
|
||||||
/// <param name="imageId"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public string this[string language, int imageId]
|
|
||||||
{
|
{
|
||||||
get
|
var redisValue = database.StringGet($"{redisKey}:{language}:{imageId}");
|
||||||
|
if (redisValue.IsNullOrEmpty)
|
||||||
{
|
{
|
||||||
if (imageId == 0)
|
redisValue = database.StringGet($"{redisKey}:default:{imageId}");
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
var _imageData = this[language];
|
|
||||||
if (_imageData == null)
|
|
||||||
{
|
|
||||||
_imageData = new ConcurrentDictionary<int, string>();
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
return redisValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConcurrentDictionary<string, ConcurrentDictionary<int, string>> LoadImage(DAO dao, AppConfig appConfig)
|
private void LoadImagesFromDatabase()
|
||||||
{
|
{
|
||||||
// 初始化_data字典
|
var isadd = database.StringGet<List<string>>($"{redisKey}:language");
|
||||||
ConcurrentDictionary<string, ConcurrentDictionary<int, string>> _data = new ConcurrentDictionary<string, ConcurrentDictionary<int, string>>();
|
if (isadd != null && isadd.Count > 0)
|
||||||
|
{
|
||||||
// 获取图像列表
|
foreach (var _language in isadd)
|
||||||
var imageList = dao.DaoExt.Context.T_App_Image
|
{
|
||||||
|
var mKey = $"{appConfig.Identifier}:App:Image:{_language}";
|
||||||
|
var imageRedis = database.StringGet<Dictionary<int, string>>($"{redisKey}:language:{_language}");
|
||||||
|
//database.StringGet<>
|
||||||
|
var imagex = new ConcurrentDictionary<int, string>(imageRedis ?? new Dictionary<int, string>());
|
||||||
|
MemoryCacheHelper.SetCache(mKey, imagex);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var data = new ConcurrentDictionary<string, ConcurrentDictionary<int, string>>();
|
||||||
|
var images = dao.DaoExt.Context.T_App_Image
|
||||||
.Where(it => !string.IsNullOrEmpty(it.Url))
|
.Where(it => !string.IsNullOrEmpty(it.Url))
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.Select(it => new { it.ImageId, it.Language, it.Url })
|
.Select(it => new { it.ImageId, it.Language, it.Url })
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
// 设置默认语言
|
// 设置默认语言
|
||||||
if (string.IsNullOrEmpty(appConfig.DefaultLanguage))
|
if (string.IsNullOrEmpty(appConfig.DefaultLanguage))
|
||||||
{
|
{
|
||||||
appConfig.DefaultLanguage = "zh";
|
appConfig.DefaultLanguage = "zh";
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建默认语言的图像字典
|
// 创建默认语言的图像字典
|
||||||
var defaultImage = imageList
|
var defaultImage = images
|
||||||
.Where(it => it.Language == appConfig.DefaultLanguage)
|
.Where(it => it.Language == appConfig.DefaultLanguage)
|
||||||
.GroupBy(it => it.ImageId)
|
.GroupBy(it => it.ImageId)
|
||||||
.ToDictionary(group => group.Key, group => appConfig.AliyunConfig.ImagePrefix + group.Last().Url);
|
.ToDictionary(group => group.Key, group => appConfig.AliyunConfig.ImagePrefix + group.Last().Url);
|
||||||
|
if (defaultImage == null)
|
||||||
// 遍历图像列表,填充_data字典
|
|
||||||
foreach (var item in imageList)
|
|
||||||
{
|
{
|
||||||
// 尝试获取语言字典,如果不存在则创建
|
defaultImage = new Dictionary<int, string>();
|
||||||
if (!_data.TryGetValue(item.Language, out var languageImage))
|
}
|
||||||
|
foreach (var image in images)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(image.Url))
|
||||||
{
|
{
|
||||||
languageImage = new ConcurrentDictionary<int, string>();
|
continue;
|
||||||
_data[item.Language] = languageImage;
|
|
||||||
}
|
}
|
||||||
|
var languageCache = data.GetOrAdd(image.Language, _ => new ConcurrentDictionary<int, string>());
|
||||||
// 设置图像URL
|
var url = string.Empty;
|
||||||
languageImage[item.ImageId] = appConfig.AliyunConfig.ImagePrefix + item.Url;
|
if (image.Url.StartsWith("http://") || image.Url.StartsWith("https://"))
|
||||||
|
{
|
||||||
|
url = $"{image.Url}";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
url = $"{appConfig.AliyunConfig.ImagePrefix}{image.Url}";
|
||||||
|
}
|
||||||
|
languageCache[image.ImageId] = url;
|
||||||
// 如果默认图像字典中没有此ImageId,加入默认图像字典
|
// 如果默认图像字典中没有此ImageId,加入默认图像字典
|
||||||
if (!defaultImage.ContainsKey(item.ImageId))
|
if (!defaultImage.ContainsKey(image.ImageId))
|
||||||
{
|
{
|
||||||
defaultImage[item.ImageId] = appConfig.AliyunConfig.ImagePrefix + item.Url;
|
defaultImage[image.ImageId] = url;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#region 保存默认图片
|
||||||
// 更新默认语言的图像字典
|
var defaultLanguageCache = new ConcurrentDictionary<int, string>(defaultImage);
|
||||||
_data["default"] = new ConcurrentDictionary<int, string>(defaultImage);
|
foreach (var kv in defaultLanguageCache)
|
||||||
foreach (var item in _data.Keys)
|
|
||||||
{
|
{
|
||||||
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}";
|
d = defaultLanguageCache;
|
||||||
database.StringSet(_redisKey, image.Value, TimeSpan.FromDays(1));
|
|
||||||
}
|
}
|
||||||
|
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));
|
database.StringSet($"{redisKey}:language", languages);
|
||||||
return _data;
|
|
||||||
|
#endregion
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 读取图片
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="imageId"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public string this[int imageId]
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
var imageUrl = this[appRequestConfig.Language, imageId];
|
|
||||||
return imageUrl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 清除缓存
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="NotImplementedException"></exception>
|
|
||||||
public bool ClearData()
|
public bool ClearData()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
|
||||||
|
foreach (var _language in languages)
|
||||||
|
{
|
||||||
|
var mKey = $"{appConfig.Identifier}:App:Image:{_language}";
|
||||||
|
MemoryCacheHelper.cache.Remove(mKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 重新加载缓存
|
|
||||||
/// </summary>
|
|
||||||
/// <exception cref="NotImplementedException"></exception>
|
|
||||||
public void ReloadData()
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
using CloudGaming.Code.Cache;
|
||||||
using CloudGaming.DtoModel;
|
using CloudGaming.DtoModel;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
@ -48,6 +49,24 @@ namespace CloudGaming.Code.Config
|
||||||
return list.GetAppIsChecking(AppRequestInfo);
|
return list.GetAppIsChecking(AppRequestInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 清除缓存
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool ClearCacheData()
|
||||||
|
{
|
||||||
|
this.ClearLocalDataCache();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 加载redis缓存
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool ReloadLocalData()
|
||||||
|
{
|
||||||
|
this.ReloadLocalDataCache();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
objectResult.Value = dic;
|
||||||
}
|
}
|
||||||
//else
|
//else
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ namespace CloudGaming.Code.Game
|
||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 初始化app
|
/// 初始化游戏服务
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="builder"></param>
|
/// <param name="builder"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,10 @@ namespace CloudGaming.AppConfigModel
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string PrivacyAgreement { get; set; }
|
public string PrivacyAgreement { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 多语言列表请求地址
|
||||||
|
/// </summary>
|
||||||
|
public string LanguageRequestUrl { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取数据库连接字符串
|
/// 获取数据库连接字符串
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -105,7 +105,7 @@ public abstract class CommonDataEntityCache<T> : ICacheClearData, ICacheReloadDa
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 缓存扩展-
|
/// 缓存扩展-
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class RedisDataEntityCache<T> : CommonDataEntityCache<T> where T : class
|
public abstract class RedisDataEntityCache<T> : CommonDataEntityCache<T>, ICacheClearLocalData where T : class
|
||||||
{
|
{
|
||||||
public IDatabase database;
|
public IDatabase database;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -160,7 +160,7 @@ public abstract class RedisDataEntityCache<T> : CommonDataEntityCache<T> where T
|
||||||
database.StringSet(key, tempDataList, TimeSpan.FromSeconds(cacheTime));
|
database.StringSet(key, tempDataList, TimeSpan.FromSeconds(cacheTime));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_dataList = JsonConvert.DeserializeObject<List<T>>(JsonConvert.SerializeObject(tempDataList));
|
//_dataList = JsonConvert.DeserializeObject<List<T>>(JsonConvert.SerializeObject(tempDataList));
|
||||||
database.KeyDeleteAsync($"lock:{key}").Wait();
|
database.KeyDeleteAsync($"lock:{key}").Wait();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -214,4 +214,10 @@ public abstract class RedisDataEntityCache<T> : CommonDataEntityCache<T> where T
|
||||||
database.KeyDeleteAsync($"lock:{key}").Wait();
|
database.KeyDeleteAsync($"lock:{key}").Wait();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool ClearLocalData()
|
||||||
|
{
|
||||||
|
_dataList = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ using System.Threading.Tasks;
|
||||||
namespace HuanMeng.DotNetCore.CacheHelper.Contract
|
namespace HuanMeng.DotNetCore.CacheHelper.Contract
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 清除缓存
|
/// 清除缓存
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ICacheClearData
|
public interface ICacheClearData
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 清除缓存
|
||||||
|
/// </summary>
|
||||||
|
public interface ICacheClearLocalData
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 清除数据
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
bool ClearLocalData();
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user