193 lines
5.4 KiB
C#
193 lines
5.4 KiB
C#
|
|
//--------------------------------------------------------------------
|
|
// 此代码由liquid模板自动生成 byzhouhang 20240909
|
|
// 生成时间 2026-03-10 06:15:17Z
|
|
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
|
//--------------------------------------------------------------------
|
|
using AutoMapper;
|
|
using IRaCIS.Core.Application.Helper;
|
|
|
|
using IRaCIS.Core.Domain.Models;
|
|
using IRaCIS.Core.Domain.Share;
|
|
using IRaCIS.Core.Infra.EFCore;
|
|
using IRaCIS.Core.Infra.EFCore.Common;
|
|
using IRaCIS.Core.Infrastructure.Extention;
|
|
using IRaCIS.Core.SCP;
|
|
using IRaCIS.Core.SCP.Service;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.Localization;
|
|
using Microsoft.Extensions.Options;
|
|
using System.Drawing;
|
|
using System.Threading.Channels;
|
|
using System.Threading.Tasks;
|
|
using ZiggyCreatures.Caching.Fusion;
|
|
|
|
namespace IRaCIS.Core.SCP.Service;
|
|
|
|
public class FileUploadRecordAddOrEdit
|
|
{
|
|
public Guid? Id { get; set; }
|
|
|
|
|
|
public string FileName { get; set; }
|
|
|
|
public long FileSize { get; set; }
|
|
|
|
public string FileType { get; set; }
|
|
|
|
public string Path { get; set; }
|
|
|
|
|
|
public string UploadBatchId { get; set; }
|
|
public BatchDataType BatchDataType { get; set; }
|
|
|
|
|
|
public Guid? TrialId { get; set; }
|
|
|
|
public Guid? SubjectId { get; set; }
|
|
|
|
public Guid? SubjectVisitId { get; set; }
|
|
|
|
public Guid? DicomStudyId { get; set; }
|
|
|
|
public Guid? NoneDicomStudyId { get; set; }
|
|
|
|
|
|
|
|
public string FileMarkId { get; set; }
|
|
|
|
public int? Priority { get; set; }
|
|
public string IP { get; set; }
|
|
public bool? IsNeedSync { get; set; }
|
|
public string UploadRegion { get; set; }
|
|
public string TargetRegion { get; set; }
|
|
}
|
|
public interface IFileUploadRecordService
|
|
{
|
|
|
|
|
|
Task<IResponseOutput> AddOrUpdateFileUploadRecord(FileUploadRecordAddOrEdit addOrEditFileUploadRecord);
|
|
|
|
}
|
|
|
|
[ApiExplorerSettings(GroupName = "Common")]
|
|
public class FileUploadRecordService(IRepository<FileUploadRecord> _fileUploadRecordRepository,
|
|
IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer, IOptionsMonitor<ObjectStoreServiceOptions> options,
|
|
IFusionCache _fusionCache, IRepository<Trial> _trialRepository, FileSyncQueue _fileSyncQueue) : BaseService, IFileUploadRecordService
|
|
{
|
|
|
|
ObjectStoreServiceOptions ObjectStoreServiceConfig = options.CurrentValue;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public async Task<IResponseOutput> AddOrUpdateFileUploadRecord(FileUploadRecordAddOrEdit addOrEditFileUploadRecord)
|
|
{
|
|
|
|
addOrEditFileUploadRecord.IP = _userInfo.IP;
|
|
|
|
if (ObjectStoreServiceConfig.IsOpenStoreSync && _userInfo.Domain.IsNotNullOrEmpty())
|
|
{
|
|
var find = ObjectStoreServiceConfig.SyncConfigList.FirstOrDefault(t => t.Domain == _userInfo.Domain);
|
|
if (find != null)
|
|
{
|
|
addOrEditFileUploadRecord.UploadRegion = find.UploadRegion;
|
|
addOrEditFileUploadRecord.TargetRegion = find.TargetRegion;
|
|
|
|
}
|
|
}
|
|
|
|
if (addOrEditFileUploadRecord.TrialId != null)
|
|
{
|
|
|
|
var trialDataStore = await _fusionCache.GetOrSetAsync(CacheKeys.TrialDataStoreType(addOrEditFileUploadRecord.TrialId.Value), async _ =>
|
|
{
|
|
return await _trialRepository.Where(t => t.Id == addOrEditFileUploadRecord.TrialId).Select(t => t.TrialDataStoreType)
|
|
.FirstOrDefaultAsync();
|
|
},
|
|
TimeSpan.FromDays(7)
|
|
);
|
|
|
|
//项目配置了,那么就设置需要同步
|
|
if (trialDataStore == TrialDataStore.MUtiCenter)
|
|
{
|
|
addOrEditFileUploadRecord.IsNeedSync = true;
|
|
|
|
addOrEditFileUploadRecord.Priority = 0;
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
addOrEditFileUploadRecord.TargetRegion = "";
|
|
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
//系统文件,默认同步
|
|
addOrEditFileUploadRecord.IsNeedSync = true;
|
|
|
|
addOrEditFileUploadRecord.Priority = 0;
|
|
}
|
|
|
|
var entity = await _fileUploadRecordRepository.InsertOrUpdateAsync(addOrEditFileUploadRecord, true);
|
|
|
|
if (addOrEditFileUploadRecord.IsNeedSync == true)
|
|
{
|
|
_fileSyncQueue.Enqueue(entity.Id, addOrEditFileUploadRecord.Priority ?? 0);
|
|
}
|
|
|
|
return ResponseOutput.Ok(entity.Id.ToString());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// 同步队列 信号量
|
|
/// </summary>
|
|
public class FileSyncQueue
|
|
{
|
|
private readonly PriorityQueue<Guid, int> _queue = new();
|
|
private readonly SemaphoreSlim _signal = new(0);
|
|
private readonly object _lock = new();
|
|
|
|
public void Enqueue(Guid id, int priority)
|
|
{
|
|
lock (_lock)
|
|
{
|
|
// priority 越大越优先
|
|
_queue.Enqueue(id, -priority);
|
|
}
|
|
|
|
//类似于计数器,不会产生通知风暴,可消费资源 +1
|
|
//if (有等待线程) 唤醒一个 else 仅增加计数
|
|
_signal.Release(); // 唤醒一个 worker
|
|
}
|
|
|
|
/// <summary>
|
|
/// 如果没有任务 → 挂起等待 有任务 → 被唤醒并返回
|
|
/// </summary>
|
|
/// <param name="ct"></param>
|
|
/// <returns></returns>
|
|
public async Task<Guid> DequeueAsync(CancellationToken ct)
|
|
{
|
|
await _signal.WaitAsync(ct);
|
|
|
|
lock (_lock)
|
|
{
|
|
return _queue.Dequeue();
|
|
}
|
|
}
|
|
} |