项目缓存状态逻辑,全局修改
continuous-integration/drone/push Build is passing Details

IRC_NewDev
hang 2024-08-21 14:37:33 +08:00
parent c7fd9a6bcb
commit 3b48dfae31
6 changed files with 86 additions and 67 deletions

View File

@ -37,23 +37,24 @@ namespace IRaCIS.Application.Services.BackGroundJob
{ {
_logger.LogInformation("项目启动 hangfire 任务初始化 执行开始~"); _logger.LogInformation("项目启动 hangfire 任务初始化 执行开始~");
//初始化国际化
//项目状态 立即加载到缓存中
await MemoryCacheTrialStatusAsync();
//await MemoryCacheAnonymizeData();
//创建项目缓存 定时任务
HangfireJobHelper.AddOrUpdateInitCronJob<IIRaCISHangfireJob>("RecurringJob_Cache_TrialState", t => t.MemoryCacheTrialStatusAsync(), Cron.Daily());
//初始化
await InternationalizationHelper.InitInternationlizationDataAndWatchJsonFileAsync(_internationalizationRepository); await InternationalizationHelper.InitInternationlizationDataAndWatchJsonFileAsync(_internationalizationRepository);
//创建邮件定时任务 //创建邮件定时任务
await InitSysAndTrialCronJobAsync(); await InitSysAndTrialCronJobAsync();
#region 废弃
////项目状态 立即加载到缓存中
//await MemoryCacheTrialStatusAsync();
////await MemoryCacheAnonymizeData();
////创建项目缓存 定时任务
//HangfireJobHelper.AddOrUpdateInitCronJob<IIRaCISHangfireJob>("RecurringJob_Cache_TrialState", t => t.MemoryCacheTrialStatusAsync(), Cron.Daily());
#endregion
_logger.LogInformation("项目启动 hangfire 任务初始化 执行结束"); _logger.LogInformation("项目启动 hangfire 任务初始化 执行结束");
} }

View File

