|
|
|
@ -25,7 +25,7 @@ public class InboxProcessor : IInboxProcessor, ITransientDependency |
|
|
|
protected IEventInbox Inbox { get; private set; } = default!; |
|
|
|
protected InboxConfig InboxConfig { get; private set; } = default!; |
|
|
|
protected AbpEventBusBoxesOptions EventBusBoxesOptions { get; } |
|
|
|
|
|
|
|
protected InboxProcessorOptions InboxProcessorOptions { get; set; } |
|
|
|
protected DateTime? LastCleanTime { get; set; } |
|
|
|
|
|
|
|
protected string DistributedLockName { get; set; } = default!; |
|
|
|
@ -40,7 +40,8 @@ public class InboxProcessor : IInboxProcessor, ITransientDependency |
|
|
|
IAbpDistributedLock distributedLock, |
|
|
|
IUnitOfWorkManager unitOfWorkManager, |
|
|
|
IClock clock, |
|
|
|
IOptions<AbpEventBusBoxesOptions> eventBusBoxesOptions) |
|
|
|
IOptions<AbpEventBusBoxesOptions> eventBusBoxesOptions, |
|
|
|
IOptions<InboxProcessorOptions> inboxProcessorOptions) |
|
|
|
{ |
|
|
|
ServiceProvider = serviceProvider; |
|
|
|
Timer = timer; |
|
|
|
@ -49,6 +50,7 @@ public class InboxProcessor : IInboxProcessor, ITransientDependency |
|
|
|
UnitOfWorkManager = unitOfWorkManager; |
|
|
|
Clock = clock; |
|
|
|
EventBusBoxesOptions = eventBusBoxesOptions.Value; |
|
|
|
InboxProcessorOptions = inboxProcessorOptions.Value; |
|
|
|
Timer.Period = Convert.ToInt32(EventBusBoxesOptions.PeriodTimeSpan.TotalMilliseconds); |
|
|
|
Timer.Elapsed += TimerOnElapsed; |
|
|
|
Logger = NullLogger<InboxProcessor>.Instance; |
|
|
|
@ -103,6 +105,12 @@ public class InboxProcessor : IInboxProcessor, ITransientDependency |
|
|
|
|
|
|
|
foreach (var waitingEvent in waitingEvents) |
|
|
|
{ |
|
|
|
if (waitingEvent.NextRetryTime.HasValue && waitingEvent.NextRetryTime.Value > Clock.Now) |
|
|
|
{ |
|
|
|
Logger.LogInformation($"Event with id = {waitingEvent.Id:N} is not ready to be processed yet. Next retry time: {waitingEvent.NextRetryTime.Value}"); |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
try |
|
|
|
{ |
|
|
|
using (var uow = UnitOfWorkManager.Begin(isTransactional: true, requiresNew: true)) |
|
|
|
@ -121,6 +129,45 @@ public class InboxProcessor : IInboxProcessor, ITransientDependency |
|
|
|
catch (Exception e) |
|
|
|
{ |
|
|
|
Logger.LogError(e, $"An error occurred while processing the incoming event with id = {waitingEvent.Id:N}"); |
|
|
|
|
|
|
|
if (InboxProcessorOptions.FailurePolicy == InboxProcessorFailurePolicy.Retry) |
|
|
|
{ |
|
|
|
throw; |
|
|
|
} |
|
|
|
|
|
|
|
if (InboxProcessorOptions.FailurePolicy == InboxProcessorFailurePolicy.RetryLater) |
|
|
|
{ |
|
|
|
using (var uow = UnitOfWorkManager.Begin(isTransactional: true, requiresNew: true)) |
|
|
|
{ |
|
|
|
if (waitingEvent.RetryCount >= InboxProcessorOptions.MaxRetryCount) |
|
|
|
{ |
|
|
|
Logger.LogWarning($"Max retry count reached for event with id = {waitingEvent.Id:N}. Discarding the event."); |
|
|
|
|
|
|
|
await Inbox.MarkAsDiscardAsync(waitingEvent.Id); |
|
|
|
await uow.CompleteAsync(StoppingToken); |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
Logger.LogInformation($"Retrying event with id = {waitingEvent.Id:N}. " + |
|
|
|
$"Retry count: {waitingEvent.RetryCount}, " + |
|
|
|
$"Next retry time: {GetNextRetryTime(waitingEvent.RetryCount, InboxProcessorOptions.MaxRetryCount)}"); |
|
|
|
|
|
|
|
await Inbox.RetryLaterAsync(waitingEvent.Id, waitingEvent.RetryCount++, GetNextRetryTime(waitingEvent.RetryCount, InboxProcessorOptions.MaxRetryCount)); |
|
|
|
await uow.CompleteAsync(StoppingToken); |
|
|
|
} |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
if (InboxProcessorOptions.FailurePolicy == InboxProcessorFailurePolicy.Discard) |
|
|
|
{ |
|
|
|
using (var uow = UnitOfWorkManager.Begin(isTransactional: true, requiresNew: true)) |
|
|
|
{ |
|
|
|
Logger.LogInformation($"Discarding event with id = {waitingEvent.Id:N} due to an error."); |
|
|
|
await Inbox.MarkAsDiscardAsync(waitingEvent.Id); |
|
|
|
await uow.CompleteAsync(StoppingToken); |
|
|
|
} |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -137,6 +184,18 @@ public class InboxProcessor : IInboxProcessor, ITransientDependency |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
protected virtual DateTime? GetNextRetryTime(int retryCount, int maxRetryCount) |
|
|
|
{ |
|
|
|
if (retryCount > maxRetryCount) |
|
|
|
{ |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
var delaySeconds = 1 * (int)Math.Pow(2, retryCount - 1); |
|
|
|
|
|
|
|
return DateTime.Now.AddSeconds(delaySeconds); |
|
|
|
} |
|
|
|
|
|
|
|
protected virtual async Task<List<IncomingEventInfo>> GetWaitingEventsAsync() |
|
|
|
{ |
|
|
|
return await Inbox.GetWaitingEventsAsync(EventBusBoxesOptions.InboxWaitingEventMaxCount, EventBusBoxesOptions.InboxProcessorFilter, StoppingToken); |
|
|
|
|