using Hangfire; using Hangfire.Dashboard; using Hangfire.MemoryStorage; using QYZH.InteractiveMagazine.Infrastructure.RabbitMQ; using QYZH.InteractiveMagazine.Models.Settings; using QYZH.InteractiveMagazine.WorkService.Consumers; using QYZH.InteractiveMagazine.WorkService.Jobs; using Serilog; using SqlSugar; using SqlSugar.IOC; using System.Linq.Expressions; using System.Reflection; using Yitter.IdGenerator; var builder = WebApplication.CreateBuilder(args); // 加载配置 builder.Configuration .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: true, reloadOnChange: true); // 配置Serilog Log.Logger = new LoggerConfiguration() .ReadFrom.Configuration(builder.Configuration) .Enrich.FromLogContext() .CreateLogger(); builder.Services.AddSerilog(); // 初始化雪花ID生成器 YitIdHelper.SetIdGenerator(new IdGeneratorOptions { WorkerId = 2 }); // 初始化MySQL(SqlSugar) builder.Services.AddSqlSugar(new IocConfig { ConfigId = 0, DbType = IocDbType.MySql, ConnectionString = builder.Configuration.GetConnectionString("DefaultConnection"), IsAutoCloseConnection = true }); SugarIocServices.ConfigurationSugar(db => { db.Aop.OnLogExecuting = (sql, pars) => { Log.Information("[SQL] {Sql}", UtilMethods.GetSqlString((DbType)IocDbType.MySql, sql, pars)); }; db.Aop.OnError = ex => { Log.Error(ex, "[SQL Error] {Message}", ex.Message); }; }); // 配置Hangfire(内存存储,后续可切换Redis) builder.Services.AddHangfire(config => config .UseMemoryStorage() .UseSerializerSettings(new Newtonsoft.Json.JsonSerializerSettings { TypeNameHandling = Newtonsoft.Json.TypeNameHandling.All })); builder.Services.AddHangfireServer(); // 配置RabbitMQ builder.Services.AddRabbitMQ(builder.Configuration); // 注册队列消费者(新增消费者只需实现 IQueueConsumer 并在此注册) builder.Services.AddScoped(); builder.Services.AddScoped(); // 注册消费者后台服务 builder.Services.AddHostedService(); // 从配置文件读取定时任务列表 var jobSettings = builder.Configuration.GetSection("HangfireJobs").Get(); var app = builder.Build(); // 配置Hangfire Dashboard(仅本机访问) app.UseHangfireDashboard("/hangfire", new DashboardOptions { Authorization = new[] { new LocalRequestsOnlyAuthorizationFilter() } }); // 根据配置动态注册定时任务 if (jobSettings?.Jobs != null) { foreach (var job in jobSettings.Jobs) { var jobType = Type.GetType(job.JobType); if (jobType == null) { Log.Warning("定时任务 [{Name}] 类型未找到: {JobType},跳过注册", job.Name, job.JobType); continue; } if (!job.Enabled) { // 配置为关闭的任务,从 Hangfire 中移除 RecurringJob.RemoveIfExists(job.Name); Log.Information("定时任务 [{Name}] 已禁用,已移除", job.Name); continue; } // 构造表达式:job => job.MethodName() var method = jobType.GetMethod(job.MethodName); if (method == null) { Log.Warning("定时任务 [{Name}] 方法未找到: {MethodName},跳过注册", job.Name, job.MethodName); continue; } var param = Expression.Parameter(jobType, "job"); var call = Expression.Call(param, method); var lambda = Expression.Lambda(call, param); RecurringJob.AddOrUpdate(job.Name, lambda, job.Cron); Log.Information("定时任务 [{Name}] 已注册,Cron: {Cron}", job.Name, job.Cron); } } Log.Information("WorkService 已启动,Hangfire Dashboard: /hangfire"); app.Run();