@ -9,6 +9,7 @@ using Panda.DynamicWebApi.Attributes;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using ZiggyCreatures.Caching.Fusion;
namespace IRaCIS.Core.Application namespace IRaCIS.Core.Application
{ {
@ -32,7 +33,7 @@ namespace IRaCIS.Core.Application
public IWebHostEnvironment _hostEnvironment { get; set; } public IWebHostEnvironment _hostEnvironment { get; set; }
public IFusionCache _fusionCache { get; set; }
public static IResponseOutput Null404NotFound<TEntity>(TEntity? businessObject) where TEntity : class public static IResponseOutput Null404NotFound<TEntity>(TEntity? businessObject) where TEntity : class
@ -60,6 +61,9 @@ namespace IRaCIS.Core.Application
[MemberNotNull(nameof(_hostEnvironment))] [MemberNotNull(nameof(_hostEnvironment))]
public IWebHostEnvironment _hostEnvironment { get; set; } public IWebHostEnvironment _hostEnvironment { get; set; }
[MemberNotNull(nameof(_fusionCache))]
public IFusionCache _fusionCache { get; set; }
} }
#endregion #endregion
@ -81,7 +85,8 @@ namespace IRaCIS.Core.Application
[MemberNotNull(nameof(_localizer))] [MemberNotNull(nameof(_localizer))]
public IStringLocalizer _localizer { get; set; } public IStringLocalizer _localizer { get; set; }
[MemberNotNull(nameof(_fusionCache))]
public IFusionCache _fusionCache { get; set; }
} }
@ -97,6 +102,8 @@ namespace IRaCIS.Core.Application
public IStringLocalizer _localizer { get; set; } public IStringLocalizer _localizer { get; set; }
public IFusionCache _fusionCache { get; set; }
public static IResponseOutput Null404NotFound<TEntity>(TEntity? businessObject) where TEntity : class public static IResponseOutput Null404NotFound<TEntity>(TEntity? businessObject) where TEntity : class
{ {
return new ResponseOutput<string>() return new ResponseOutput<string>()

View File

@ -1,4 +1,5 @@
using EasyCaching.Core; using EasyCaching.Core;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
@ -19,15 +20,17 @@ namespace IRaCIS.Core.Application.Filter
private readonly IUserInfo _userInfo; private readonly IUserInfo _userInfo;
private readonly IFusionCache _fusionCache; private readonly IFusionCache _fusionCache;
public IStringLocalizer _localizer; public IStringLocalizer _localizer;
private readonly List<string> _trialOptList=new List<string>(); private readonly IRepository<Trial> _trialRepository;
private readonly List<string> _trialOptList = new List<string>();
public TrialResourceFilter(IFusionCache fusionCache, IEasyCachingProvider provider, IStringLocalizer localizer , IUserInfo userInfo, string trialOpt = null, string trialOpt2 = null, string trialOpt3 = null) public TrialResourceFilter(IFusionCache fusionCache, IRepository<Trial> trialRepository, IEasyCachingProvider provider, IStringLocalizer localizer, IUserInfo userInfo, string trialOpt = null, string trialOpt2 = null, string trialOpt3 = null)
{ {
_fusionCache = fusionCache; _fusionCache = fusionCache;
_provider = provider; _provider = provider;
_userInfo = userInfo; _userInfo = userInfo;
_localizer = localizer; _localizer = localizer;
_trialRepository = trialRepository;
if (!string.IsNullOrWhiteSpace(trialOpt)) _trialOptList.Add(trialOpt.Trim()); if (!string.IsNullOrWhiteSpace(trialOpt)) _trialOptList.Add(trialOpt.Trim());
if (!string.IsNullOrWhiteSpace(trialOpt2)) _trialOptList.Add(trialOpt2.Trim()); if (!string.IsNullOrWhiteSpace(trialOpt2)) _trialOptList.Add(trialOpt2.Trim());
@ -44,7 +47,7 @@ namespace IRaCIS.Core.Application.Filter
#region 处理新的用户类型,不能操作项目相关接口 #region 处理新的用户类型,不能操作项目相关接口
// 后期列举出具体的类型,其他任何用户类型,都不允许操作 // 后期列举出具体的类型,其他任何用户类型,都不允许操作
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA && _userInfo.RequestUrl.ToLower()!= "TrialDocument/userConfirm".ToLower()) if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA && _userInfo.RequestUrl.ToLower() != "TrialDocument/userConfirm".ToLower())
{ {
//---对不起,您的账户没有操作权限。 //---对不起,您的账户没有操作权限。
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_NoAccessPermission"])); context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_NoAccessPermission"]));
@ -116,16 +119,16 @@ namespace IRaCIS.Core.Application.Filter
if (matchResult.Success) if (matchResult.Success)
{ {
//有可能匹配错误 "trialId":"","documentId":"b8180000-3e2c-0016-9fe0-08da33f96236" 从缓存里面验证下 //有可能匹配错误 "trialId":"","documentId":"b8180000-3e2c-0016-9fe0-08da33f96236" 从缓存里面验证下
var cacheResultDic = _provider.GetAll<string>(new[] { matchResult.Value });
var trialStatusStr = cacheResultDic[matchResult.Value.ToLower()].Value;
if (!string.IsNullOrWhiteSpace(trialStatusStr))
{
trialIdStr = matchResult.Value; trialIdStr = matchResult.Value;
var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
if (string.IsNullOrWhiteSpace(trialStatusStr))
{
//数据库 检查该项目Id不对
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
} }
} }
else else
{ {
@ -141,34 +144,12 @@ namespace IRaCIS.Core.Application.Filter
} }
//通过path 或者body 找到trialId 了 //通过path 或者body 找到trialId 了
if ( !string.IsNullOrWhiteSpace(trialIdStr)) if (!string.IsNullOrWhiteSpace(trialIdStr))
{ {
var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
//如果没缓存数据,可能定时任务没执行或者缓存丢失 在此重新缓存
if (_provider.GetCount() == 0)
{
var _trialRepository = context.HttpContext.RequestServices.GetService(typeof(IRepository<Trial>)) as IRepository<Trial>;
var list = _trialRepository.IfNullThrowException().Select(t => new { TrialId = t.Id, TrialStatusStr = t.TrialStatusStr })
.ToList();
list.ForEach(t => _provider.Set(t.TrialId.ToString(), t.TrialStatusStr, TimeSpan.FromDays(7)));
}
var cacheResultDic = _provider.GetAll<string>(new[] { trialIdStr });
var trialStatusStr = cacheResultDic[trialIdStr].Value;
//意外 导致缓存过期,调整服务器时间,测试不想重启程序
if (string.IsNullOrWhiteSpace(trialStatusStr))
{
var trialRepository = context.HttpContext.RequestServices.GetService(typeof(IRepository<Trial>)) as IRepository<Trial>;
trialStatusStr = trialRepository?.Where(t => t.Id == Guid.Parse(trialIdStr)).Select(t => t.TrialStatusStr).FirstOrDefault();
}
// 这里是统一拦截 项目有关的操作允许情况(特殊的地方比如项目配置有的在多种状态初始化ongoing都可以操作有的仅仅在Initializing还有 项目添加和更新,不走这里,特殊处理,不然在这里显得很乱,判断是哪个接口) // 这里是统一拦截 项目有关的操作允许情况(特殊的地方比如项目配置有的在多种状态初始化ongoing都可以操作有的仅仅在Initializing还有 项目添加和更新,不走这里,特殊处理,不然在这里显得很乱,判断是哪个接口)
if (trialStatusStr == StaticData.TrialState.TrialOngoing || _trialOptList.Any(t=>t== TrialOpt.BeforeOngoingCantOpt) ) if (trialStatusStr == StaticData.TrialState.TrialOngoing || _trialOptList.Any(t => t == TrialOpt.BeforeOngoingCantOpt))
{ {
await next.Invoke(); await next.Invoke();
@ -184,7 +165,7 @@ namespace IRaCIS.Core.Application.Filter
} }
//添加项目 签名系统文档的时候 不做拦截 但是更新项目 签名项目文档的时候需要拦截 //添加项目 签名系统文档的时候 不做拦截 但是更新项目 签名项目文档的时候需要拦截
else if (_trialOptList.Any(t => t == TrialOpt.AddOrUpdateTrial ||t ==TrialOpt.SignSystemDocNoTrialId)) else if (_trialOptList.Any(t => t == TrialOpt.AddOrUpdateTrial || t == TrialOpt.SignSystemDocNoTrialId))
{ {
await next.Invoke(); await next.Invoke();
} }

View File

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IRaCIS.Core.Application.Helper
{
public static class CacheKeys
{
public static string Trial(string trialIdStr) => $"TrialId:{trialIdStr}";
// 你可以为其他实体和模块定义更多的键
}
public static class CacheHelper
{
public static async Task<string?> GetTrialStatusAsync(Guid trialId, IRepository<Trial> _trialRepository)
{
var statusStr = await _trialRepository.Where(t => t.Id == trialId, ignoreQueryFilters: true).Select(t => t.TrialStatusStr).FirstOrDefaultAsync();
return statusStr;
}
}
}

View File

@ -23,6 +23,8 @@ using IRaCIS.Application.Contracts;
using SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors; using SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors;
using Newtonsoft.Json; using Newtonsoft.Json;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using IRaCIS.Core.Application.Helper;
using ZiggyCreatures.Caching.Fusion;
namespace IRaCIS.Core.Application namespace IRaCIS.Core.Application
{ {
@ -1239,7 +1241,7 @@ namespace IRaCIS.Core.Application
} }
await _provider.SetAsync(trialId.ToString(), trialStatusStr, TimeSpan.FromDays(7)); await _fusionCache.SetAsync(CacheKeys.Trial(trial.Id.ToString()), trialStatusStr, TimeSpan.FromDays(7));
await _repository.SaveChangesAsync(); await _repository.SaveChangesAsync();
@ -1390,7 +1392,7 @@ namespace IRaCIS.Core.Application
{ {
var trialCode = await _trialRepository.Where(t => t.Id == trialId).Select(t => t.TrialCode).FirstOrDefaultAsync(); var trialCode = await _trialRepository.Where(t => t.Id == trialId).Select(t => t.TrialCode).FirstOrDefaultAsync();
return new TrialPacsInfo() { Ip=optionsMonitor.CurrentValue.IP,Port=optionsMonitor.CurrentValue.Port,TrialCalledAE=$"EI{trialCode}" }; return new TrialPacsInfo() { Ip = optionsMonitor.CurrentValue.IP, Port = optionsMonitor.CurrentValue.Port, TrialCalledAE = $"EI{trialCode}" };
} }
} }
} }

