diff --git a/IRaCIS.Core.API/IRaCIS.Core.API.csproj b/IRaCIS.Core.API/IRaCIS.Core.API.csproj
index 70da0d235..988372377 100644
--- a/IRaCIS.Core.API/IRaCIS.Core.API.csproj
+++ b/IRaCIS.Core.API/IRaCIS.Core.API.csproj
@@ -69,6 +69,10 @@
+
+
+
+
diff --git a/IRaCIS.Core.API/Startup.cs b/IRaCIS.Core.API/Startup.cs
index f19961aed..498b34c37 100644
--- a/IRaCIS.Core.API/Startup.cs
+++ b/IRaCIS.Core.API/Startup.cs
@@ -29,6 +29,7 @@ using IRaCIS.Core.Application.Helper;
using Microsoft.AspNetCore.Http;
using Autofac.Core;
using DocumentFormat.OpenXml.InkML;
+using EasyCaching.Core;
namespace IRaCIS.Core.API
{
@@ -114,7 +115,7 @@ namespace IRaCIS.Core.API
// MediatR 进程内消息 事件解耦 从程序集中 注册命令和handler对应关系
services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining());
// EasyCaching 缓存
- services.AddEasyCachingSetup();
+ services.AddEasyCachingSetup(_configuration);
//services.AddDistributedMemoryCache();
diff --git a/IRaCIS.Core.API/_ServiceExtensions/EFSetup.cs b/IRaCIS.Core.API/_ServiceExtensions/EFSetup.cs
index 2f2890712..6c679d676 100644
--- a/IRaCIS.Core.API/_ServiceExtensions/EFSetup.cs
+++ b/IRaCIS.Core.API/_ServiceExtensions/EFSetup.cs
@@ -1,8 +1,12 @@
-锘縰sing IRaCIS.Core.Application.Triggers;
+锘縰sing Hangfire.SqlServer;
+using IRaCIS.Core.Application.Triggers;
using IRaCIS.Core.Infra.EFCore;
+using Medallion.Threading;
+using Medallion.Threading.SqlServer;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
+using StackExchange.Redis;
namespace IRaCIS.Core.API
{
@@ -52,6 +56,13 @@ namespace IRaCIS.Core.API
});
+ //娉ㄦ剰鍖哄垎 easy caching 涔熸湁 IDistributedLockProvider
+ services.AddSingleton(sp =>
+ {
+ //var connection = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!);
+
+ return new SqlDistributedSynchronizationProvider(configuration.GetSection("ConnectionStrings:RemoteNew").Value);
+ });
//services.AddAssemblyTriggers(typeof(SubjectVisitImageDateTrigger).Assembly);
}
diff --git a/IRaCIS.Core.API/_ServiceExtensions/EasyCachingSetup.cs b/IRaCIS.Core.API/_ServiceExtensions/EasyCachingSetup.cs
index 7d7a28c6a..63be01d92 100644
--- a/IRaCIS.Core.API/_ServiceExtensions/EasyCachingSetup.cs
+++ b/IRaCIS.Core.API/_ServiceExtensions/EasyCachingSetup.cs
@@ -1,17 +1,26 @@
锘縰sing EasyCaching.Core;
+using EasyCaching.Core.Configurations;
using EasyCaching.Interceptor.Castle;
+using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace IRaCIS.Core.API
{
public static class EasyCachingSetup
{
- public static void AddEasyCachingSetup(this IServiceCollection services)
+ public static void AddEasyCachingSetup(this IServiceCollection services, IConfiguration configuration)
{
services.AddEasyCaching(options =>
{
options.UseInMemory();
+
+ //options.UseRedis(configuration, EasyCachingConstValue.DefaultRedisName).WithMessagePack(EasyCachingConstValue.DefaultRedisName);
+
+
});
+
+ //services.ConfigureCastleInterceptor(options => options.CacheProviderName = EasyCachingConstValue.DefaultRedisName);
+
services.ConfigureCastleInterceptor(options => options.CacheProviderName = EasyCachingConstValue.DefaultInMemoryName);
}
}
diff --git a/IRaCIS.Core.API/appsettings.json b/IRaCIS.Core.API/appsettings.json
index a773c1174..dee559b4c 100644
--- a/IRaCIS.Core.API/appsettings.json
+++ b/IRaCIS.Core.API/appsettings.json
@@ -57,6 +57,26 @@
"EnableReadDeepClone": true,
"EnableWriteDeepClone": false
}
+ },
+ "redis": {
+ "MaxRdSecond": 120,
+ "EnableLogging": false,
+ "LockMs": 5000,
+ "SleepMs": 300,
+ "dbconfig": {
+ "Password": "xc@123456",
+ "IsSsl": false,
+ "SslHost": null,
+ "ConnectionTimeout": 5000,
+ "AllowAdmin": true,
+ "Endpoints": [
+ {
+ "Host": "47.117.164.182",
+ "Port": 6379
+ }
+ ],
+ "Database": 0
+ }
}
},
"IRaCISImageStore": {
diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj b/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj
index 929eca75b..076870710 100644
--- a/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj
+++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj
@@ -65,7 +65,11 @@
-
+
+
+
+
+
@@ -93,12 +97,12 @@
true
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/IRaCIS.Core.Application/Service/Common/MailService.cs b/IRaCIS.Core.Application/Service/Common/MailService.cs
index 2a4e0bb2d..d821708b6 100644
--- a/IRaCIS.Core.Application/Service/Common/MailService.cs
+++ b/IRaCIS.Core.Application/Service/Common/MailService.cs
@@ -6,7 +6,6 @@ using Microsoft.AspNetCore.Hosting;
using IRaCIS.Core.Application.Auth;
using AutoMapper;
using IRaCIS.Application.Contracts;
-using Nito.AsyncEx;
using Microsoft.Extensions.Options;
namespace IRaCIS.Application.Services
@@ -55,7 +54,6 @@ namespace IRaCIS.Application.Services
- private readonly AsyncLock _mutex = new AsyncLock();
private readonly SystemEmailSendConfig _systemEmailConfig;
diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/DicomArchiveService.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/DicomArchiveService.cs
index 5b1115177..f34ac28db 100644
--- a/IRaCIS.Core.Application/Service/ImageAndDoc/DicomArchiveService.cs
+++ b/IRaCIS.Core.Application/Service/ImageAndDoc/DicomArchiveService.cs
@@ -9,10 +9,11 @@ using Microsoft.AspNetCore.Hosting;
using IRaCIS.Core.Infrastructure;
using FellowOakDicom;
using FellowOakDicom.Imaging.Codec;
+using Medallion.Threading;
namespace IRaCIS.Core.Application.Services
{
- public class DicomArchiveService :BaseService, IDicomArchiveService
+ public class DicomArchiveService : BaseService, IDicomArchiveService
{
private readonly IRepository _studyRepository;
private readonly IRepository _seriesRepository;
@@ -22,7 +23,7 @@ namespace IRaCIS.Core.Application.Services
private readonly IWebHostEnvironment _hostEnvironment;
- private static object lockCodeGenerate = new object();
+ private readonly IDistributedLockProvider _distributedLockProvider;
private List _instanceIdList = new List();
@@ -32,8 +33,9 @@ namespace IRaCIS.Core.Application.Services
IRepository instanceRepository,
IWebHostEnvironment hostEnvironment,
IRepository dictionaryRepository,
- IEasyCachingProvider provider)
+ IEasyCachingProvider provider, IDistributedLockProvider distributedLockProvider)
{
+ _distributedLockProvider = distributedLockProvider;
_hostEnvironment = hostEnvironment;
_studyRepository = studyRepository;
@@ -51,7 +53,7 @@ namespace IRaCIS.Core.Application.Services
return success;
}
-
+
public async Task<(Guid StudyId, string StudyCode)> ArchiveDicomStreamAsync(Stream dicomStream,
@@ -130,7 +132,7 @@ namespace IRaCIS.Core.Application.Services
DicomStudy dicomStudy = CreateDicomStudy(dataset, addtionalInfo, out bool isStudyNeedAdd);
DicomSeries dicomSeries = CreateDicomSeries(dataset, dicomStudy, out bool isSeriesNeedAdd);
- DicomInstance dicomInstance = CreateDicomInstance(dataset, dicomStudy, dicomSeries,out bool isInstanceNeedAdd);
+ DicomInstance dicomInstance = CreateDicomInstance(dataset, dicomStudy, dicomSeries, out bool isInstanceNeedAdd);
dicomSeries.DicomStudy = dicomStudy;
@@ -184,7 +186,7 @@ namespace IRaCIS.Core.Application.Services
//姝e父淇濆瓨 涓嶅仛澶勭悊
await dicomFile.SaveAsync(physicalPath);
}
- else
+ else
{
//RLELossless 淇濆瓨
await dicomFile.Clone(DicomTransferSyntax.RLELossless).SaveAsync(physicalPath); //RLELossless
@@ -236,7 +238,7 @@ namespace IRaCIS.Core.Application.Services
{
modalityForEdit = "PET";
}
- if(modality== "PT銆丆T")
+ if (modality == "PT銆丆T")
{
modalityForEdit = "PET-CT";
}
@@ -283,9 +285,10 @@ namespace IRaCIS.Core.Application.Services
dicomStudy.PatientBirthDate = $"{dicomStudy.PatientBirthDate[0]}{dicomStudy.PatientBirthDate[1]}{dicomStudy.PatientBirthDate[2]}{dicomStudy.PatientBirthDate[3]}-{dicomStudy.PatientBirthDate[4]}{dicomStudy.PatientBirthDate[5]}-{dicomStudy.PatientBirthDate[6]}{dicomStudy.PatientBirthDate[7]}";
}
- lock (lockCodeGenerate)
- {
+ var @lock = _distributedLockProvider.CreateLock($"StudyCode");
+ using (@lock.Acquire())
+ {
//鏌ヨ鏁版嵁搴撹幏鍙栨渶澶х殑Code 娌℃湁璁板綍鍒欎负0
var dbStudyCodeIntMax = _studyRepository.Where(s => s.TrialId == addtionalInfo.TrialId).Select(t => t.Code).DefaultIfEmpty().Max();
@@ -299,9 +302,9 @@ namespace IRaCIS.Core.Application.Services
dicomStudy.StudyCode = AppSettings.GetCodeStr(currentNextCodeInt, nameof(DicomStudy));
_provider.Set($"{addtionalInfo.TrialId}_{StaticData.CacheKey.StudyMaxCode}", dicomStudy.Code, TimeSpan.FromMinutes(30));
-
}
+
#region Setting Code old
//var studyCode = _studyRepository.Where(s => s.TrialId == addtionalInfo.TrialId).Select(t => t.StudyCode).OrderByDescending(c => c).FirstOrDefault();
@@ -469,7 +472,7 @@ namespace IRaCIS.Core.Application.Services
_instanceIdList.Add(instanceId);
}
-
+
return dicomInstance;
}
diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs
index 173c643f1..adb1f224a 100644
--- a/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs
+++ b/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs
@@ -14,16 +14,13 @@ using IRaCIS.Core.Application.MediatR.Handlers;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using System.Threading;
-using Nito.AsyncEx;
+using Medallion.Threading;
namespace IRaCIS.Core.Application.Service.ImageAndDoc
{
[ApiExplorerSettings(GroupName = "Image")]
public class StudyService : BaseService, IStudyService
{
- private static object lockObj = new object();
- private static readonly AsyncLock _mutex = new AsyncLock();
- private static readonly AsyncLock _mutex2 = new AsyncLock();
private readonly IEasyCachingProvider _provider;
@@ -35,12 +32,12 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
private readonly IRepository _dictionaryRepository;
private readonly IRepository _studyMonitorRepository;
-
+ private readonly IDistributedLockProvider _distributedLockProvider;
public StudyService(IEasyCachingProvider provider
, IRepository subjectVisitRepository,
IRepository dicomInstanceRepository,
- IRepository dicomSeriesRepository, IRepository dicomstudyRepository, IRepository dictionaryRepository, IRepository studyMonitorRepository)
+ IRepository dicomSeriesRepository, IRepository dicomstudyRepository, IRepository dictionaryRepository, IRepository studyMonitorRepository, IDistributedLockProvider distributedLockProvider)
{
_provider = provider;
_subjectVisitRepository = subjectVisitRepository;
@@ -49,6 +46,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
_dicomstudyRepository = dicomstudyRepository;
_dictionaryRepository = dictionaryRepository;
_studyMonitorRepository = studyMonitorRepository;
+ _distributedLockProvider = distributedLockProvider;
}
@@ -160,7 +158,9 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
{
var study = _mapper.Map(incommand.Study);
- using (await _mutex.LockAsync())
+ var @lock = _distributedLockProvider.CreateLock($"StudyCode");
+
+ using (await @lock.AcquireAsync())
{
//鏌ヨ鏁版嵁搴撹幏鍙栨渶澶х殑Code 娌℃湁璁板綍鍒欎负0
var dbStudyCodeIntMax = _dicomstudyRepository.Where(s => s.TrialId == trialId).Select(t => t.Code).DefaultIfEmpty().Max();
@@ -306,11 +306,11 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
}
- using (await _mutex2.LockAsync())
+ var @lock2 = _distributedLockProvider.CreateLock($"StudyCommit");
+
+ using (await @lock2.AcquireAsync())
{
await _dicomInstanceRepository.SaveChangesAsync();
-
-
}
}
catch (Exception ex)
@@ -765,7 +765,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
if (_provider.Exists($"StudyUid_{trialId}_{studyInstanceUid}"))
{
-
+
result.AllowUpload = false;
result.AllowReUpload = false;
@@ -826,22 +826,22 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
}
result.StudyInstanceUid = studyInstanceUid;
+ var @lock = _distributedLockProvider.CreateLock($"StudyUpload");
- if (result.AllowReUpload || result.AllowUpload)
+ using (@lock.Acquire())
{
- lock (lockObj)
+ if (result.AllowReUpload || result.AllowUpload)
{
_provider.Set($"StudyUid_{trialId}_{studyInstanceUid}", _userInfo.Id, TimeSpan.FromSeconds(30));
}
- }
- else
- {
- lock (lockObj)
+ else
{
_provider.Remove($"StudyUid_{trialId}_{studyInstanceUid}");
}
}
+
+
return result;
}
diff --git a/IRaCIS.Core.Application/Service/Institution/SiteService.cs b/IRaCIS.Core.Application/Service/Institution/SiteService.cs
index 137d4ffd0..b65b2379f 100644
--- a/IRaCIS.Core.Application/Service/Institution/SiteService.cs
+++ b/IRaCIS.Core.Application/Service/Institution/SiteService.cs
@@ -3,7 +3,7 @@ using IRaCIS.Application.Contracts;
using IRaCIS.Core.Infra.EFCore;
using Microsoft.AspNetCore.Mvc;
using IRaCIS.Core.Domain.Share;
-using Nito.AsyncEx;
+using Medallion.Threading;
namespace IRaCIS.Application.Services
{
@@ -12,13 +12,13 @@ namespace IRaCIS.Application.Services
{
private readonly IRepository _siteRepository;
private readonly IRepository _trialSiteUserRepository;
+ private readonly IDistributedLockProvider _distributedLockProvider;
- private readonly AsyncLock _mutex = new AsyncLock();
-
- public SiteService(IRepository siteRepository, IRepository trialSiteUserRepository)
+ public SiteService(IRepository siteRepository, IRepository trialSiteUserRepository, IDistributedLockProvider distributedLockProvider)
{
_siteRepository = siteRepository;
- this._trialSiteUserRepository = trialSiteUserRepository;
+ _trialSiteUserRepository = trialSiteUserRepository;
+ _distributedLockProvider = distributedLockProvider;
}
/// 鍒嗛〉鑾峰彇鐮旂┒涓績鍒楄〃
@@ -27,7 +27,7 @@ namespace IRaCIS.Application.Services
{
var siteQueryable = _siteRepository
- .WhereIf(!string.IsNullOrWhiteSpace(searchModel.SiteName), t => t.SiteName.Contains(searchModel.SiteName)||t.SiteNameCN.Contains(searchModel.SiteName))
+ .WhereIf(!string.IsNullOrWhiteSpace(searchModel.SiteName), t => t.SiteName.Contains(searchModel.SiteName) || t.SiteNameCN.Contains(searchModel.SiteName))
.WhereIf(!string.IsNullOrWhiteSpace(searchModel.AliasName), t => t.AliasName.Contains(searchModel.AliasName))
.WhereIf(!string.IsNullOrWhiteSpace(searchModel.City), t => t.City.Contains(searchModel.City))
.WhereIf(!string.IsNullOrWhiteSpace(searchModel.Country), t => t.Country.Contains(searchModel.Country))
@@ -58,7 +58,9 @@ namespace IRaCIS.Application.Services
VerifyMsg = _localizer["Site_DupName"]
};
- using (await _mutex.LockAsync())
+ var @lock = _distributedLockProvider.CreateLock($"SiteAdd");
+
+ using (await @lock.AcquireAsync())
{
if (siteCommand.Id == null)
{
diff --git a/IRaCIS.Core.Application/Service/Management/UserService.cs b/IRaCIS.Core.Application/Service/Management/UserService.cs
index 32df5fa15..b36859015 100644
--- a/IRaCIS.Core.Application/Service/Management/UserService.cs
+++ b/IRaCIS.Core.Application/Service/Management/UserService.cs
@@ -12,6 +12,7 @@ using IRaCIS.Core.Infra.Common.Cache;
using Microsoft.Identity.Client;
using static IRaCIS.Core.Domain.Share.StaticData;
using IRaCIS.Core.Application.ViewModel;
+using Medallion.Threading;
namespace IRaCIS.Application.Services
{
@@ -24,7 +25,7 @@ namespace IRaCIS.Application.Services
private readonly IRepository _userTrialRepository;
private readonly IRepository _userLogRepository;
-
+ private readonly IDistributedLockProvider _distributedLockProvider;
private readonly IMemoryCache _cache;
private readonly IOptionsMonitor _verifyConfig;
@@ -38,7 +39,8 @@ namespace IRaCIS.Application.Services
IRepository userTrialRepository,
IOptionsMonitor verifyConfig,
IRepository userLogRepository
- )
+,
+ IDistributedLockProvider distributedLockProvider)
{
_userLogRepository = userLogRepository;
@@ -47,9 +49,10 @@ namespace IRaCIS.Application.Services
_userRepository = userRepository;
_mailVerificationService = mailVerificationService;
_verificationCodeRepository = verificationCodeRepository;
-
+
_userTrialRepository = userTrialRepository;
_userLogRepository = userLogRepository;
+ _distributedLockProvider = distributedLockProvider;
}
@@ -502,29 +505,32 @@ namespace IRaCIS.Application.Services
var saveItem = _mapper.Map(userAddModel);
- saveItem.Code = await _userRepository.Select(t => t.Code).DefaultIfEmpty().MaxAsync() + 1;
+ var @lock = _distributedLockProvider.CreateLock($"UserAccount");
- saveItem.UserCode = AppSettings.GetCodeStr(saveItem.Code, nameof(User));
-
- if (saveItem.IsZhiZhun)
+ using (await @lock.AcquireAsync())
{
- saveItem.OrganizationName = AppSettings.DefaultInternalOrganizationName;
+ saveItem.Code = await _userRepository.Select(t => t.Code).DefaultIfEmpty().MaxAsync() + 1;
+
+ saveItem.UserCode = AppSettings.GetCodeStr(saveItem.Code, nameof(User));
+
+ if (saveItem.IsZhiZhun)
+ {
+ saveItem.OrganizationName = AppSettings.DefaultInternalOrganizationName;
+ }
+
+
+ saveItem.Password = MD5Helper.Md5("123456");
+
+ await _userRepository.AddAsync(saveItem);
+
+ var success = await _userRepository.SaveChangesAsync();
}
-
- saveItem.Password = MD5Helper.Md5("123456");
-
- await _userRepository.AddAsync(saveItem);
-
- var success = await _userRepository.SaveChangesAsync();
-
-
+
await _mailVerificationService.AddUserSendEmailAsync(saveItem.Id, userAddModel.BaseUrl, userAddModel.RouteUrl);
-
-
- return ResponseOutput.Result(success, new UserAddedReturnDTO { Id = saveItem.Id, UserCode = saveItem.UserCode });
+ return ResponseOutput.Ok( new UserAddedReturnDTO { Id = saveItem.Id, UserCode = saveItem.UserCode });
}
diff --git a/IRaCIS.Core.Application/Service/QC/NoneDicomStudyService.cs b/IRaCIS.Core.Application/Service/QC/NoneDicomStudyService.cs
index fa912838f..e6a40c3bf 100644
--- a/IRaCIS.Core.Application/Service/QC/NoneDicomStudyService.cs
+++ b/IRaCIS.Core.Application/Service/QC/NoneDicomStudyService.cs
@@ -5,10 +5,10 @@
//--------------------------------------------------------------------
using Microsoft.AspNetCore.Mvc;
using IRaCIS.Core.Application.Filter;
-using Nito.AsyncEx;
using System.ComponentModel.DataAnnotations;
using IRaCIS.Core.Application.Service;
using IRaCIS.Core.Domain.Share;
+using Medallion.Threading;
namespace IRaCIS.Core.Application.Contracts
{
@@ -20,19 +20,19 @@ namespace IRaCIS.Core.Application.Contracts
{
private readonly IRepository _noneDicomStudyRepository;
private readonly IRepository _noneDicomStudyFileRepository;
- private readonly AsyncLock _mutex = new AsyncLock();
+ private readonly IDistributedLockProvider _distributedLockProvider;
private readonly QCCommon _qCCommon;
public NoneDicomStudyService(IRepository noneDicomStudyRepository,
QCCommon qCCommon,
- IRepository noneDicomStudyFileRepository)
+ IRepository noneDicomStudyFileRepository, IDistributedLockProvider distributedLockProvider)
{
_qCCommon = qCCommon;
_noneDicomStudyRepository = noneDicomStudyRepository;
_noneDicomStudyFileRepository = noneDicomStudyFileRepository;
-
+ _distributedLockProvider = distributedLockProvider;
}
@@ -62,7 +62,9 @@ namespace IRaCIS.Core.Application.Contracts
}
NoneDicomStudy? optEntity = null;
- using (await _mutex.LockAsync())
+ var @lock = _distributedLockProvider.CreateLock($"NoneDicomCode");
+
+ using (await @lock.AcquireAsync())
{
if (addOrEditNoneDicomStudy.Id == Guid.Empty || addOrEditNoneDicomStudy.Id == null)
{
diff --git a/IRaCIS.Core.Application/Service/QC/QCOperationService.cs b/IRaCIS.Core.Application/Service/QC/QCOperationService.cs
index 0e905e2f8..5f8e7e621 100644
--- a/IRaCIS.Core.Application/Service/QC/QCOperationService.cs
+++ b/IRaCIS.Core.Application/Service/QC/QCOperationService.cs
@@ -10,13 +10,13 @@ using WinSCP;
using Newtonsoft.Json;
using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Application.Service.Inspection.DTO;
-using Nito.AsyncEx;
using System.ComponentModel.DataAnnotations;
using IRaCIS.Core.Application.Auth;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Application.Service;
+using Medallion.Threading;
namespace IRaCIS.Core.Application.Image.QA
{
@@ -35,8 +35,7 @@ namespace IRaCIS.Core.Application.Image.QA
private readonly IRepository _trialRepository;
private readonly IRepository _visitTaskRepository;
private readonly IVisitTaskHelpeService _IVisitTaskHelpeService;
-
- private readonly AsyncLock _mutex = new AsyncLock();
+ private readonly IDistributedLockProvider _distributedLockProvider;
public QCOperationService(IRepository subjectVisitRepository,
IRepository qcChallengeRepository,
@@ -48,7 +47,8 @@ namespace IRaCIS.Core.Application.Image.QA
IRepository readingClinicalDataRepository,
IRepository qCChallengeDialogrepository,
IRepository checkChallengeDialogrepository,
- IVisitTaskHelpeService visitTaskHelpeService
+ IVisitTaskHelpeService visitTaskHelpeService,
+ IDistributedLockProvider distributedLockProvider
)
{
_subjectVisitRepository = subjectVisitRepository;
@@ -62,6 +62,7 @@ namespace IRaCIS.Core.Application.Image.QA
_trialRepository = trialRepository;
this._visitTaskRepository = visitTaskRepository;
_IVisitTaskHelpeService = visitTaskHelpeService;
+ _distributedLockProvider = distributedLockProvider;
}
#region QC璐ㄧ枒 浠ュ強鍥炲 鍏抽棴
@@ -108,9 +109,9 @@ namespace IRaCIS.Core.Application.Image.QA
var trialConfig = (await _trialRepository.Where(t => t.Id == trialId).Select(t => new { TrialId = t.Id, t.QCProcessEnum, t.IsImageConsistencyVerification }).FirstOrDefaultAsync()).IfNullThrowException();
+ var @lock = _distributedLockProvider.CreateLock($"QCChallengeCode");
-
- using (await _mutex.LockAsync())
+ using (await @lock.AcquireAsync())
{
//鑾峰彇缂栧彿
var code = _qcChallengeRepository.Where(t => t.TrialId == trialId).Select(t => t.Code).DefaultIfEmpty().Max();
diff --git a/IRaCIS.Core.Application/Service/SiteSurvey/TrialSiteSurveyService.cs b/IRaCIS.Core.Application/Service/SiteSurvey/TrialSiteSurveyService.cs
index 29bcead40..e5c673fbd 100644
--- a/IRaCIS.Core.Application/Service/SiteSurvey/TrialSiteSurveyService.cs
+++ b/IRaCIS.Core.Application/Service/SiteSurvey/TrialSiteSurveyService.cs
@@ -20,6 +20,7 @@ using Microsoft.VisualBasic;
using DocumentFormat.OpenXml.Spreadsheet;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Application.ViewModel;
+using Medallion.Threading;
namespace IRaCIS.Core.Application.Contracts
{
@@ -35,13 +36,14 @@ namespace IRaCIS.Core.Application.Contracts
private readonly IRepository _trialSiteRepository;
private readonly IRepository _trialUserRepository;
private readonly IRepository _trialSiteUserRepository;
+ private readonly IDistributedLockProvider _distributedLockProvider;
private readonly ITokenService _tokenService;
private readonly IMailVerificationService _mailVerificationService;
public TrialSiteSurveyService(IRepository trialSiteSurveyRepository, IRepository trialUserRepository, IRepository trialSiteUserSurveyRepository,
IRepository userRepository, IRepository trialSiteRepository,
ITokenService tokenService,
- IMailVerificationService mailVerificationService, IRepository trialSiteUserRepository)
+ IMailVerificationService mailVerificationService, IRepository trialSiteUserRepository, IDistributedLockProvider distributedLockProvider)
{
_trialSiteSurveyRepository = trialSiteSurveyRepository;
_trialSiteUserSurveyRepository = trialSiteUserSurveyRepository;
@@ -51,9 +53,9 @@ namespace IRaCIS.Core.Application.Contracts
_tokenService = tokenService;
_mailVerificationService = mailVerificationService;
_trialSiteUserRepository = trialSiteUserRepository;
+ _distributedLockProvider = distributedLockProvider;
}
- private object lockObj { get; set; } = new object();
///
/// 鍙戦侀獙璇佺爜
@@ -791,7 +793,9 @@ namespace IRaCIS.Core.Application.Contracts
if (sysUserInfo == null)
{
- lock (lockObj)
+ var @lock = _distributedLockProvider.CreateLock($"UserCode");
+
+ using (await @lock.AcquireAsync())
{
var saveItem = _mapper.Map(item);
@@ -971,7 +975,9 @@ namespace IRaCIS.Core.Application.Contracts
if (sysUserInfo == null)
{
- lock (lockObj)
+ var @lock = _distributedLockProvider.CreateLock($"UserCode");
+
+ using (await @lock.AcquireAsync())
{
var saveItem = _mapper.Map(item);
diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialExternalUserService.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialExternalUserService.cs
index 6bf00a16e..96704f954 100644
--- a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialExternalUserService.cs
+++ b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialExternalUserService.cs
@@ -16,6 +16,7 @@ using Panda.DynamicWebApi.Attributes;
using IRaCIS.Core.Application.Auth;
using IRaCIS.Application.Services;
using IRaCIS.Core.Application.Filter;
+using Medallion.Threading;
namespace IRaCIS.Core.Application.Service
{
@@ -31,10 +32,11 @@ namespace IRaCIS.Core.Application.Service
private readonly IRepository _trialSiteSurveyUserRepository;
private readonly IRepository _trialSiteUserRepository;
private readonly IMailVerificationService _mailVerificationService;
+ private readonly IDistributedLockProvider _distributedLockProvider;
public TrialExternalUserService(IRepository trialExternalUseRepository, IRepository userRepository, IRepository trialUserRepository,
IRepository trialSiteSurveyUserRepository, IRepository trialSiteUserRepository,
- IMailVerificationService mailVerificationService)
+ IMailVerificationService mailVerificationService, IDistributedLockProvider distributedLockProvider)
{
_trialExternalUseRepository = trialExternalUseRepository;
_userRepository = userRepository;
@@ -43,6 +45,7 @@ namespace IRaCIS.Core.Application.Service
_trialSiteUserRepository = trialSiteUserRepository;
_mailVerificationService = mailVerificationService;
+ _distributedLockProvider = distributedLockProvider;
}
@@ -75,121 +78,125 @@ namespace IRaCIS.Core.Application.Service
if (addOrEditTrialExternalUser.Id == null)
{
- var existSysUser = await _userRepository.FirstOrDefaultAsync(t => t.EMail == addOrEditTrialExternalUser.Email && t.UserTypeId == addOrEditTrialExternalUser.UserTypeId);
+ var @lock = _distributedLockProvider.CreateLock($"UserCode");
- if (existSysUser != null)
+ using (await @lock.AcquireAsync())
{
- if (existSysUser.LastName != addOrEditTrialExternalUser.LastName || existSysUser.FirstName != addOrEditTrialExternalUser.FirstName)
+ var existSysUser = await _userRepository.FirstOrDefaultAsync(t => t.EMail == addOrEditTrialExternalUser.Email && t.UserTypeId == addOrEditTrialExternalUser.UserTypeId);
+
+ if (existSysUser != null)
{
- //$"璇ョ敤鎴峰湪绯荤粺涓殑鐢ㄦ埛鍚嶄负锛歿existSysUser.LastName + " / " + existSysUser.FirstName} 鐢佃瘽锛歿existSysUser.Phone}锛屼笌濉啓淇℃伅瀛樺湪涓嶄竴鑷撮」, 璇峰皢鐣岄潰淇℃伅淇敼涓轰笌绯荤粺涓鑷达紝鍐嶈繘琛屼繚瀛",
- return ResponseOutput.NotOk(_localizer["TrialExternalUser_Inconsistency", existSysUser.LastName + " / " + existSysUser.FirstName, existSysUser.Phone], new { existSysUser.LastName, existSysUser.FirstName, existSysUser.Phone, existSysUser.IsZhiZhun, existSysUser.IsTestUser }, ApiResponseCodeEnum.NeedTips);
+ if (existSysUser.LastName != addOrEditTrialExternalUser.LastName || existSysUser.FirstName != addOrEditTrialExternalUser.FirstName)
+ {
+ //$"璇ョ敤鎴峰湪绯荤粺涓殑鐢ㄦ埛鍚嶄负锛歿existSysUser.LastName + " / " + existSysUser.FirstName} 鐢佃瘽锛歿existSysUser.Phone}锛屼笌濉啓淇℃伅瀛樺湪涓嶄竴鑷撮」, 璇峰皢鐣岄潰淇℃伅淇敼涓轰笌绯荤粺涓鑷达紝鍐嶈繘琛屼繚瀛",
+ return ResponseOutput.NotOk(_localizer["TrialExternalUser_Inconsistency", existSysUser.LastName + " / " + existSysUser.FirstName, existSysUser.Phone], new { existSysUser.LastName, existSysUser.FirstName, existSysUser.Phone, existSysUser.IsZhiZhun, existSysUser.IsTestUser }, ApiResponseCodeEnum.NeedTips);
+ }
+
}
- }
+ //澶勭悊 鐢熸垚璐︽埛
- //澶勭悊 鐢熸垚璐︽埛
-
- if (await _trialExternalUseRepository.AnyAsync(t =>
- t.Email == addOrEditTrialExternalUser.Email &&
- t.UserTypeId == addOrEditTrialExternalUser.UserTypeId && t.TrialId == addOrEditTrialExternalUser.TrialId))
- {
- //---绯荤粺宸茬粡瀛樺湪涓庡垪琛ㄤ腑濉啓鐨勯偖绠卞拰鐢ㄦ埛绫诲瀷鐩稿悓鐨勮处鎴凤紝璇风‘璁ゃ
- return ResponseOutput.NotOk(_localizer["TrialExternalUser_EmailTypeDuplicate"]);
- }
+ if (await _trialExternalUseRepository.AnyAsync(t =>
+ t.Email == addOrEditTrialExternalUser.Email &&
+ t.UserTypeId == addOrEditTrialExternalUser.UserTypeId && t.TrialId == addOrEditTrialExternalUser.TrialId))
+ {
+ //---绯荤粺宸茬粡瀛樺湪涓庡垪琛ㄤ腑濉啓鐨勯偖绠卞拰鐢ㄦ埛绫诲瀷鐩稿悓鐨勮处鎴凤紝璇风‘璁ゃ
+ return ResponseOutput.NotOk(_localizer["TrialExternalUser_EmailTypeDuplicate"]);
+ }
- var addEntity = _mapper.Map(addOrEditTrialExternalUser);
+ var addEntity = _mapper.Map(addOrEditTrialExternalUser);
- await _trialExternalUseRepository.AddAsync(addEntity);
+ await _trialExternalUseRepository.AddAsync(addEntity);
- var existUser = await _userRepository.FirstOrDefaultAsync(t => t.EMail == addOrEditTrialExternalUser.Email && t.UserTypeId == addOrEditTrialExternalUser.UserTypeId);
- var trialType = await _repository.Where(t => t.Id == addOrEditTrialExternalUser.TrialId).Select(t => t.TrialType).FirstOrDefaultAsync();
+ var existUser = await _userRepository.FirstOrDefaultAsync(t => t.EMail == addOrEditTrialExternalUser.Email && t.UserTypeId == addOrEditTrialExternalUser.UserTypeId);
+ var trialType = await _repository.Where(t => t.Id == addOrEditTrialExternalUser.TrialId).Select(t => t.TrialType).FirstOrDefaultAsync();
- if (existUser != null)
- {
- addEntity.IsSystemUser = true;
- addEntity.SystemUserId = existUser.Id;
+ if (existUser != null)
+ {
+ addEntity.IsSystemUser = true;
+ addEntity.SystemUserId = existUser.Id;
- }
- else
- {
+ }
+ else
+ {
- //鐢熸垚璐︽埛 骞舵彃鍏
+ //鐢熸垚璐︽埛 骞舵彃鍏
- var generateUser = _mapper.Map(addOrEditTrialExternalUser);
+ var generateUser = _mapper.Map(addOrEditTrialExternalUser);
+
+ if (trialType == TrialType.NoneOfficial)
+ {
+ generateUser.IsTestUser = true;
+ }
+
+ // 澶栭儴浜哄憳鐢熸垚璐﹀彿 閮芥槸澶栭儴鐨
+ generateUser.IsZhiZhun = false;
+
+ generateUser.Code = _userRepository.Select(t => t.Code).DefaultIfEmpty().Max() + 1;
+
+
+ generateUser.UserCode = AppSettings.GetCodeStr(generateUser.Code, nameof(User));
+
+ generateUser.UserName = generateUser.UserCode;
+
+ generateUser.UserTypeEnum = _repository.Where(t => t.Id == generateUser.UserTypeId).Select(t => t.UserTypeEnum).First();
+
+ generateUser.Password = MD5Helper.Md5("123456");
+
+ generateUser.Status = UserStateEnum.Disable;
+
+ var newAddUser = await _repository.AddAsync(generateUser);
+
+
+ addEntity.IsSystemUser = false;
+ addEntity.SystemUserId = newAddUser.Id;
+
+
+ existUser = newAddUser;
+
+ }
+
+ #region 楠岃瘉鐢ㄦ埛 鑳藉惁鍔犲叆
+
+ if (trialType == TrialType.OfficialTrial || trialType == TrialType.Training)
+ {
+
+ if (existUser.IsTestUser)
+ {
+ //---姝e紡绫诲瀷 銆佸煿璁被鍨嬬殑椤圭洰 涓嶅厑璁稿姞鍏ユ祴璇曠敤鎴
+ throw new BusinessValidationFailedException(_localizer["TrialExternalUser_TestUserNotAllowed"]);
+
+ }
+ }
if (trialType == TrialType.NoneOfficial)
{
- generateUser.IsTestUser = true;
+
+ if (existUser.IsTestUser == false)
+ {
+ //---娴嬭瘯椤圭洰 涓嶅厑璁稿姞鍏ユ寮忕敤鎴
+ throw new BusinessValidationFailedException(_localizer["TrialExternalUser_FormalUserNotAllowed"]);
+ }
}
- // 澶栭儴浜哄憳鐢熸垚璐﹀彿 閮芥槸澶栭儴鐨
- generateUser.IsZhiZhun = false;
-
- generateUser.Code = _userRepository.Select(t => t.Code).DefaultIfEmpty().Max() + 1;
+ #endregion
- generateUser.UserCode = AppSettings.GetCodeStr(generateUser.Code, nameof(User));
-
- generateUser.UserName = generateUser.UserCode;
-
- generateUser.UserTypeEnum = _repository.Where(t => t.Id == generateUser.UserTypeId).Select(t => t.UserTypeEnum).First();
-
- generateUser.Password = MD5Helper.Md5("123456");
-
- generateUser.Status = UserStateEnum.Disable;
-
- var newAddUser = await _repository.AddAsync(generateUser);
+ await _trialExternalUseRepository.SaveChangesAsync();
- addEntity.IsSystemUser = false;
- addEntity.SystemUserId = newAddUser.Id;
-
-
- existUser = newAddUser;
-
- }
-
- #region 楠岃瘉鐢ㄦ埛 鑳藉惁鍔犲叆
-
- if (trialType == TrialType.OfficialTrial || trialType == TrialType.Training)
- {
-
- if (existUser.IsTestUser)
+ //娣诲姞鐨勬椂鍊欏氨鍙戦偖浠 鐜板湪鐪佺暐
+ if (addOrEditTrialExternalUser.IsSendEmail)
{
- //---姝e紡绫诲瀷 銆佸煿璁被鍨嬬殑椤圭洰 涓嶅厑璁稿姞鍏ユ祴璇曠敤鎴
- throw new BusinessValidationFailedException(_localizer["TrialExternalUser_TestUserNotAllowed"]);
-
- }
- }
-
- if (trialType == TrialType.NoneOfficial)
- {
-
- if (existUser.IsTestUser == false )
- {
- //---娴嬭瘯椤圭洰 涓嶅厑璁稿姞鍏ユ寮忕敤鎴
- throw new BusinessValidationFailedException(_localizer["TrialExternalUser_FormalUserNotAllowed"]);
- }
- }
-
- #endregion
-
-
- await _trialExternalUseRepository.SaveChangesAsync();
-
-
- //娣诲姞鐨勬椂鍊欏氨鍙戦偖浠 鐜板湪鐪佺暐
- if (addOrEditTrialExternalUser.IsSendEmail)
- {
- await SendExternalUserJoinEmail(new TrialExternalUserSendEmail()
- {
- BaseUrl = addOrEditTrialExternalUser.BaseUrl,
- RouteUrl = addOrEditTrialExternalUser.RouteUrl,
- TrialId = addOrEditTrialExternalUser.TrialId,
- SendUsers = new List()
+ await SendExternalUserJoinEmail(new TrialExternalUserSendEmail()
+ {
+ BaseUrl = addOrEditTrialExternalUser.BaseUrl,
+ RouteUrl = addOrEditTrialExternalUser.RouteUrl,
+ TrialId = addOrEditTrialExternalUser.TrialId,
+ SendUsers = new List()
{
new UserEmail()
{
@@ -199,12 +206,13 @@ namespace IRaCIS.Core.Application.Service
SystemUserId=addEntity.SystemUserId
}
}
- });
+ });
+ }
+
+
+ return ResponseOutput.Ok(addEntity.Id.ToString());
}
-
- return ResponseOutput.Ok(addEntity.Id.ToString());
-
}
else
{
diff --git a/IRaCIS.Core.Application/TestService.cs b/IRaCIS.Core.Application/TestService.cs
index aea881b0c..5e0bf334f 100644
--- a/IRaCIS.Core.Application/TestService.cs
+++ b/IRaCIS.Core.Application/TestService.cs
@@ -1,15 +1,19 @@
-锘縰sing IRaCIS.Core.Application.Service;
+锘縰sing DocumentFormat.OpenXml.Office2010.Excel;
+using IRaCIS.Core.Application.Service;
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure;
using MassTransit;
+using Medallion.Threading;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Distributed;
+using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using MiniExcelLibs;
using System.Linq.Expressions;
+using System.Reflection.Metadata;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
@@ -20,6 +24,8 @@ namespace IRaCIS.Application.Services
[ApiExplorerSettings(GroupName = "Institution")]
public class TestService : BaseService
{
+
+ public static int IntValue = 100;
private readonly IRepository _dicRepository;
private readonly IRepository _trialRepository;
@@ -30,10 +36,13 @@ namespace IRaCIS.Application.Services
private readonly IOptionsMonitor _basicConfig;
private readonly IRepository _visitTaskRepositoryy;
+ private readonly IDistributedLockProvider _distributedLockProvider;
- public TestService(IRepository dicRepository, IRepository trialRepository/*, IDistributedCache cache*/
+ private readonly ILogger _logger;
- , IOptionsMonitor systemEmailConfig, IOptionsMonitor basicConfig, IRepository visitTaskRepository)
+ public TestService(IRepository dicRepository, IRepository trialRepository,ILogger logger
+
+ , IOptionsMonitor systemEmailConfig, IOptionsMonitor basicConfig, IRepository visitTaskRepository, IDistributedLockProvider distributedLockProvider)
{
_visitTaskRepositoryy = visitTaskRepository;
@@ -42,10 +51,36 @@ namespace IRaCIS.Application.Services
_dicRepository = dicRepository;
_trialRepository = trialRepository;
+
+ _distributedLockProvider= distributedLockProvider;
+
+ _logger= logger;
//_cache = cache;
}
+
+ [AllowAnonymous]
+ public async Task TestDistributedLock( )
+ {
+ Console.WriteLine($"鎴戣繘鏉ヤ簡褰撳墠鍊兼槸锛" + IntValue);
+ _logger.LogWarning($"鎴戣繘鏉ヤ簡褰撳墠鍊兼槸锛" + IntValue);
+
+ var @lock = _distributedLockProvider.CreateLock($"UserAccount");
+
+ using (await @lock.AcquireAsync())
+ {
+ await Task.Delay(4);
+ IntValue--;
+
+ _logger.LogWarning( IntValue.ToString());
+ Console.WriteLine(IntValue);
+ }
+
+ return ResponseOutput.Ok(IntValue);
+ }
+
+
[AllowAnonymous]
public async Task GetMemoryStoreData()
{