将轨迹、面单、9610、揽收、自动触发与 ForecastBilling 异步化,缩短扫码与下单 RT;队列未启用时同步回落。 Co-authored-by: Cursor <cursoragent@cursor.com>
113 lines
3.4 KiB
C#
113 lines
3.4 KiB
C#
using Fake.EventBus.Distributed;
|
||
using Microsoft.Extensions.DependencyInjection;
|
||
using Microsoft.Extensions.Logging;
|
||
using Oms.Application.Services.Orders.Issues;
|
||
|
||
namespace Oms.Application.Messaging.OrderSideEffects;
|
||
|
||
/// <summary>
|
||
/// 优先 Fake.EventBus.RabbitMQ;发布失败则同进程同步执行 Handler。
|
||
/// </summary>
|
||
public sealed class OrderSideEffectEventPublisher(
|
||
IDistributedEventBus eventBus,
|
||
IServiceScopeFactory scopeFactory,
|
||
ILogger<OrderSideEffectEventPublisher> logger) : IOrderSideEffectEventPublisher
|
||
{
|
||
public async Task PublishLifecycleTrackAppendAsync(
|
||
int orderId,
|
||
string orderNo,
|
||
string trackCode,
|
||
string? authorization = null,
|
||
CancellationToken cancellationToken = default)
|
||
{
|
||
if (orderId <= 0 || string.IsNullOrWhiteSpace(orderNo) || string.IsNullOrWhiteSpace(trackCode))
|
||
{
|
||
return;
|
||
}
|
||
|
||
var @event = new OrderLifecycleTrackAppendIntegrationEvent
|
||
{
|
||
OrderId = orderId,
|
||
OrderNo = orderNo.Trim(),
|
||
TrackCode = trackCode.Trim(),
|
||
Authorization = string.IsNullOrWhiteSpace(authorization) ? null : authorization.Trim()
|
||
};
|
||
|
||
if (await TryPublishAsync(@event, cancellationToken))
|
||
{
|
||
return;
|
||
}
|
||
|
||
await ExecuteInScopeAsync<OrderLifecycleTrackAppendEventHandler>(
|
||
h => h.HandleAsync(@event, cancellationToken),
|
||
cancellationToken);
|
||
}
|
||
|
||
public async Task PublishAutoTriggerFireAsync(
|
||
int orderId,
|
||
AutoTriggerTiming timing,
|
||
int operatorUserId,
|
||
CancellationToken cancellationToken = default)
|
||
{
|
||
if (orderId <= 0)
|
||
{
|
||
return;
|
||
}
|
||
|
||
var @event = new OrderAutoTriggerFireIntegrationEvent
|
||
{
|
||
OrderId = orderId,
|
||
Timing = timing.ToString(),
|
||
OperatorUserId = operatorUserId
|
||
};
|
||
|
||
if (await TryPublishAsync(@event, cancellationToken))
|
||
{
|
||
return;
|
||
}
|
||
|
||
await ExecuteInScopeAsync<OrderAutoTriggerFireEventHandler>(
|
||
h => h.HandleAsync(@event, cancellationToken),
|
||
cancellationToken);
|
||
}
|
||
|
||
private async Task<bool> TryPublishAsync(IntegrationEvent @event, CancellationToken cancellationToken)
|
||
{
|
||
try
|
||
{
|
||
await eventBus.PublishAsync(@event, cancellationToken);
|
||
logger.LogDebug(
|
||
"Published side-effect event {EventName} Id={EventId}",
|
||
@event.GetType().Name,
|
||
@event.Id);
|
||
return true;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
logger.LogWarning(
|
||
ex,
|
||
"Publish side-effect event {EventName} failed, fallback to sync. EventId={EventId}",
|
||
@event.GetType().Name,
|
||
@event.Id);
|
||
return false;
|
||
}
|
||
}
|
||
|
||
private async Task ExecuteInScopeAsync<THandler>(
|
||
Func<THandler, Task> action,
|
||
CancellationToken cancellationToken)
|
||
where THandler : notnull
|
||
{
|
||
try
|
||
{
|
||
using var scope = scopeFactory.CreateScope();
|
||
var handler = scope.ServiceProvider.GetRequiredService<THandler>();
|
||
await action(handler);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
logger.LogWarning(ex, "Sync fallback for {Handler} failed", typeof(THandler).Name);
|
||
}
|
||
}
|
||
}
|