游戏列表异步实验
This commit is contained in:
parent
1fb5621af7
commit
ea1fc8a322
|
|
@ -56,7 +56,7 @@ namespace CloudGaming.Api.Controllers
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[RedisCache(2, 2, 0)]
|
[RedisCache(2, 2, 0)]
|
||||||
public GameInfoDto GetGameInfo([FromQuery] string gameId)
|
public Task<GameInfoDto> GetGameInfo([FromQuery] string gameId)
|
||||||
{
|
{
|
||||||
GameBLL gamebll = new GameBLL(this.ServiceProvider);
|
GameBLL gamebll = new GameBLL(this.ServiceProvider);
|
||||||
return gamebll.GetGameInfo(gameId);
|
return gamebll.GetGameInfo(gameId);
|
||||||
|
|
@ -68,7 +68,7 @@ namespace CloudGaming.Api.Controllers
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[RedisCache(0, 5, 0)]
|
[RedisCache(0, 5, 0)]
|
||||||
public List<GameListDto> GameRecommendations([FromQuery] string? gameId)
|
public Task<List<GameListDto>> GameRecommendations([FromQuery] string? gameId)
|
||||||
{
|
{
|
||||||
|
|
||||||
GameBLL gamebll = new GameBLL(this.ServiceProvider);
|
GameBLL gamebll = new GameBLL(this.ServiceProvider);
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ namespace CloudGaming.Code.Cache
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
|
||||||
return GameEntityCache?.DataList ?? new List<GameInfo>();
|
return GameEntityCache?.DataListAsync.Result;// ?? new List<GameInfo>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@ using CloudGaming.GameModel.Db.Db_Game;
|
||||||
using HuanMeng.DotNetCore.CacheHelper;
|
using HuanMeng.DotNetCore.CacheHelper;
|
||||||
using HuanMeng.DotNetCore.Redis;
|
using HuanMeng.DotNetCore.Redis;
|
||||||
|
|
||||||
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
using Org.BouncyCastle.Utilities.Collections;
|
using Org.BouncyCastle.Utilities.Collections;
|
||||||
|
|
@ -24,37 +26,63 @@ 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) :
|
||||||
|
CommonDataEntityCacheAsync<GameInfo>(GameEntityCache.SemaphoreSlim, 60 * 60 * 24)
|
||||||
|
//CommonDataEntityCache<GameInfo>(GameEntityCache.GameEntityCacheLock, 60 * 60 * 24 * 7)
|
||||||
{
|
{
|
||||||
public static object GameEntityCacheLock;
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步锁
|
||||||
|
/// </summary>
|
||||||
|
public static SemaphoreSlim SemaphoreSlim = new SemaphoreSlim(1, 1);
|
||||||
|
/// <summary>
|
||||||
|
/// 内存key
|
||||||
|
/// </summary>
|
||||||
public override string key => $"{appConfig.Identifier}:game:gameInfo";
|
public override string key => $"{appConfig.Identifier}:game:gameInfo";
|
||||||
|
/// <summary>
|
||||||
|
/// 缓存锁key
|
||||||
|
/// </summary>
|
||||||
public string locaKey => $"lock:gameInfo";
|
public string locaKey => $"lock:gameInfo";
|
||||||
|
/// <summary>
|
||||||
|
/// redis 缓存key
|
||||||
|
/// </summary>
|
||||||
public string RedisKey => $"cache:game:gameInfo";
|
public string RedisKey => $"cache:game:gameInfo";
|
||||||
|
/// <summary>
|
||||||
|
/// 缓存时间
|
||||||
|
/// </summary>
|
||||||
|
public const int CacheHoursTime = 10;
|
||||||
|
|
||||||
public override List<GameInfo> GetDataList()
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 游戏数据
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override async Task<List<GameInfo>> GetDataListAsync()
|
||||||
{
|
{
|
||||||
var gameCbtList = dao.DaoPhone.Context.T_GameCBT.AsNoTracking().Where(it => it.IsOnline).ToList() ?? new List<T_GameCBT>();
|
var gameCbtList = await dao.DaoPhone.Context.T_GameCBT.AsNoTracking().Where(it => it.IsOnline).ToListAsync() ?? new List<T_GameCBT>();
|
||||||
var gameListDict = dao.DaoGame.Context.T_Game_List.AsNoTracking().ToDictionary(g => g.GameId);
|
//游戏列表
|
||||||
var gameChildList = dao.DaoGame.Context.T_Game_ChildList.AsNoTracking().ToList();
|
var gameListDict = await dao.DaoGame.Context.T_Game_List.AsNoTracking().ToDictionaryAsync(g => g.GameId);
|
||||||
|
//游戏标签、分类关联
|
||||||
var gameTypesDict = dao.DaoGame.Context.T_Game_Types.AsNoTracking().ToDictionary(type => type.TypeId);
|
var gameChildList = await dao.DaoGame.Context.T_Game_ChildList.AsNoTracking().ToListAsync();
|
||||||
var gameTagsDict = dao.DaoGame.Context.T_Game_Tags.AsNoTracking().ToDictionary(tag => tag.TagId);
|
//游戏分类
|
||||||
//游戏分享头像
|
var gameTypesDict = await dao.DaoGame.Context.T_Game_Types.AsNoTracking().ToDictionaryAsync(type => type.TypeId);
|
||||||
var gameUserShare = dao.DaoGame.Context.T_Game_UserShare.AsNoTracking().GroupBy(it => it.GameId).ToDictionary(it => it.Key, it => it.Last().NickName);
|
//标签
|
||||||
var appConfig = dao.DaoExt.Context.T_App_Config.AsNoTracking().Where(it => it.ConfigType == 3).ToList();
|
var gameTagsDict = await dao.DaoGame.Context.T_Game_Tags.AsNoTracking().ToDictionaryAsync(tag => tag.TagId);
|
||||||
|
//游戏用户分享
|
||||||
|
var gameUserShare = await dao.DaoGame.Context.T_Game_UserShare.AsNoTracking().GroupBy(it => it.GameId).ToDictionaryAsync(it => it.Key, it => it.Last().NickName);
|
||||||
|
//游戏配置
|
||||||
|
var appConfig = await dao.DaoExt.Context.T_App_Config.AsNoTracking().Where(it => it.ConfigType == 3).ToListAsync();
|
||||||
|
//统一消耗配置
|
||||||
var config = appConfig.GetAppConfig(3, 1, null);
|
var config = appConfig.GetAppConfig(3, 1, null);
|
||||||
var defaultConsumeDiamondNumHour = 0;
|
var defaultConsumeDiamondNumHour = 0;
|
||||||
if (!string.IsNullOrEmpty(config?.ConfigValue))
|
if (!string.IsNullOrEmpty(config?.ConfigValue))
|
||||||
{
|
{
|
||||||
int.TryParse(config?.ConfigValue, out defaultConsumeDiamondNumHour);
|
int.TryParse(config?.ConfigValue, out defaultConsumeDiamondNumHour);
|
||||||
}
|
}
|
||||||
//var lorem = new Bogus.DataSets.Lorem(locale: "zh_CN");
|
//生成用户昵称
|
||||||
var faker = new Faker("zh_CN");
|
var faker = new Faker("zh_CN");
|
||||||
//f.r
|
//组装游戏
|
||||||
|
|
||||||
//lorem.
|
|
||||||
var gameInfos = gameCbtList
|
var gameInfos = gameCbtList
|
||||||
.Where(gameCbt => gameListDict.ContainsKey(gameCbt.GameId))
|
.Where(gameCbt => gameListDict.ContainsKey(gameCbt.GameId))
|
||||||
.Select(gameCbt =>
|
.Select(gameCbt =>
|
||||||
|
|
@ -76,7 +104,6 @@ namespace CloudGaming.Code.Cache.Special
|
||||||
gameInfo.ConsumeDiamondNumHour = defaultConsumeDiamondNumHour;
|
gameInfo.ConsumeDiamondNumHour = defaultConsumeDiamondNumHour;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (gameInfo.ConsumeDiamondNumHour > 0)
|
if (gameInfo.ConsumeDiamondNumHour > 0)
|
||||||
{
|
{
|
||||||
gameInfo.GameDetailsofCharges = $"游戏资费:游玩按分钟计费,{gameInfo.ConsumeDiamondNumHour}钻石/小时。";
|
gameInfo.GameDetailsofCharges = $"游戏资费:游玩按分钟计费,{gameInfo.ConsumeDiamondNumHour}钻石/小时。";
|
||||||
|
|
@ -92,85 +119,93 @@ namespace CloudGaming.Code.Cache.Special
|
||||||
return gameInfos;
|
return gameInfos;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
public override Task<List<GameInfo>> DataListAsync
|
||||||
/// </summary>
|
|
||||||
public override List<GameInfo> DataList
|
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
start:
|
if (_dataList != null) return Task.FromResult(_dataList);
|
||||||
if (_dataList != null) return _dataList;
|
|
||||||
|
|
||||||
var tempDataList = MemoryCacheHelper.GetCache<List<GameInfo>>(key);
|
var tempDataList = MemoryCacheHelper.GetCache<List<GameInfo>>(key);
|
||||||
if (tempDataList != null)
|
if (tempDataList != null)
|
||||||
{
|
{
|
||||||
_dataList = tempDataList;
|
_dataList = tempDataList;
|
||||||
return _dataList;
|
return Task.FromResult(_dataList);
|
||||||
}
|
}
|
||||||
|
return Task.Run(async () =>
|
||||||
long hashLength = database.HashLength(RedisKey);
|
|
||||||
if (hashLength > 0)
|
|
||||||
{
|
{
|
||||||
var hashEntries = database.HashGetAll(RedisKey);
|
start:
|
||||||
var list = hashEntries
|
long hashLength = await database.HashLengthAsync(RedisKey);
|
||||||
.Where(entry => !string.IsNullOrEmpty(entry.Value))
|
if (hashLength > 0)
|
||||||
.Select(entry => JsonConvert.DeserializeObject<GameInfo>(entry.Value))
|
{
|
||||||
.ToList();
|
var hashEntries = await database.HashGetAllAsync(RedisKey);
|
||||||
|
var list = hashEntries
|
||||||
|
.Where(entry => !string.IsNullOrEmpty(entry.Value))
|
||||||
|
.Select(entry => JsonConvert.DeserializeObject<GameInfo>(entry.Value))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
MemoryCacheHelper.SetCache(key, list, 10);
|
MemoryCacheHelper.SetCache(key, list, TimeSpan.FromHours(CacheHoursTime));
|
||||||
_dataList = list;
|
_dataList = list;
|
||||||
|
return _dataList;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!database.StringSetLock(locaKey, "1", 5))
|
||||||
|
{
|
||||||
|
await Task.Delay(50);
|
||||||
|
goto start;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
tempDataList ??= await GetDataListAsync();
|
||||||
|
MemoryCacheHelper.SetCache(key, tempDataList, TimeSpan.FromHours(CacheHoursTime));
|
||||||
|
var serializedGameInfos = tempDataList
|
||||||
|
.Select(info => new HashEntry($"gameInfo:{info.GameId}", JsonConvert.SerializeObject(info)))
|
||||||
|
.ToArray();
|
||||||
|
await database.HashSetAsync(RedisKey, serializedGameInfos);
|
||||||
|
// 设置过期时间为1天
|
||||||
|
await database.KeyExpireAsync(RedisKey, TimeSpan.FromDays(1));
|
||||||
|
_dataList = tempDataList;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
database.KeyDelete(locaKey);
|
||||||
|
}
|
||||||
return _dataList;
|
return _dataList;
|
||||||
}
|
});
|
||||||
|
|
||||||
if (!database.StringSetLock(locaKey, "1", 5))
|
|
||||||
{
|
|
||||||
goto start;
|
|
||||||
}
|
|
||||||
|
|
||||||
tempDataList ??= GetDataList();
|
|
||||||
var serializedGameInfos = tempDataList
|
|
||||||
.Select(info => new HashEntry($"gameInfo:{info.GameId}", JsonConvert.SerializeObject(info)))
|
|
||||||
.ToArray();
|
|
||||||
database.HashSet(RedisKey, serializedGameInfos);
|
|
||||||
|
|
||||||
MemoryCacheHelper.SetCache(key, tempDataList, 60 * 60);
|
|
||||||
_dataList = tempDataList;
|
|
||||||
database.KeyDelete(locaKey);
|
|
||||||
return _dataList;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//public Task<List<GameInfo>> DataListAsync
|
|
||||||
//{
|
|
||||||
// get
|
|
||||||
// {
|
|
||||||
|
|
||||||
// return new List<GameInfo>();
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
private Dictionary<string, GameInfo> gameInfoDic;
|
private Dictionary<string, GameInfo> gameInfoDic;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 游戏详情
|
/// 游戏详情
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Dictionary<string, GameInfo> GameInfoDic
|
public Task<Dictionary<string, GameInfo>> GameInfoAsync
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (gameInfoDic == null)
|
if (gameInfoDic != null)
|
||||||
{
|
{
|
||||||
gameInfoDic = DataList.ToDictionary(it => it.GameId);
|
return Task.FromResult(gameInfoDic);
|
||||||
}
|
}
|
||||||
return gameInfoDic;
|
return Task.Run(async () => { gameInfoDic = (await DataListAsync).ToDictionary(it => it.GameId); return gameInfoDic; });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取游戏详情
|
/// 获取游戏详情
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="gameId"></param>
|
/// <param name="gameId"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public GameInfo? this[string? gameId]
|
public Task<GameInfo?> this[string? gameId]
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
|
@ -178,15 +213,11 @@ namespace CloudGaming.Code.Cache.Special
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return GameInfoDic[gameId] ?? null;
|
return Task.Run(async () => (await GameInfoAsync)[gameId] ?? null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<GameExtendedAttribute> GetGameExtendedAttributes<T>(
|
private List<GameExtendedAttribute> GetGameExtendedAttributes<T>(List<T_Game_ChildList> gameChildList, string gameId, int childType, Dictionary<int, T> dictionary) where T : class
|
||||||
List<T_Game_ChildList> gameChildList,
|
|
||||||
string gameId,
|
|
||||||
int childType,
|
|
||||||
Dictionary<int, T> dictionary) where T : class
|
|
||||||
{
|
{
|
||||||
return gameChildList
|
return gameChildList
|
||||||
.Where(it => it.GameId == gameId && it.ChildType == childType && (it.ChildId ?? 0) > 0)
|
.Where(it => it.GameId == gameId && it.ChildType == childType && (it.ChildId ?? 0) > 0)
|
||||||
|
|
@ -217,25 +248,26 @@ namespace CloudGaming.Code.Cache.Special
|
||||||
|
|
||||||
public override bool ClearData()
|
public override bool ClearData()
|
||||||
{
|
{
|
||||||
lock (GameEntityCacheLock)
|
|
||||||
{
|
database.KeyDelete(key);
|
||||||
database.KeyDelete(key);
|
MemoryCacheHelper.DelCache(key);
|
||||||
MemoryCacheHelper.DelCache(key);
|
database.KeyDelete(RedisKey);
|
||||||
_dataList = null;
|
_dataList = null;
|
||||||
gameInfoDic = null;
|
gameInfoDic = null;
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ReloadData()
|
public override void ReloadData()
|
||||||
{
|
{
|
||||||
lock (lockObj)
|
database.KeyDelete(key);
|
||||||
{
|
database.KeyDelete(RedisKey);
|
||||||
database.KeyDelete(key);
|
|
||||||
MemoryCacheHelper.DelCache(key);
|
MemoryCacheHelper.DelCache(key);
|
||||||
_dataList = null;
|
|
||||||
var x = DataList;
|
_dataList = null;
|
||||||
}
|
var x = DataListAsync.Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,39 +26,33 @@ namespace CloudGaming.Code.Epg
|
||||||
public async Task<List<EpgCategoryDto>> GetHomeInfo()
|
public async Task<List<EpgCategoryDto>> GetHomeInfo()
|
||||||
{
|
{
|
||||||
var listQueryable = GetEpgCategory(EpgEnum.EpgCatIdName.大厅首页).AsQueryable();
|
var listQueryable = GetEpgCategory(EpgEnum.EpgCatIdName.大厅首页).AsQueryable();
|
||||||
if (IsChecking)
|
int[] showStatus = IsChecking ? [0, 2] : [0, 1];
|
||||||
{
|
var list = listQueryable.Where(it => showStatus.Contains(it.ShowStatus)).OrderBy(it => it.OrderId).ToList();
|
||||||
listQueryable = listQueryable.Where(it => it.ShowStatus == 0 || it.ShowStatus == 2).AsQueryable();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
listQueryable = listQueryable.Where(it => it.ShowStatus == 0 || it.ShowStatus == 1).AsQueryable();
|
|
||||||
}
|
|
||||||
var list = listQueryable.OrderBy(it => it.OrderId).ToList();
|
|
||||||
|
|
||||||
List<EpgCategoryDto> epgCategoryDtos = new List<EpgCategoryDto>();
|
List<EpgCategoryDto> epgCategoryDtos = new List<EpgCategoryDto>();
|
||||||
list.ForEach(it =>
|
foreach (var it in list)
|
||||||
{
|
{
|
||||||
var list = new List<EpgInfo>()
|
var epglist = new List<EpgInfo>()
|
||||||
{
|
{
|
||||||
//STEAMCLOUD
|
//STEAMCLOUD
|
||||||
};
|
};
|
||||||
var epgList = GetEpgList(it.Id);
|
var epgList = GetEpgList(it.Id);
|
||||||
epgList?.ForEach(item =>
|
foreach (var item in epgList)
|
||||||
{
|
{
|
||||||
//如果首页展示数量小于集合数量,则退出
|
//如果首页展示数量小于集合数量,则退出
|
||||||
if (it.ShowNumIndex < list.Count)
|
if (it.ShowNumIndex < epglist.Count)
|
||||||
{
|
{
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
var epgInfo = item.ToEpgInfo(Cache.GameEntityCache);
|
var epgInfo = await item.ToEpgInfo(Cache.GameEntityCache);
|
||||||
if (epgInfo != null)
|
if (epgInfo != null)
|
||||||
{
|
{
|
||||||
list.Add(epgInfo);
|
epglist.Add(epgInfo);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
if (list.Count > 0)
|
|
||||||
|
if (epglist.Count > 0)
|
||||||
{
|
{
|
||||||
EpgCategoryDto epgCategoryDto = new EpgCategoryDto()
|
EpgCategoryDto epgCategoryDto = new EpgCategoryDto()
|
||||||
{
|
{
|
||||||
|
|
@ -66,12 +60,13 @@ namespace CloudGaming.Code.Epg
|
||||||
CategoryType = it.IdName,
|
CategoryType = it.IdName,
|
||||||
IsQuickStartPopUp = it.IsQuickStartPopUp ?? false,
|
IsQuickStartPopUp = it.IsQuickStartPopUp ?? false,
|
||||||
ShowNum_Index = it.ShowNumIndex ?? 0,
|
ShowNum_Index = it.ShowNumIndex ?? 0,
|
||||||
EpgList = list
|
EpgList = epglist
|
||||||
};
|
};
|
||||||
|
|
||||||
epgCategoryDtos.Add(epgCategoryDto);
|
epgCategoryDtos.Add(epgCategoryDto);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
return epgCategoryDtos;
|
return epgCategoryDtos;
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ namespace CloudGaming.Code.Epg
|
||||||
/// <param name="epgCfg"></param>
|
/// <param name="epgCfg"></param>
|
||||||
/// <param name="gameEntityCache"></param>
|
/// <param name="gameEntityCache"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static EpgInfo ToEpgInfo(this T_Epg_Cfg epgCfg, GameEntityCache gameEntityCache)
|
public static async Task<EpgInfo> ToEpgInfo(this T_Epg_Cfg epgCfg, GameEntityCache gameEntityCache)
|
||||||
{
|
{
|
||||||
if (epgCfg.ResType == (int)EpgEnum.EpgResType.游戏 && string.IsNullOrEmpty(epgCfg.ResId))
|
if (epgCfg.ResType == (int)EpgEnum.EpgResType.游戏 && string.IsNullOrEmpty(epgCfg.ResId))
|
||||||
{
|
{
|
||||||
|
|
@ -41,7 +41,7 @@ namespace CloudGaming.Code.Epg
|
||||||
|
|
||||||
if (epgCfg.ResType == (int)EpgEnum.EpgResType.游戏)
|
if (epgCfg.ResType == (int)EpgEnum.EpgResType.游戏)
|
||||||
{
|
{
|
||||||
var gameInfo = gameEntityCache[epgCfg.ResId];
|
var gameInfo = await gameEntityCache[epgCfg.ResId];
|
||||||
if (gameInfo == null)
|
if (gameInfo == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
|
|
|
||||||
|
|
@ -24,10 +24,8 @@ namespace CloudGaming.Code.Game
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<List<GameExtendedAttribute>> GetGameTypeListAsync()
|
public async Task<List<GameExtendedAttribute>> GetGameTypeListAsync()
|
||||||
{
|
{
|
||||||
var gameList = Cache.GameEntityCache?.DataList ?? new List<GameInfo>();
|
var gameList = await Cache.GameEntityCache.DataListAsync;
|
||||||
var gameTypes = await Task.Run(() =>
|
var list = CloudGamingCacheExtend.GetDataEntityCache<T_Game_Types>(this, it => it.IsOnline)?.DataList
|
||||||
{
|
|
||||||
return CloudGamingCacheExtend.GetDataEntityCache<T_Game_Types>(this, it => it.IsOnline)?.DataList
|
|
||||||
.Where(it => gameList.Any(item => item.GameType?.Any(gameType => gameType.Id == it.TypeId) ?? false))
|
.Where(it => gameList.Any(item => item.GameType?.Any(gameType => gameType.Id == it.TypeId) ?? false))
|
||||||
.OrderBy(it => it.OrderId)
|
.OrderBy(it => it.OrderId)
|
||||||
.Select(it => new GameExtendedAttribute
|
.Select(it => new GameExtendedAttribute
|
||||||
|
|
@ -37,9 +35,9 @@ namespace CloudGaming.Code.Game
|
||||||
OrderId = it.OrderId
|
OrderId = it.OrderId
|
||||||
})
|
})
|
||||||
.ToList();
|
.ToList();
|
||||||
});
|
return list;
|
||||||
|
|
||||||
|
|
||||||
return gameTypes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -49,14 +47,8 @@ namespace CloudGaming.Code.Game
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<List<GameListDto>> GetGameListAsync(int typeId)
|
public async Task<List<GameListDto>> GetGameListAsync(int typeId)
|
||||||
{
|
{
|
||||||
|
var gameList = await Cache.GameEntityCache.DataListAsync;
|
||||||
var gameListDto = await Task.Run(() =>
|
var gameListDto = gameList.Where(it => it.GameType?.Any(item => item.Id == typeId) ?? false).Select(it => new GameListDto(it)).ToList();
|
||||||
{
|
|
||||||
var gameList = Cache.GameEntityCache?.DataList ?? new List<GameInfo>();
|
|
||||||
var x = gameList.Where(it => it.GameType?.Any(item => item.Id == typeId) ?? false).Select(it => new
|
|
||||||
GameListDto(it)).ToList();
|
|
||||||
return x;
|
|
||||||
});
|
|
||||||
return gameListDto;
|
return gameListDto;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -65,13 +57,13 @@ namespace CloudGaming.Code.Game
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="gameId"></param>
|
/// <param name="gameId"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public GameInfoDto GetGameInfo(string gameId)
|
public async Task<GameInfoDto> GetGameInfo(string gameId)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(gameId))
|
if (string.IsNullOrEmpty(gameId))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
var game = Cache.GameEntityCache[gameId];
|
var game = await Cache.GameEntityCache[gameId];
|
||||||
if (game == null)
|
if (game == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -85,12 +77,12 @@ namespace CloudGaming.Code.Game
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="gameId"></param>
|
/// <param name="gameId"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public List<GameListDto> GameRecommendations(string gameId)
|
public async Task<List<GameListDto>> GameRecommendations(string gameId)
|
||||||
{
|
{
|
||||||
List<GameInfo>? gameInfos = null;
|
List<GameInfo>? gameInfos = null;
|
||||||
if (!string.IsNullOrEmpty(gameId))
|
if (!string.IsNullOrEmpty(gameId))
|
||||||
{
|
{
|
||||||
var game = Cache.GameEntityCache[gameId];
|
var game = await Cache.GameEntityCache[gameId];
|
||||||
if (game != null)
|
if (game != null)
|
||||||
{
|
{
|
||||||
var gameTagIds = game.GameTags.Select(it => it.Id);
|
var gameTagIds = game.GameTags.Select(it => it.Id);
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ namespace CloudGaming.Code.MiddlewareExtend
|
||||||
{
|
{
|
||||||
// 检查当前请求是否需要缓存
|
// 检查当前请求是否需要缓存
|
||||||
var cacheAttribute = GetCacheAttribute(context);
|
var cacheAttribute = GetCacheAttribute(context);
|
||||||
if (cacheAttribute == null)
|
if (cacheAttribute == null || true)
|
||||||
{
|
{
|
||||||
await _next(context);
|
await _next(context);
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,14 @@
|
||||||
using HuanMeng.DotNetCore.CacheHelper.Contract;
|
using HuanMeng.DotNetCore.CacheHelper.Contract;
|
||||||
|
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Internal;
|
||||||
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace HuanMeng.DotNetCore.CacheHelper
|
namespace HuanMeng.DotNetCore.CacheHelper
|
||||||
|
|
@ -55,12 +58,8 @@ namespace HuanMeng.DotNetCore.CacheHelper
|
||||||
{
|
{
|
||||||
lock (lockObj)
|
lock (lockObj)
|
||||||
{
|
{
|
||||||
tempDataList = MemoryCacheHelper.GetCache<List<T>>(key);
|
tempDataList = GetDataList();
|
||||||
if (tempDataList == null)
|
MemoryCacheHelper.SetCache(key, tempDataList, cacheTime);
|
||||||
{
|
|
||||||
tempDataList = GetDataList();
|
|
||||||
MemoryCacheHelper.SetCache(key, tempDataList, cacheTime);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_dataList = JsonConvert.DeserializeObject<List<T>>(JsonConvert.SerializeObject(tempDataList));
|
_dataList = JsonConvert.DeserializeObject<List<T>>(JsonConvert.SerializeObject(tempDataList));
|
||||||
|
|
@ -95,4 +94,120 @@ namespace HuanMeng.DotNetCore.CacheHelper
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步缓存
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
public abstract class CommonDataEntityCacheAsync<T> : ICacheClearData, ICacheReloadData where T : class
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 过期时间
|
||||||
|
/// </summary>
|
||||||
|
protected int cacheTime;
|
||||||
|
|
||||||
|
private readonly SemaphoreSlim _semaphore; // 异步锁
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="semaphore">异步锁new SemaphoreSlim(initialCount: 1, maxCount: 1); </param>
|
||||||
|
/// <param name="cacheTime"></param>
|
||||||
|
protected CommonDataEntityCacheAsync(SemaphoreSlim semaphore, int cacheTime = 36000)
|
||||||
|
{
|
||||||
|
//new SemaphoreSlim(initialCount: 1, maxCount: 1);
|
||||||
|
this._semaphore = semaphore;
|
||||||
|
this.cacheTime = cacheTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public abstract string key { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 缓存数据
|
||||||
|
/// </summary>
|
||||||
|
protected List<T>? _dataList;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数据
|
||||||
|
/// </summary>
|
||||||
|
public virtual Task<List<T>> DataListAsync
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
// 如果已有缓存数据,直接返回
|
||||||
|
if (_dataList != null)
|
||||||
|
{
|
||||||
|
return Task.FromResult(_dataList);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 尝试从缓存获取
|
||||||
|
var tempDataList = MemoryCacheHelper.GetCache<List<T>>(key);
|
||||||
|
if (tempDataList != null)
|
||||||
|
{
|
||||||
|
_dataList = JsonConvert.DeserializeObject<List<T>>(JsonConvert.SerializeObject(tempDataList)) ?? new List<T>();
|
||||||
|
return Task.FromResult(_dataList);
|
||||||
|
}
|
||||||
|
return Task.Run(async () =>
|
||||||
|
{
|
||||||
|
// 进行异步加锁,避免多线程竞争
|
||||||
|
await _semaphore.WaitAsync();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 重新检查缓存
|
||||||
|
tempDataList = MemoryCacheHelper.GetCache<List<T>>(key);
|
||||||
|
if (tempDataList == null)
|
||||||
|
{
|
||||||
|
tempDataList = await GetDataListAsync(); // 异步获取数据
|
||||||
|
MemoryCacheHelper.SetCache(key, tempDataList, cacheTime);
|
||||||
|
}
|
||||||
|
_dataList = JsonConvert.DeserializeObject<List<T>>(JsonConvert.SerializeObject(tempDataList)) ?? new List<T>();
|
||||||
|
|
||||||
|
return _dataList;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_semaphore.Release(); // 释放锁
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取缓存数据
|
||||||
|
/// </summary>
|
||||||
|
public abstract Task<List<T>> GetDataListAsync();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 清除缓存
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual bool ClearData()
|
||||||
|
{
|
||||||
|
|
||||||
|
MemoryCacheHelper.DelCache(key);
|
||||||
|
_dataList = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 重新加载缓存
|
||||||
|
/// </summary>
|
||||||
|
public virtual void ReloadData()
|
||||||
|
{
|
||||||
|
|
||||||
|
var tempDataList = GetDataListAsync().Result;
|
||||||
|
MemoryCacheHelper.SetCache(key, tempDataList, cacheTime);
|
||||||
|
_dataList = tempDataList;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using Microsoft.Extensions.Caching.Memory;
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
@ -22,7 +23,7 @@ namespace HuanMeng.DotNetCore.CacheHelper
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static T? GetCache<T>(string cacheName) where T : class, new()
|
public static T? GetCache<T>(string cacheName) where T : class, new()
|
||||||
{
|
{
|
||||||
|
|
||||||
return cache.TryGetValue(cacheName, out var value) ? value as T : null;
|
return cache.TryGetValue(cacheName, out var value) ? value as T : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -40,6 +41,18 @@ namespace HuanMeng.DotNetCore.CacheHelper
|
||||||
cache.Set(cacheName, val, TimeSpan.FromSeconds(cacheTime));
|
cache.Set(cacheName, val, TimeSpan.FromSeconds(cacheTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设置缓存
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cacheName"></param>
|
||||||
|
/// <param name="val"></param>
|
||||||
|
/// <param name="cacheTime">单位秒,默认1小时</param>
|
||||||
|
public static void SetCache(string cacheName, object val, TimeSpan timeSpan)
|
||||||
|
{
|
||||||
|
cache.Set(cacheName, val, timeSpan);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 删除缓存
|
/// 删除缓存
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user