feat: initialize Evergreen Health backend
This commit is contained in:
@@ -0,0 +1,211 @@
|
||||
using OnceMi.AspNetCore.OSS;
|
||||
|
||||
namespace Admin.NET.Core.Service;
|
||||
|
||||
/// <summary>
|
||||
/// OSS服务管理器接口
|
||||
/// </summary>
|
||||
public interface IOSSServiceManager : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取OSS服务实例
|
||||
/// </summary>
|
||||
/// <param name="provider">存储提供者配置</param>
|
||||
/// <returns></returns>
|
||||
Task<IOSSService> GetOSSServiceAsync(SysFileProvider provider);
|
||||
|
||||
/// <summary>
|
||||
/// 清除缓存
|
||||
/// </summary>
|
||||
void ClearCache();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OSS服务管理器实现
|
||||
/// </summary>
|
||||
public class OSSServiceManager : IOSSServiceManager, ITransient
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly ConcurrentDictionary<string, IOSSService> _ossServiceCache;
|
||||
private readonly object _lockObject = new object();
|
||||
private bool _disposed = false;
|
||||
|
||||
public OSSServiceManager(IServiceProvider serviceProvider)
|
||||
{
|
||||
_serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
|
||||
_ossServiceCache = new ConcurrentDictionary<string, IOSSService>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取OSS服务实例(带缓存)
|
||||
/// </summary>
|
||||
/// <param name="provider">存储提供者配置</param>
|
||||
/// <returns></returns>
|
||||
public async Task<IOSSService> GetOSSServiceAsync(SysFileProvider provider)
|
||||
{
|
||||
if (provider == null)
|
||||
throw new ArgumentNullException(nameof(provider));
|
||||
|
||||
var cacheKey = provider.ConfigKey;
|
||||
|
||||
// 尝试从缓存获取
|
||||
if (_ossServiceCache.TryGetValue(cacheKey, out var cachedService))
|
||||
{
|
||||
return cachedService;
|
||||
}
|
||||
|
||||
// 验证配置
|
||||
if (!await ValidateConfigurationAsync(provider))
|
||||
{
|
||||
throw new InvalidOperationException($"OSS提供者配置无效: {provider.DisplayName}");
|
||||
}
|
||||
|
||||
// 线程安全地创建新服务
|
||||
lock (_lockObject)
|
||||
{
|
||||
// 双重检查锁定模式
|
||||
if (_ossServiceCache.TryGetValue(cacheKey, out cachedService))
|
||||
{
|
||||
return cachedService;
|
||||
}
|
||||
|
||||
// 转换配置并创建服务
|
||||
var ossOptions = ConvertToOSSOptions(provider);
|
||||
var ossService = CreateOSSService(ossOptions);
|
||||
|
||||
// 添加到缓存
|
||||
_ossServiceCache.TryAdd(cacheKey, ossService);
|
||||
|
||||
return ossService;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建OSS服务实例
|
||||
/// </summary>
|
||||
/// <param name="options">OSS配置选项</param>
|
||||
/// <returns></returns>
|
||||
private IOSSService CreateOSSService(OSSOptions options)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(options);
|
||||
|
||||
try
|
||||
{
|
||||
// 使用现有的IOSSServiceFactory,但需要先注册配置
|
||||
var providerName = Enum.GetName(options.Provider);
|
||||
var configSectionName = $"TempOSS_{Guid.NewGuid():N}";
|
||||
|
||||
// 创建临时配置
|
||||
var configData = new Dictionary<string, string>
|
||||
{
|
||||
[$"{configSectionName}:Provider"] = providerName,
|
||||
[$"{configSectionName}:Endpoint"] = options.Endpoint ?? "",
|
||||
[$"{configSectionName}:AccessKey"] = options.AccessKey ?? "",
|
||||
[$"{configSectionName}:SecretKey"] = options.SecretKey ?? "",
|
||||
[$"{configSectionName}:Region"] = options.Region ?? "",
|
||||
[$"{configSectionName}:IsEnableHttps"] = options.IsEnableHttps.ToString(),
|
||||
[$"{configSectionName}:IsEnableCache"] = options.IsEnableCache.ToString()
|
||||
};
|
||||
|
||||
var tempConfig = new ConfigurationBuilder()
|
||||
.AddInMemoryCollection(configData)
|
||||
.Build();
|
||||
|
||||
// 创建临时服务集合,但不立即释放
|
||||
var services = new ServiceCollection();
|
||||
services.AddSingleton<IConfiguration>(tempConfig);
|
||||
services.AddLogging();
|
||||
services.AddOSSService(providerName, configSectionName);
|
||||
|
||||
// 构建服务提供者并创建OSS服务
|
||||
var tempServiceProvider = services.BuildServiceProvider();
|
||||
var ossServiceFactory = tempServiceProvider.GetRequiredService<IOSSServiceFactory>();
|
||||
var ossService = ossServiceFactory.Create(providerName);
|
||||
|
||||
// 注意:不要释放tempServiceProvider,因为ossService可能依赖它
|
||||
// 这里我们接受这个内存开销,因为缓存会减少创建频率
|
||||
|
||||
return ossService;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw Oops.Oh($"创建OSS服务失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证配置
|
||||
/// </summary>
|
||||
/// <param name="provider">存储提供者配置</param>
|
||||
/// <returns></returns>
|
||||
private Task<bool> ValidateConfigurationAsync(SysFileProvider provider)
|
||||
{
|
||||
if (provider == null) return Task.FromResult(false);
|
||||
|
||||
// 基本字段验证
|
||||
var isValid = !string.IsNullOrWhiteSpace(provider.Provider) &&
|
||||
!string.IsNullOrWhiteSpace(provider.BucketName) &&
|
||||
!string.IsNullOrWhiteSpace(provider.AccessKey) &&
|
||||
!string.IsNullOrWhiteSpace(provider.SecretKey);
|
||||
|
||||
// Minio额外需要Endpoint
|
||||
if (provider.Provider.ToUpper() == "MINIO")
|
||||
{
|
||||
isValid = isValid && !string.IsNullOrWhiteSpace(provider.Endpoint);
|
||||
}
|
||||
|
||||
return Task.FromResult(isValid);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将SysFileProvider转换为OSSOptions
|
||||
/// </summary>
|
||||
/// <param name="provider"></param>
|
||||
/// <returns></returns>
|
||||
private OSSOptions ConvertToOSSOptions(SysFileProvider provider)
|
||||
{
|
||||
if (provider == null)
|
||||
throw new ArgumentNullException(nameof(provider));
|
||||
|
||||
var ossOptions = new OSSOptions
|
||||
{
|
||||
Provider = Enum.Parse<OSSProvider>(provider.Provider),
|
||||
Endpoint = provider.Endpoint,
|
||||
Region = provider.Region,
|
||||
IsEnableHttps = provider.IsEnableHttps ?? true,
|
||||
IsEnableCache = provider.IsEnableCache ?? true
|
||||
};
|
||||
|
||||
// 设置认证信息(所有提供者现在都使用统一的字段)
|
||||
ossOptions.AccessKey = provider.AccessKey;
|
||||
ossOptions.SecretKey = provider.SecretKey;
|
||||
|
||||
return ossOptions;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除缓存
|
||||
/// </summary>
|
||||
public void ClearCache()
|
||||
{
|
||||
lock (_lockObject)
|
||||
{
|
||||
_ossServiceCache.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 释放资源
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
lock (_lockObject)
|
||||
{
|
||||
_ossServiceCache.Clear();
|
||||
}
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user