diff --git a/IRaCIS.Core.Application/BackGroundJob/IRaCISCHangfireJob.cs b/IRaCIS.Core.Application/BackGroundJob/IRaCISCHangfireJob.cs index 6317b4020..7e062a0f8 100644 --- a/IRaCIS.Core.Application/BackGroundJob/IRaCISCHangfireJob.cs +++ b/IRaCIS.Core.Application/BackGroundJob/IRaCISCHangfireJob.cs @@ -37,23 +37,24 @@ namespace IRaCIS.Application.Services.BackGroundJob { _logger.LogInformation("项目启动 hangfire 任务初始化 执行开始~"); - - //项目状态 立即加载到缓存中 - await MemoryCacheTrialStatusAsync(); - - //await MemoryCacheAnonymizeData(); - - - //创建项目缓存 定时任务 - HangfireJobHelper.AddOrUpdateInitCronJob("RecurringJob_Cache_TrialState", t => t.MemoryCacheTrialStatusAsync(), Cron.Daily()); - - //初始化 + //初始化国际化 await InternationalizationHelper.InitInternationlizationDataAndWatchJsonFileAsync(_internationalizationRepository); //创建邮件定时任务 await InitSysAndTrialCronJobAsync(); + #region 废弃 + ////项目状态 立即加载到缓存中 + //await MemoryCacheTrialStatusAsync(); + + ////await MemoryCacheAnonymizeData(); + + + ////创建项目缓存 定时任务 + //HangfireJobHelper.AddOrUpdateInitCronJob("RecurringJob_Cache_TrialState", t => t.MemoryCacheTrialStatusAsync(), Cron.Daily()); + #endregion + _logger.LogInformation("项目启动 hangfire 任务初始化 执行结束"); } diff --git a/IRaCIS.Core.Application/BaseService.cs b/IRaCIS.Core.Application/BaseService.cs index 00df0c376..1d87bdb1f 100644 --- a/IRaCIS.Core.Application/BaseService.cs +++ b/IRaCIS.Core.Application/BaseService.cs @@ -9,6 +9,7 @@ using Panda.DynamicWebApi.Attributes; using System.Diagnostics.CodeAnalysis; using IRaCIS.Core.Domain.Share; using Microsoft.AspNetCore.Mvc; +using ZiggyCreatures.Caching.Fusion; namespace IRaCIS.Core.Application { @@ -32,7 +33,7 @@ namespace IRaCIS.Core.Application public IWebHostEnvironment _hostEnvironment { get; set; } - + public IFusionCache _fusionCache { get; set; } public static IResponseOutput Null404NotFound(TEntity? businessObject) where TEntity : class @@ -60,6 +61,9 @@ namespace IRaCIS.Core.Application [MemberNotNull(nameof(_hostEnvironment))] public IWebHostEnvironment _hostEnvironment { get; set; } + [MemberNotNull(nameof(_fusionCache))] + public IFusionCache _fusionCache { get; set; } + } #endregion @@ -81,8 +85,9 @@ namespace IRaCIS.Core.Application [MemberNotNull(nameof(_localizer))] public IStringLocalizer _localizer { get; set; } + [MemberNotNull(nameof(_fusionCache))] + public IFusionCache _fusionCache { get; set; } - } [TypeFilter(typeof(UnifiedApiResultFilter))] @@ -97,6 +102,8 @@ namespace IRaCIS.Core.Application public IStringLocalizer _localizer { get; set; } + public IFusionCache _fusionCache { get; set; } + public static IResponseOutput Null404NotFound(TEntity? businessObject) where TEntity : class { return new ResponseOutput() diff --git a/IRaCIS.Core.Application/BusinessFilter/TrialResourceFilter.cs b/IRaCIS.Core.Application/BusinessFilter/TrialResourceFilter.cs index 7e0791122..683059714 100644 --- a/IRaCIS.Core.Application/BusinessFilter/TrialResourceFilter.cs +++ b/IRaCIS.Core.Application/BusinessFilter/TrialResourceFilter.cs @@ -1,4 +1,5 @@ using EasyCaching.Core; +using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Domain.Share; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; @@ -19,32 +20,34 @@ namespace IRaCIS.Core.Application.Filter private readonly IUserInfo _userInfo; private readonly IFusionCache _fusionCache; public IStringLocalizer _localizer; - private readonly List _trialOptList=new List(); + private readonly IRepository _trialRepository; + private readonly List _trialOptList = new List(); - public TrialResourceFilter(IFusionCache fusionCache, IEasyCachingProvider provider, IStringLocalizer localizer , IUserInfo userInfo, string trialOpt = null, string trialOpt2 = null, string trialOpt3 = null) + public TrialResourceFilter(IFusionCache fusionCache, IRepository trialRepository, IEasyCachingProvider provider, IStringLocalizer localizer, IUserInfo userInfo, string trialOpt = null, string trialOpt2 = null, string trialOpt3 = null) { _fusionCache = fusionCache; _provider = provider; _userInfo = userInfo; _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(trialOpt3)) _trialOptList.Add(trialOpt3.Trim()); - + } //优先选择异步的方法 public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next) { - // var typeFilter = context.ActionDescriptor.EndpointMetadata.Where(t => t.GetType() == typeof(TypeFilterAttribute)).Select(t => (TypeFilterAttribute)t).ToList().FirstOrDefault(); - //var _trialOptList= typeFilter.Arguments.Select(t => t.ToString()).ToList(); + // var typeFilter = context.ActionDescriptor.EndpointMetadata.Where(t => t.GetType() == typeof(TypeFilterAttribute)).Select(t => (TypeFilterAttribute)t).ToList().FirstOrDefault(); + //var _trialOptList= typeFilter.Arguments.Select(t => t.ToString()).ToList(); #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"])); @@ -85,7 +88,7 @@ namespace IRaCIS.Core.Application.Filter } else { - //---正则取请求Refer 中trialId 失败,请联系开发人员核查 + //---正则取请求Refer 中trialId 失败,请联系开发人员核查 context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"])); } @@ -116,20 +119,20 @@ namespace IRaCIS.Core.Application.Filter if (matchResult.Success) { //有可能匹配错误 "trialId":"","documentId":"b8180000-3e2c-0016-9fe0-08da33f96236" 从缓存里面验证下 - var cacheResultDic = _provider.GetAll(new[] { matchResult.Value }); - var trialStatusStr = cacheResultDic[matchResult.Value.ToLower()].Value; + trialIdStr = matchResult.Value; - if (!string.IsNullOrWhiteSpace(trialStatusStr)) + var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7)); + + if (string.IsNullOrWhiteSpace(trialStatusStr)) { - trialIdStr = matchResult.Value; + //数据库 检查该项目Id不对 + context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"])); } - - } else { - //---正则取请求Refer 中trialId 失败,请联系开发人员核查 + //---正则取请求Refer 中trialId 失败,请联系开发人员核查 context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"])); } @@ -141,34 +144,12 @@ namespace IRaCIS.Core.Application.Filter } //通过path 或者body 找到trialId 了 - if ( !string.IsNullOrWhiteSpace(trialIdStr)) + if (!string.IsNullOrWhiteSpace(trialIdStr)) { - - //如果没缓存数据,可能定时任务没执行或者缓存丢失 在此重新缓存 - if (_provider.GetCount() == 0) - { - - var _trialRepository = context.HttpContext.RequestServices.GetService(typeof(IRepository)) as IRepository; - - 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(new[] { trialIdStr }); - - var trialStatusStr = cacheResultDic[trialIdStr].Value; - - //意外 导致缓存过期,调整服务器时间,测试不想重启程序 - if (string.IsNullOrWhiteSpace(trialStatusStr)) - { - var trialRepository = context.HttpContext.RequestServices.GetService(typeof(IRepository)) as IRepository; - trialStatusStr = trialRepository?.Where(t => t.Id == Guid.Parse(trialIdStr)).Select(t => t.TrialStatusStr).FirstOrDefault(); - } + var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7)); // 这里是统一拦截 项目有关的操作允许情况(特殊的地方,比如项目配置(有的在多种状态(初始化,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(); @@ -177,14 +158,14 @@ namespace IRaCIS.Core.Application.Filter // 项目停止、或者完成 不允许操作 else { - //---本次请求被配置规则拦截:项目状态处于进行中时,才允许操作,若此处逻辑有误,请联系开发人员修改 + //---本次请求被配置规则拦截:项目状态处于进行中时,才允许操作,若此处逻辑有误,请联系开发人员修改 context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_InterceptedProjectStatusRule"])); } } //添加项目 签名系统文档的时候 不做拦截 但是更新项目 签名项目文档的时候需要拦截 - 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(); } diff --git a/IRaCIS.Core.Application/Helper/CacheHelper.cs b/IRaCIS.Core.Application/Helper/CacheHelper.cs new file mode 100644 index 000000000..9e0035e9e --- /dev/null +++ b/IRaCIS.Core.Application/Helper/CacheHelper.cs @@ -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 GetTrialStatusAsync(Guid trialId, IRepository _trialRepository) + { + var statusStr = await _trialRepository.Where(t => t.Id == trialId, ignoreQueryFilters: true).Select(t => t.TrialStatusStr).FirstOrDefaultAsync(); + + return statusStr; + } + } +} diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialConfigService.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialConfigService.cs index b130638a7..f80656e8f 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialConfigService.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialConfigService.cs @@ -23,6 +23,8 @@ using IRaCIS.Application.Contracts; using SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors; using Newtonsoft.Json; using Microsoft.Extensions.Options; +using IRaCIS.Core.Application.Helper; +using ZiggyCreatures.Caching.Fusion; namespace IRaCIS.Core.Application { @@ -1239,8 +1241,8 @@ 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(); return ResponseOutput.Ok(); @@ -1390,7 +1392,7 @@ namespace IRaCIS.Core.Application { 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}" }; } } } diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialService.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialService.cs index 190511173..7534c3860 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialService.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialService.cs @@ -12,6 +12,8 @@ using Microsoft.AspNetCore.Authorization; using System.Linq.Expressions; using System.Linq; using IRaCIS.Core.Domain.Models; +using IRaCIS.Core.Application.Helper; +using ZiggyCreatures.Caching.Fusion; 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(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) - .ProjectTo(_mapper.ConfigurationProvider, new { userTypeEnumInt = _userInfo.UserTypeEnumInt, userId = _userInfo.Id , isEn_Us= _userInfo.IsEn_Us }); + .ProjectTo(_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); @@ -119,7 +121,7 @@ namespace IRaCIS.Application.Services [HttpGet("{projectId:guid}")] public async Task GetTrialInfoAndLockState(Guid projectId) { - return (await _trialRepository.Where(o => o.Id == projectId).ProjectTo(_mapper.ConfigurationProvider, new {isEn_Us = _userInfo.IsEn_Us }).FirstOrDefaultAsync()).IfNullThrowException(); + return (await _trialRepository.Where(o => o.Id == projectId).ProjectTo(_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 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 }); @@ -234,12 +236,11 @@ namespace IRaCIS.Application.Services { item.TrialId = trial.Id; } - - - await _repository.AddRangeAsync(needAddBodyPartList,true); - _provider.Set(trial.Id.ToString(), StaticData.TrialState.TrialInitializing, TimeSpan.FromDays(7)); + await _repository.AddRangeAsync(needAddBodyPartList, true); + + await _fusionCache.SetAsync(CacheKeys.Trial(trial.Id.ToString()), StaticData.TrialState.TrialInitializing, TimeSpan.FromDays(7)); return ResponseOutput.Ok(trial); } @@ -589,7 +590,7 @@ namespace IRaCIS.Application.Services await _repository.BatchDeleteAsync(t => t.OriginalReReadingTask.TrialId == trialId); await _repository.BatchDeleteAsync(t => t.TrialId == trialId); - await _repository.BatchDeleteAsync(t => t.TrialId == trialId) ; + await _repository.BatchDeleteAsync(t => t.TrialId == trialId); return ResponseOutput.Ok(); @@ -650,7 +651,7 @@ namespace IRaCIS.Application.Services .WhereIf(!string.IsNullOrEmpty(searchModel.Code), o => o.TrialCode.Contains(searchModel.Code)) .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)) - .ProjectTo(_mapper.ConfigurationProvider, new { userTypeEnumInt = _userInfo.UserTypeEnumInt, userId = _userInfo.Id ,isEn_Us = _userInfo.IsEn_Us }); + .ProjectTo(_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);