Supress execution context flow when queuing email task. (#14571)

This commit is contained in:
Mole
2023-07-19 13:42:25 +02:00
committed by GitHub
parent d1aac3964c
commit 4824fc8839

View File

@@ -565,49 +565,58 @@ public class NotificationService : INotificationService
}
}
private void Process(BlockingCollection<NotificationRequest> notificationRequests) =>
ThreadPool.QueueUserWorkItem(state =>
private void Process(BlockingCollection<NotificationRequest> notificationRequests)
{
// We need to suppress the flow of the ExecutionContext when starting a new thread.
// Otherwise our scope stack will leak into the context of the new thread, leading to disposing race conditions.
using (ExecutionContext.SuppressFlow())
{
if (_logger.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug))
ThreadPool.QueueUserWorkItem(state =>
{
_logger.LogDebug("Begin processing notifications.");
}
while (true)
{
// stay on for 8s
while (notificationRequests.TryTake(out NotificationRequest? request, 8 * 1000))
if (_logger.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug))
{
try
_logger.LogDebug("Begin processing notifications.");
}
while (true)
{
// stay on for 8s
while (notificationRequests.TryTake(out NotificationRequest? request, 8 * 1000))
{
_emailSender.SendAsync(request.Mail, Constants.Web.EmailTypes.Notification).GetAwaiter()
.GetResult();
if (_logger.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug))
try
{
_logger.LogDebug("Notification '{Action}' sent to {Username} ({Email})", request.Action, request.UserName, request.Email);
_emailSender.SendAsync(request.Mail, Constants.Web.EmailTypes.Notification).GetAwaiter()
.GetResult();
if (_logger.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug))
{
_logger.LogDebug("Notification '{Action}' sent to {Username} ({Email})", request.Action, request.UserName, request.Email);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "An error occurred sending notification");
}
}
catch (Exception ex)
lock (Locker)
{
_logger.LogError(ex, "An error occurred sending notification");
if (notificationRequests.Count > 0)
{
continue; // last chance
}
_running = false; // going down
break;
}
}
lock (Locker)
if (_logger.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug))
{
if (notificationRequests.Count > 0)
{
continue; // last chance
}
_running = false; // going down
break;
_logger.LogDebug("Done processing notifications.");
}
}
if (_logger.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug))
{
_logger.LogDebug("Done processing notifications.");
}
});
});
}
}
private class NotificationRequest
{