Isolate MAX chat commands from outbox sends
This commit is contained in:
@@ -16,9 +16,12 @@ public sealed class MaxOutboxService(
|
||||
IHubContext<QMaxHub> hubContext,
|
||||
ILogger<MaxOutboxService> logger)
|
||||
{
|
||||
private static readonly TimeSpan InitialChatActionRetryDelay = TimeSpan.FromMinutes(10);
|
||||
private static readonly TimeSpan MaxChatActionRetryDelay = TimeSpan.FromHours(6);
|
||||
|
||||
public async Task<int> ProcessOnceAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var processed = await ProcessPendingChatActionsAsync(cancellationToken);
|
||||
var processed = 0;
|
||||
|
||||
var candidates = await db.Messages
|
||||
.Include(message => message.Chat)
|
||||
@@ -47,18 +50,20 @@ public sealed class MaxOutboxService(
|
||||
}
|
||||
}
|
||||
|
||||
return processed;
|
||||
return processed + await ProcessPendingChatActionsAsync(cancellationToken);
|
||||
}
|
||||
|
||||
private async Task<int> ProcessPendingChatActionsAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
var pending = await db.Chats
|
||||
.Where(chat => chat.PendingMaxAction != null)
|
||||
.ToListAsync(cancellationToken);
|
||||
pending = pending
|
||||
.Where(chat => IsChatActionDue(chat, now))
|
||||
.OrderBy(chat => chat.PendingMaxActionRequestedAt ?? chat.UpdatedAt)
|
||||
.ThenBy(chat => chat.Id)
|
||||
.Take(10)
|
||||
.Take(1)
|
||||
.ToList();
|
||||
|
||||
var processed = 0;
|
||||
@@ -74,6 +79,30 @@ public sealed class MaxOutboxService(
|
||||
return processed;
|
||||
}
|
||||
|
||||
private static bool IsChatActionDue(Chat chat, DateTimeOffset now)
|
||||
{
|
||||
if (chat.PendingMaxActionLastAttemptAt is null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return now - chat.PendingMaxActionLastAttemptAt.Value >= GetChatActionRetryDelay(chat.PendingMaxActionAttempts);
|
||||
}
|
||||
|
||||
private static TimeSpan GetChatActionRetryDelay(int attempts)
|
||||
{
|
||||
if (attempts <= 1)
|
||||
{
|
||||
return InitialChatActionRetryDelay;
|
||||
}
|
||||
|
||||
var multiplier = Math.Pow(2, Math.Min(attempts - 1, 5));
|
||||
var retryDelay = TimeSpan.FromTicks((long)(InitialChatActionRetryDelay.Ticks * multiplier));
|
||||
return retryDelay <= MaxChatActionRetryDelay
|
||||
? retryDelay
|
||||
: MaxChatActionRetryDelay;
|
||||
}
|
||||
|
||||
private async Task<bool> ProcessChatActionAsync(Chat chat, CancellationToken cancellationToken)
|
||||
{
|
||||
var pendingAction = chat.PendingMaxAction;
|
||||
@@ -110,6 +139,8 @@ public sealed class MaxOutboxService(
|
||||
{
|
||||
chat.PendingMaxAction = null;
|
||||
chat.PendingMaxActionRequestedAt = null;
|
||||
chat.PendingMaxActionLastAttemptAt = null;
|
||||
chat.PendingMaxActionAttempts = 0;
|
||||
chat.PendingMaxActionError = null;
|
||||
}
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user