refactor(infrastructure): dispatch EmailSyncWorker by IncomingProtocol, add POP3 sync path, use await using for scopes
This commit is contained in:
@@ -2,6 +2,7 @@ using DigitalData.MessagingService.Application.Common.Interfaces;
|
|||||||
using DigitalData.MessagingService.Application.Common.Interfaces.Repositories;
|
using DigitalData.MessagingService.Application.Common.Interfaces.Repositories;
|
||||||
using DigitalData.MessagingService.Application.Common.Options;
|
using DigitalData.MessagingService.Application.Common.Options;
|
||||||
using DigitalData.MessagingService.Domain.Entities;
|
using DigitalData.MessagingService.Domain.Entities;
|
||||||
|
using DigitalData.MessagingService.Domain.Enums;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
@@ -21,40 +22,66 @@ public class EmailSyncWorker(IOptions<EmailAccountsOptions> Options, IServicePro
|
|||||||
|
|
||||||
while (!stoppingToken.IsCancellationRequested)
|
while (!stoppingToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
using var scope = Provider.CreateAsyncScope();
|
await using var scope = Provider.CreateAsyncScope();
|
||||||
|
|
||||||
var emailAccountRepo = scope.ServiceProvider.GetRequiredService<IRepository<EmailAccount>>();
|
var emailAccountRepo = scope.ServiceProvider.GetRequiredService<IRepository<EmailAccount>>();
|
||||||
|
|
||||||
var imapService = scope.ServiceProvider.GetRequiredService<IImapEmailService>();
|
var imapService = scope.ServiceProvider.GetRequiredService<IImapEmailService>();
|
||||||
|
var pop3Service = scope.ServiceProvider.GetRequiredService<IPop3EmailService>();
|
||||||
|
|
||||||
foreach (var account in await emailAccountRepo.GetAllAsync(stoppingToken))
|
foreach (var account in await emailAccountRepo.GetAllAsync(stoppingToken))
|
||||||
if (account.ImapServer is not null)
|
{
|
||||||
{
|
await SyncAccountAsync(account, imapService, pop3Service, stoppingToken);
|
||||||
Logger.LogDebug("Email synchronization has started for account {username} in folder {folder}.", account.Username, DefaultFolder);
|
}
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var res = await imapService.SyncEmailsAsync(account, DefaultFolder, stoppingToken);
|
|
||||||
Logger.LogDebug("Email synchronization has completed for account {username} in folder {folder}. Processed: {processedCount}, Failed: {failedCount}", account.Username, DefaultFolder, res.ProcessedCount, res.FailedCount);
|
|
||||||
}
|
|
||||||
catch(Exception ex)
|
|
||||||
{
|
|
||||||
// Log the exception or handle it as needed
|
|
||||||
Logger.LogError(ex, "Error syncing emails for account {username}", account.Username);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await Task.Delay(interval, stoppingToken).ConfigureAwait(ConfigureAwaitOptions.SuppressThrowing);
|
await Task.Delay(interval, stoppingToken).ConfigureAwait(ConfigureAwaitOptions.SuppressThrowing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task SyncAccountAsync(
|
||||||
|
EmailAccount account,
|
||||||
|
IImapEmailService imapService,
|
||||||
|
IPop3EmailService pop3Service,
|
||||||
|
CancellationToken stoppingToken)
|
||||||
|
{
|
||||||
|
if (account.IncomingProtocol == IncomingProtocol.None)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Logger.LogDebug(
|
||||||
|
"Email sync started. Account={Username}, Protocol={Protocol}.",
|
||||||
|
account.Username, account.IncomingProtocol);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = account.IncomingProtocol switch
|
||||||
|
{
|
||||||
|
IncomingProtocol.Imap or IncomingProtocol.ImapOAuth2
|
||||||
|
=> await imapService.SyncEmailsAsync(account, DefaultFolder, stoppingToken),
|
||||||
|
|
||||||
|
IncomingProtocol.Pop3 or IncomingProtocol.Pop3OAuth2
|
||||||
|
=> await pop3Service.SyncEmailsAsync(account, stoppingToken),
|
||||||
|
|
||||||
|
_ => throw new NotSupportedException(
|
||||||
|
$"IncomingProtocol '{account.IncomingProtocol}' is not supported by the sync worker.")
|
||||||
|
};
|
||||||
|
|
||||||
|
Logger.LogDebug(
|
||||||
|
"Email sync completed. Account={Username}, Protocol={Protocol}, Processed={Processed}, Failed={Failed}.",
|
||||||
|
account.Username, account.IncomingProtocol, result.ProcessedCount, result.FailedCount);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.LogError(ex,
|
||||||
|
"Email sync failed. Account={Username}, Protocol={Protocol}.",
|
||||||
|
account.Username, account.IncomingProtocol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task UpsertSeedEmailAccount(CancellationToken stoppingToken)
|
public async Task UpsertSeedEmailAccount(CancellationToken stoppingToken)
|
||||||
{
|
{
|
||||||
using var scope = Provider.CreateAsyncScope();
|
await using var scope = Provider.CreateAsyncScope();
|
||||||
|
|
||||||
var emailAccountRepo = scope.ServiceProvider.GetRequiredService<IRepository<EmailAccount>>();
|
var emailAccountRepo = scope.ServiceProvider.GetRequiredService<IRepository<EmailAccount>>();
|
||||||
|
|
||||||
// init seed email accounts if not exist
|
|
||||||
foreach (var account in Options.Value.Accounts)
|
foreach (var account in Options.Value.Accounts)
|
||||||
await emailAccountRepo.UpsertAsync(a => a.Username == account.Username, account, stoppingToken);
|
await emailAccountRepo.UpsertAsync(a => a.Username == account.Username, account, stoppingToken);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user