refactor(infrastructure): migrate EmailSyncWorker to DB-backed account source with upsert seed

- EmailSyncWorker now fetches active email accounts from IRepository<EmailAccount>
  on every polling cycle instead of reading from static options list
- Add UpsertSeedEmailAccount: on startup, seed accounts from EmailAccountsOptions
  into the database via IRepository.UpsertAsync (insert or update by Username)
- Remove standalone EmailAccountSyncWorker (merged into EmailSyncWorker)
This commit is contained in:
2026-08-13 11:58:12 +02:00
parent 14180860d3
commit 25d0c009ee
2 changed files with 22 additions and 28 deletions

View File

@@ -1,26 +0,0 @@
using DigitalData.MessagingService.Application.Common.Interfaces.Repositories;
using DigitalData.MessagingService.Application.Common.Options;
using DigitalData.MessagingService.Domain.Entities;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
namespace DigitalData.MessagingService.Infrastructure.Services.Background;
/// <summary>
/// A hosted background service responsible for initializing the competing email consumer pool.
/// Leverages a push-based, event-driven RabbitMQ consumer to eliminate polling overhead.
/// Email account configuration is resolved exclusively from application settings; no database access is performed.
/// </summary>
public class EmailAccountSyncWorker(IRepository<EmailAccount> Repository, IOptions<EmailAccountsOptions> Options) : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
foreach (var account in Options.Value.Accounts)
{
if (account is EmailAccount emailAccount)
await Repository.UpsertAsync(a => a.Username == emailAccount.Username, emailAccount, stoppingToken);
}
await Task.Delay(Timeout.Infinite, stoppingToken).ConfigureAwait(ConfigureAwaitOptions.SuppressThrowing);
}
}

View File

@@ -1,17 +1,22 @@
using DigitalData.MessagingService.Application.Common.Dto.MailSearch; using DigitalData.MessagingService.Application.Common.Dto.MailSearch;
using DigitalData.MessagingService.Application.Common.Interfaces; using DigitalData.MessagingService.Application.Common.Interfaces;
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 Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
namespace DigitalData.MessagingService.Infrastructure.Services.Background; namespace DigitalData.MessagingService.Infrastructure.Services.Background;
public class EmailSyncWorker(IImapEmailService imapService, IOptions<EmailAccountsOptions> Options) : BackgroundService public class EmailSyncWorker(IImapEmailService imapService, IOptions<EmailAccountsOptions> Options, IServiceProvider Provider) : BackgroundService
{ {
private DateFilter? _dateFilter = null; private DateFilter? _dateFilter = null;
protected override async Task ExecuteAsync(CancellationToken stoppingToken) protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{ {
await UpsertSeedEmailAccount(stoppingToken);
if (imapService is not LimilabsImapEmailService limapService) if (imapService is not LimilabsImapEmailService limapService)
{ {
await Task.Delay(Timeout.Infinite, stoppingToken).ConfigureAwait(ConfigureAwaitOptions.SuppressThrowing); await Task.Delay(Timeout.Infinite, stoppingToken).ConfigureAwait(ConfigureAwaitOptions.SuppressThrowing);
@@ -22,7 +27,11 @@ public class EmailSyncWorker(IImapEmailService imapService, IOptions<EmailAccoun
while (!stoppingToken.IsCancellationRequested) while (!stoppingToken.IsCancellationRequested)
{ {
foreach (var account in Options.Value.Accounts) using var scope = Provider.CreateAsyncScope();
var emailAccountRepo = scope.ServiceProvider.GetRequiredService<IRepository<EmailAccount>>();
foreach (var account in await emailAccountRepo.GetAllAsync(stoppingToken))
if (account.ImapServer is not null) if (account.ImapServer is not null)
{ {
// init or update last date filter // init or update last date filter
@@ -44,4 +53,15 @@ public class EmailSyncWorker(IImapEmailService imapService, IOptions<EmailAccoun
await Task.Delay(interval, stoppingToken).ConfigureAwait(ConfigureAwaitOptions.SuppressThrowing); await Task.Delay(interval, stoppingToken).ConfigureAwait(ConfigureAwaitOptions.SuppressThrowing);
} }
} }
public async Task UpsertSeedEmailAccount(CancellationToken stoppingToken)
{
using var scope = Provider.CreateAsyncScope();
var emailAccountRepo = scope.ServiceProvider.GetRequiredService<IRepository<EmailAccount>>();
// init seed email accounts if not exist
foreach (var account in Options.Value.Accounts)
await emailAccountRepo.UpsertAsync(a => a.Username == account.Username, account, stoppingToken);
}
} }