feat: SKU保存链路切换到RabbitMQ Outbox并新增独立Worker
All checks were successful
Build and Deploy TenantApi / build-and-deploy (push) Successful in 51s
All checks were successful
Build and Deploy TenantApi / build-and-deploy (push) Successful in 51s
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
using MassTransit;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using TakeoutSaaS.Application.App.Products.Messaging;
|
||||
using TakeoutSaaS.Domain.Products.Enums;
|
||||
using TakeoutSaaS.Infrastructure.App.Persistence;
|
||||
using TakeoutSaaS.TenantApi.Services;
|
||||
|
||||
namespace TakeoutSaaS.SkuWorker.Consumers;
|
||||
|
||||
/// <summary>
|
||||
/// SKU 保存任务消费器。
|
||||
/// </summary>
|
||||
public sealed class ProductSkuSaveJobRequestedConsumer(
|
||||
ProductSkuSaveJobRunner jobRunner,
|
||||
TakeoutAppDbContext dbContext,
|
||||
ILogger<ProductSkuSaveJobRequestedConsumer> logger) : IConsumer<ProductSkuSaveJobRequestedEvent>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task Consume(ConsumeContext<ProductSkuSaveJobRequestedEvent> context)
|
||||
{
|
||||
var payload = context.Message;
|
||||
logger.LogInformation(
|
||||
"开始消费 SKU 保存任务,JobId={JobId}, TenantId={TenantId}, StoreId={StoreId}, ProductId={ProductId}, RetryAttempt={RetryAttempt}",
|
||||
payload.JobId,
|
||||
payload.TenantId,
|
||||
payload.StoreId,
|
||||
payload.ProductId,
|
||||
context.GetRetryAttempt());
|
||||
|
||||
await jobRunner.ExecuteAsync(payload.JobId);
|
||||
|
||||
var jobStatus = await dbContext.ProductSkuSaveJobs
|
||||
.IgnoreQueryFilters()
|
||||
.AsNoTracking()
|
||||
.Where(item => item.Id == payload.JobId)
|
||||
.Select(item => item.Status)
|
||||
.SingleOrDefaultAsync(context.CancellationToken);
|
||||
|
||||
if (jobStatus == ProductSkuSaveJobStatus.Failed)
|
||||
{
|
||||
throw new InvalidOperationException($"SKU 保存任务执行失败,JobId={payload.JobId}");
|
||||
}
|
||||
}
|
||||
}
|
||||
62
src/Worker/TakeoutSaaS.SkuWorker/Program.cs
Normal file
62
src/Worker/TakeoutSaaS.SkuWorker/Program.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using MassTransit;
|
||||
using Microsoft.Extensions.Options;
|
||||
using TakeoutSaaS.Infrastructure.App.Persistence;
|
||||
using TakeoutSaaS.Infrastructure.Common.Extensions;
|
||||
using TakeoutSaaS.Module.Messaging.Options;
|
||||
using TakeoutSaaS.Module.Tenancy.Extensions;
|
||||
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
using TakeoutSaaS.TenantApi.Services;
|
||||
using TakeoutSaaS.SkuWorker.Consumers;
|
||||
using TakeoutSaaS.Application.App.Products.Messaging;
|
||||
|
||||
var builder = Host.CreateApplicationBuilder(args);
|
||||
|
||||
builder.Services.AddDatabaseInfrastructure(builder.Configuration);
|
||||
builder.Services.AddPostgresDbContext<TakeoutAppDbContext>(DatabaseConstants.AppDataSource);
|
||||
builder.Services.AddTenantResolution(builder.Configuration);
|
||||
builder.Services.AddScoped<ProductSkuSaveService>();
|
||||
builder.Services.AddScoped<ProductSkuSaveJobRunner>();
|
||||
|
||||
builder.Services.AddOptions<RabbitMqOptions>()
|
||||
.Bind(builder.Configuration.GetSection("RabbitMQ"))
|
||||
.ValidateDataAnnotations()
|
||||
.ValidateOnStart();
|
||||
|
||||
builder.Services.AddMassTransit(configurator =>
|
||||
{
|
||||
configurator.AddConsumer<ProductSkuSaveJobRequestedConsumer>(consumerConfigurator =>
|
||||
{
|
||||
consumerConfigurator.UseMessageRetry(retry =>
|
||||
{
|
||||
retry.Exponential(
|
||||
retryLimit: 5,
|
||||
minInterval: TimeSpan.FromSeconds(1),
|
||||
maxInterval: TimeSpan.FromSeconds(30),
|
||||
intervalDelta: TimeSpan.FromSeconds(2));
|
||||
});
|
||||
});
|
||||
|
||||
configurator.UsingRabbitMq((context, cfg) =>
|
||||
{
|
||||
var options = context.GetRequiredService<IOptions<RabbitMqOptions>>().Value;
|
||||
var virtualHost = string.IsNullOrWhiteSpace(options.VirtualHost) ? "/" : options.VirtualHost.Trim();
|
||||
var virtualHostPath = virtualHost == "/" ? "/" : $"/{virtualHost.TrimStart('/')}";
|
||||
var hostUri = new Uri($"rabbitmq://{options.Host}:{options.Port}{virtualHostPath}");
|
||||
|
||||
cfg.Host(hostUri, host =>
|
||||
{
|
||||
host.Username(options.Username);
|
||||
host.Password(options.Password);
|
||||
});
|
||||
|
||||
cfg.PrefetchCount = options.PrefetchCount;
|
||||
cfg.ReceiveEndpoint(ProductSkuSaveJobRequestedEvent.QueueName, endpoint =>
|
||||
{
|
||||
endpoint.PrefetchCount = options.PrefetchCount;
|
||||
endpoint.ConfigureConsumer<ProductSkuSaveJobRequestedConsumer>(context);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
var app = builder.Build();
|
||||
await app.RunAsync();
|
||||
@@ -0,0 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Worker">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MassTransit" Version="8.5.7" />
|
||||
<PackageReference Include="MassTransit.RabbitMQ" Version="8.5.7" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Api\TakeoutSaaS.TenantApi\TakeoutSaaS.TenantApi.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
30
src/Worker/TakeoutSaaS.SkuWorker/appsettings.json
Normal file
30
src/Worker/TakeoutSaaS.SkuWorker/appsettings.json
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"Database": {
|
||||
"DataSources": {
|
||||
"AppDatabase": {
|
||||
"Write": "Host=localhost;Port=5432;Database=takeout_app_db;Username=app_user;Password=AppUser112233",
|
||||
"Reads": [
|
||||
"Host=localhost;Port=5432;Database=takeout_app_db;Username=app_user;Password=AppUser112233"
|
||||
],
|
||||
"CommandTimeoutSeconds": 30,
|
||||
"MaxRetryCount": 3,
|
||||
"MaxRetryDelaySeconds": 5
|
||||
}
|
||||
}
|
||||
},
|
||||
"Tenancy": {
|
||||
"TenantIdHeaderName": "X-Tenant-Id",
|
||||
"TenantCodeHeaderName": "X-Tenant-Code",
|
||||
"RootDomain": "tenant.laosankeji.com"
|
||||
},
|
||||
"RabbitMQ": {
|
||||
"Host": "localhost",
|
||||
"Port": 5672,
|
||||
"Username": "guest",
|
||||
"Password": "guest",
|
||||
"VirtualHost": "/",
|
||||
"Exchange": "takeout.events",
|
||||
"ExchangeType": "topic",
|
||||
"PrefetchCount": 20
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user