View File

@ -12,6 +12,8 @@ using Microsoft.AspNetCore.Authorization;
using System.Linq.Expressions; using System.Linq.Expressions;
using System.Linq; using System.Linq;
using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Application.Helper;
using ZiggyCreatures.Caching.Fusion;
namespace IRaCIS.Application.Services namespace IRaCIS.Application.Services
{ {
@ -93,7 +95,7 @@ namespace IRaCIS.Application.Services
.WhereIf(multiCriteriaSelectCount > 0, t => t.TrialDicList.Count(t => t.KeyName == StaticData.Criterion) == multiCriteriaSelectCount) .WhereIf(multiCriteriaSelectCount > 0, t => t.TrialDicList.Count(t => t.KeyName == StaticData.Criterion) == multiCriteriaSelectCount)
.WhereIf(multiReviewTypeSelectCount > 0, t => t.TrialDicList.Count(t => t.KeyName == StaticData.ReviewType) == multiReviewTypeSelectCount) .WhereIf(multiReviewTypeSelectCount > 0, t => t.TrialDicList.Count(t => t.KeyName == StaticData.ReviewType) == multiReviewTypeSelectCount)
.WhereIf(_userInfo.UserTypeEnumInt != (int)UserTypeEnum.SuperAdmin, t => t.TrialUserList.Any(t => t.UserId == _userInfo.Id && t.IsDeleted == false) && t.IsDeleted == false) .WhereIf(_userInfo.UserTypeEnumInt != (int)UserTypeEnum.SuperAdmin, t => t.TrialUserList.Any(t => t.UserId == _userInfo.Id && t.IsDeleted == false) && t.IsDeleted == false)
.ProjectTo<TrialDetailDTO>(_mapper.ConfigurationProvider, new { userTypeEnumInt = _userInfo.UserTypeEnumInt, userId = _userInfo.Id , isEn_Us= _userInfo.IsEn_Us }); .ProjectTo<TrialDetailDTO>(_mapper.ConfigurationProvider, new { userTypeEnumInt = _userInfo.UserTypeEnumInt, userId = _userInfo.Id, isEn_Us = _userInfo.IsEn_Us });
return await query.ToPagedListAsync(searchParam.PageIndex, searchParam.PageSize, string.IsNullOrWhiteSpace(searchParam.SortField) ? "CreateTime" : searchParam.SortField, searchParam.Asc); return await query.ToPagedListAsync(searchParam.PageIndex, searchParam.PageSize, string.IsNullOrWhiteSpace(searchParam.SortField) ? "CreateTime" : searchParam.SortField, searchParam.Asc);
@ -119,7 +121,7 @@ namespace IRaCIS.Application.Services
[HttpGet("{projectId:guid}")] [HttpGet("{projectId:guid}")]
public async Task<TrialDetailDTO> GetTrialInfoAndLockState(Guid projectId) public async Task<TrialDetailDTO> GetTrialInfoAndLockState(Guid projectId)
{ {
return (await _trialRepository.Where(o => o.Id == projectId).ProjectTo<TrialDetailDTO>(_mapper.ConfigurationProvider, new {isEn_Us = _userInfo.IsEn_Us }).FirstOrDefaultAsync()).IfNullThrowException(); return (await _trialRepository.Where(o => o.Id == projectId).ProjectTo<TrialDetailDTO>(_mapper.ConfigurationProvider, new { isEn_Us = _userInfo.IsEn_Us }).FirstOrDefaultAsync()).IfNullThrowException();
} }
@ -216,7 +218,7 @@ namespace IRaCIS.Application.Services
await _repository.AddAsync(new TrialPaymentPrice() { TrialId = trial.Id }); await _repository.AddAsync(new TrialPaymentPrice() { TrialId = trial.Id });
//添加访视 //添加访视
await _repository.AddAsync(new VisitStage { TrialId = trial.Id, VisitNum = 0, BlindName = "B" + 0.ToString("D3"), VisitDay = 0, VisitName = "Baseline", IsBaseLine = true,VisitWindowLeft=-28,VisitWindowRight=0 }); await _repository.AddAsync(new VisitStage { TrialId = trial.Id, VisitNum = 0, BlindName = "B" + 0.ToString("D3"), VisitDay = 0, VisitName = "Baseline", IsBaseLine = true, VisitWindowLeft = -28, VisitWindowRight = 0 });
await _repository.AddAsync(new VisitStage { TrialId = trial.Id, VisitNum = 1, BlindName = "B" + 10.ToString("D3"), VisitDay = 30, VisitName = "Visit 1", VisitWindowLeft = -5, VisitWindowRight = 5 }); await _repository.AddAsync(new VisitStage { TrialId = trial.Id, VisitNum = 1, BlindName = "B" + 10.ToString("D3"), VisitDay = 30, VisitName = "Visit 1", VisitWindowLeft = -5, VisitWindowRight = 5 });
@ -236,10 +238,9 @@ namespace IRaCIS.Application.Services
} }
await _repository.AddRangeAsync(needAddBodyPartList,true); await _repository.AddRangeAsync(needAddBodyPartList, true);
await _fusionCache.SetAsync(CacheKeys.Trial(trial.Id.ToString()), StaticData.TrialState.TrialInitializing, TimeSpan.FromDays(7));
_provider.Set(trial.Id.ToString(), StaticData.TrialState.TrialInitializing, TimeSpan.FromDays(7));
return ResponseOutput.Ok(trial); return ResponseOutput.Ok(trial);
} }
@ -589,7 +590,7 @@ namespace IRaCIS.Application.Services
await _repository.BatchDeleteAsync<VisitTaskReReading>(t => t.OriginalReReadingTask.TrialId == trialId); await _repository.BatchDeleteAsync<VisitTaskReReading>(t => t.OriginalReReadingTask.TrialId == trialId);
await _repository.BatchDeleteAsync<VisitTask>(t => t.TrialId == trialId); await _repository.BatchDeleteAsync<VisitTask>(t => t.TrialId == trialId);
await _repository.BatchDeleteAsync<TrialStateChange>(t => t.TrialId == trialId) ; await _repository.BatchDeleteAsync<TrialStateChange>(t => t.TrialId == trialId);
return ResponseOutput.Ok(); return ResponseOutput.Ok();
@ -650,7 +651,7 @@ namespace IRaCIS.Application.Services
.WhereIf(!string.IsNullOrEmpty(searchModel.Code), o => o.TrialCode.Contains(searchModel.Code)) .WhereIf(!string.IsNullOrEmpty(searchModel.Code), o => o.TrialCode.Contains(searchModel.Code))
.WhereIf(!string.IsNullOrWhiteSpace(searchModel.Indication), o => o.Indication.Contains(searchModel.Indication)) .WhereIf(!string.IsNullOrWhiteSpace(searchModel.Indication), o => o.Indication.Contains(searchModel.Indication))
.WhereIf(_userInfo.UserTypeEnumInt != (int)UserTypeEnum.SuperAdmin, t => t.TrialUserList.Any(t => t.UserId == _userInfo.Id)) .WhereIf(_userInfo.UserTypeEnumInt != (int)UserTypeEnum.SuperAdmin, t => t.TrialUserList.Any(t => t.UserId == _userInfo.Id))
.ProjectTo<TrialDetailDTO>(_mapper.ConfigurationProvider, new { userTypeEnumInt = _userInfo.UserTypeEnumInt, userId = _userInfo.Id ,isEn_Us = _userInfo.IsEn_Us }); .ProjectTo<TrialDetailDTO>(_mapper.ConfigurationProvider, new { userTypeEnumInt = _userInfo.UserTypeEnumInt, userId = _userInfo.Id, isEn_Us = _userInfo.IsEn_Us });
return await query.ToPagedListAsync(searchModel.PageIndex, searchModel.PageSize, string.IsNullOrWhiteSpace(searchModel.SortField) ? "CreateTime" : searchModel.SortField, searchModel.Asc); return await query.ToPagedListAsync(searchModel.PageIndex, searchModel.PageSize, string.IsNullOrWhiteSpace(searchModel.SortField) ? "CreateTime" : searchModel.SortField, searchModel.Asc);