feat: finalize core modules and gateway
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TakeoutSaaS.Module.Scheduler.Abstractions;
|
||||
|
||||
/// <summary>
|
||||
/// 周期性任务注册抽象。
|
||||
/// </summary>
|
||||
public interface IRecurringJobRegistrar
|
||||
{
|
||||
/// <summary>
|
||||
/// 注册所有预设的周期性任务。
|
||||
/// </summary>
|
||||
Task RegisterAsync(CancellationToken cancellationToken = default);
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
using Hangfire;
|
||||
using Hangfire.PostgreSql;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using TakeoutSaaS.Module.Scheduler.Abstractions;
|
||||
using TakeoutSaaS.Module.Scheduler.HostedServices;
|
||||
using TakeoutSaaS.Module.Scheduler.Jobs;
|
||||
using TakeoutSaaS.Module.Scheduler.Options;
|
||||
using TakeoutSaaS.Module.Scheduler.Services;
|
||||
|
||||
namespace TakeoutSaaS.Module.Scheduler.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// 调度模块注册扩展(默认 Hangfire)。
|
||||
/// </summary>
|
||||
public static class SchedulerServiceCollectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 注册调度模块。
|
||||
/// </summary>
|
||||
public static IServiceCollection AddSchedulerModule(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
services.AddOptions<SchedulerOptions>()
|
||||
.Bind(configuration.GetSection("Scheduler"))
|
||||
.ValidateDataAnnotations()
|
||||
.ValidateOnStart();
|
||||
|
||||
services.AddHangfire((serviceProvider, config) =>
|
||||
{
|
||||
var options = serviceProvider.GetRequiredService<IOptionsMonitor<SchedulerOptions>>().CurrentValue;
|
||||
config
|
||||
.UseSimpleAssemblyNameTypeSerializer()
|
||||
.UseRecommendedSerializerSettings()
|
||||
.UsePostgreSqlStorage(options.ConnectionString);
|
||||
});
|
||||
|
||||
services.AddHangfireServer((serviceProvider, options) =>
|
||||
{
|
||||
var scheduler = serviceProvider.GetRequiredService<IOptionsMonitor<SchedulerOptions>>().CurrentValue;
|
||||
options.WorkerCount = scheduler.WorkerCount ?? options.WorkerCount;
|
||||
});
|
||||
|
||||
services.AddSingleton<IRecurringJobRegistrar, RecurringJobRegistrar>();
|
||||
services.AddHostedService<RecurringJobHostedService>();
|
||||
|
||||
services.AddScoped<OrderTimeoutJob>();
|
||||
services.AddScoped<CouponExpireJob>();
|
||||
services.AddScoped<LogCleanupJob>();
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 启用 Hangfire Dashboard(默认关闭,可通过配置开启)。
|
||||
/// </summary>
|
||||
public static IApplicationBuilder UseSchedulerDashboard(this IApplicationBuilder app, IConfiguration configuration)
|
||||
{
|
||||
var options = configuration.GetSection("Scheduler").Get<SchedulerOptions>();
|
||||
if (options is { DashboardEnabled: true })
|
||||
{
|
||||
app.UseHangfireDashboard(options.DashboardPath);
|
||||
}
|
||||
|
||||
return app;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using TakeoutSaaS.Module.Scheduler.Abstractions;
|
||||
|
||||
namespace TakeoutSaaS.Module.Scheduler.HostedServices;
|
||||
|
||||
/// <summary>
|
||||
/// 启动时注册周期性任务的宿主服务。
|
||||
/// </summary>
|
||||
public sealed class RecurringJobHostedService(IRecurringJobRegistrar registrar, ILogger<RecurringJobHostedService> logger) : IHostedService
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
await registrar.RegisterAsync(cancellationToken).ConfigureAwait(false);
|
||||
logger.LogInformation("调度任务已注册");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace TakeoutSaaS.Module.Scheduler.Jobs;
|
||||
|
||||
/// <summary>
|
||||
/// 优惠券过期处理任务(占位实现)。
|
||||
/// </summary>
|
||||
public sealed class CouponExpireJob(ILogger<CouponExpireJob> logger)
|
||||
{
|
||||
/// <summary>
|
||||
/// 执行优惠券过期清理。
|
||||
/// </summary>
|
||||
public Task ExecuteAsync()
|
||||
{
|
||||
logger.LogInformation("定时任务:处理已过期优惠券(占位实现)");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace TakeoutSaaS.Module.Scheduler.Jobs;
|
||||
|
||||
/// <summary>
|
||||
/// 日志清理任务(占位实现)。
|
||||
/// </summary>
|
||||
public sealed class LogCleanupJob(ILogger<LogCleanupJob> logger)
|
||||
{
|
||||
/// <summary>
|
||||
/// 执行日志清理。
|
||||
/// </summary>
|
||||
public Task ExecuteAsync()
|
||||
{
|
||||
logger.LogInformation("定时任务:清理历史日志(占位实现)");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace TakeoutSaaS.Module.Scheduler.Jobs;
|
||||
|
||||
/// <summary>
|
||||
/// 订单超时取消任务(占位,后续接入订单服务)。
|
||||
/// </summary>
|
||||
public sealed class OrderTimeoutJob(ILogger<OrderTimeoutJob> logger)
|
||||
{
|
||||
/// <summary>
|
||||
/// 执行超时订单检查。
|
||||
/// </summary>
|
||||
public Task ExecuteAsync()
|
||||
{
|
||||
logger.LogInformation("定时任务:检查超时未支付订单并取消(占位实现)");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace TakeoutSaaS.Module.Scheduler.Options;
|
||||
|
||||
/// <summary>
|
||||
/// 调度模块配置。
|
||||
/// </summary>
|
||||
public sealed class SchedulerOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Hangfire 存储使用的连接字符串。
|
||||
/// </summary>
|
||||
[Required]
|
||||
public string ConnectionString { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 工作线程数,默认根据 CPU 计算。
|
||||
/// </summary>
|
||||
[Range(1, 100)]
|
||||
public int? WorkerCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用 Dashboard(默认 false,待 AdminUI 接入)。
|
||||
/// </summary>
|
||||
public bool DashboardEnabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Dashboard 路径。
|
||||
/// </summary>
|
||||
public string DashboardPath { get; set; } = "/hangfire";
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using Hangfire;
|
||||
using TakeoutSaaS.Module.Scheduler.Abstractions;
|
||||
using TakeoutSaaS.Module.Scheduler.Jobs;
|
||||
|
||||
namespace TakeoutSaaS.Module.Scheduler.Services;
|
||||
|
||||
/// <summary>
|
||||
/// 周期性任务注册器。
|
||||
/// </summary>
|
||||
public sealed class RecurringJobRegistrar : IRecurringJobRegistrar
|
||||
{
|
||||
private readonly OrderTimeoutJob _orderTimeoutJob;
|
||||
private readonly CouponExpireJob _couponExpireJob;
|
||||
private readonly LogCleanupJob _logCleanupJob;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化注册器。
|
||||
/// </summary>
|
||||
public RecurringJobRegistrar(
|
||||
OrderTimeoutJob orderTimeoutJob,
|
||||
CouponExpireJob couponExpireJob,
|
||||
LogCleanupJob logCleanupJob)
|
||||
{
|
||||
_orderTimeoutJob = orderTimeoutJob;
|
||||
_couponExpireJob = couponExpireJob;
|
||||
_logCleanupJob = logCleanupJob;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task RegisterAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
RecurringJob.AddOrUpdate("orders.timeout-cancel", () => _orderTimeoutJob.ExecuteAsync(), "*/5 * * * *");
|
||||
RecurringJob.AddOrUpdate("coupons.expire", () => _couponExpireJob.ExecuteAsync(), "0 */1 * * *");
|
||||
RecurringJob.AddOrUpdate("logs.cleanup", () => _logCleanupJob.ExecuteAsync(), "0 3 * * *");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,16 @@
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.14" />
|
||||
<PackageReference Include="Hangfire.PostgreSql" Version="1.20.12" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.DataAnnotations" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Core\TakeoutSaaS.Shared.Abstractions\TakeoutSaaS.Shared.Abstractions.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user