Files
StoreWeb/Plugins/CloudProduct/CloudProductPlugin.cs
T
2026-11-06 19:25:36 +08:00

80 lines
3.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using MAX.Plugins;
using Hangfire;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using MySql.Data.MySqlClient;
using Store.Modules.CloudProduct.Services;
namespace Store.Modules.CloudProduct
{
public sealed class CloudProductPlugin : PluginBase
{
public override string Id => "CloudProduct";
protected override void RegisterServices(IServiceCollection services)
{
RequireConfiguration("Search:Url");
RequireConfiguration("Search:IndexName");
RequireConfiguration("Search:FavoritesIndexName");
RequireConfiguration("RawData:Path");
// 业务连接独立于宿主的 Hangfire 存储。
var connection = RequireConfiguration("CloudProductConnection");
var connectionStringBuilder = new MySqlConnectionStringBuilder(connection)
{
AllowUserVariables = true
};
services.AddTransient<GoodsIndexJob>();
services.AddTransient<GoodsViolationIndexJob>();
services.AddAuthorization(options => options.AddPolicy("CloudGoodsViolationWrite",
policy => policy.RequireAuthenticatedUser().RequireClaim("permission", "cloudgoods:violation:write")));
services.AddKeyedSingleton<IFreeSql>("CloudProductConnection", (_, _) =>
new FreeSql.FreeSqlBuilder().UseConnectionString(FreeSql.DataType.MySql, connectionStringBuilder.ConnectionString)
.UseAdoConnectionPool(true).Build());
services.AddHostedService<CloudProductSearchStartup>();
// 服务自行创建客户端,单例复用连接池并由容器负责释放。
services.AddSingleton<ImageAnalysisQuotaService>();
// 图片识别沿用专用缓存库,所有请求共享并发上限。
var inspectionConnection = RequireConfiguration("ProductInspection:ConnectionString");
services.AddKeyedSingleton<IFreeSql>("ProductInspectionConnection", (_, _) =>
new FreeSql.FreeSqlBuilder().UseConnectionString(FreeSql.DataType.MySql, inspectionConnection)
.UseAdoConnectionPool(true).Build());
var maximum = Context.Configuration.GetValue<int?>("ProductInspection:MaxConcurrentAnalysis") ?? 5;
if (maximum is < 1 or > 100) throw new InvalidOperationException("识别并发数必须在 1 至 100 之间。");
services.AddKeyedSingleton<SemaphoreSlim>("ProductInspectionAnalysisGate", (_, _) => new SemaphoreSlim(maximum, maximum));
}
/// <summary>
/// 管道装配阶段(builder.Build() 之后、app.Run() 之前):这里可以挂中间件、解析容器里的服务
/// </summary>
protected override void ConfigureApplication(IApplicationBuilder app)
{
try
{
var Configuration = Context.Configuration;
// 注册定时任务:把未同步(IndexStatus=0)的商品写入 OpenSearch 分词索引
var cron = Configuration.GetValue<string>("Indexing:Cron") ?? "*/5 * * * *";
// 用容器里的 IRecurringJobManager,而不是静态 RecurringJob:
// AddHangfire 只把 JobStorage 注册进容器(没有设置 JobStorage.Current),静态 API 在 Build() 之后调用会直接抛异常。
app.ApplicationServices.GetRequiredService<IRecurringJobManager>().AddOrUpdate<GoodsIndexJob>(
"goods-index-pending",
job => job.ProcessPendingAsync(),
cron);
app.ApplicationServices.GetRequiredService<IRecurringJobManager>().AddOrUpdate<GoodsViolationIndexJob>(
"goods-violation-delete-pending", job => job.ProcessPendingAsync(), "* * * * *");
}
catch (Exception ex)
{
// 定时任务注册失败时记录错误,数据库恢复后重启以重新注册。
Console.WriteLine("[Hangfire] CloudProduct 定时任务注册失败: " + ex.Message);
}
}
}
}