feat(infrastructure): implement IEmailSyncService on EmailSyncWorker with rate-limited ForceTriggerSync via IMemoryCache; register as singleton in DI
This commit is contained in:
@@ -13,6 +13,7 @@ using Microsoft.AspNetCore.DataProtection;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace DigitalData.MessagingService.Infrastructure;
|
||||
|
||||
@@ -71,6 +72,13 @@ public static class DependencyInjection
|
||||
services.AddHostedService<AsyncInitWorker>();
|
||||
services.AddHostedService<EmailSyncWorker>();
|
||||
|
||||
services.AddSingleton<IEmailSyncService>(p =>
|
||||
{
|
||||
var hostedServices = p.GetRequiredService<IEnumerable<IHostedService>>();
|
||||
var emailSyncWorkers = hostedServices.OfType<EmailSyncWorker>();
|
||||
return emailSyncWorkers.FirstOrDefault() ?? throw new InvalidOperationException("EmailSyncWorker is not registered.");
|
||||
});
|
||||
|
||||
services.AddMemoryCache();
|
||||
|
||||
// --- Database (InMemory) ---
|
||||
|
||||
@@ -3,6 +3,7 @@ using DigitalData.MessagingService.Application.Common.Interfaces.Repositories;
|
||||
using DigitalData.MessagingService.Application.Common.Options;
|
||||
using DigitalData.MessagingService.Domain.Entities;
|
||||
using DigitalData.MessagingService.Domain.Enums;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
@@ -10,8 +11,10 @@ using Microsoft.Extensions.Options;
|
||||
|
||||
namespace DigitalData.MessagingService.Infrastructure.Services.Background;
|
||||
|
||||
public class EmailSyncWorker(IOptions<EmailAccountsOptions> Options, IServiceProvider Provider, ILogger<EmailSyncWorker> Logger) : BackgroundService
|
||||
public class EmailSyncWorker(IOptions<EmailAccountsOptions> Options, IServiceProvider Provider, ILogger<EmailSyncWorker> Logger, IMemoryCache Cache) : BackgroundService, IEmailSyncService
|
||||
{
|
||||
private static string ForcedSyncDateCacheKey => $"{nameof(EmailSyncWorker)}_TriggerSync";
|
||||
|
||||
private readonly string DefaultFolder = "INBOX";
|
||||
|
||||
/// <summary>
|
||||
@@ -26,7 +29,15 @@ public class EmailSyncWorker(IOptions<EmailAccountsOptions> Options, IServicePro
|
||||
/// Safe to call from any thread or HTTP request at any time.
|
||||
/// If a sync is already running, the trigger is ignored — the next cycle starts normally.
|
||||
/// </summary>
|
||||
public void TriggerSync() => _syncTrigger.TrySetResult(true);
|
||||
public DateTime ForceTriggerSync()
|
||||
{
|
||||
return Cache.GetOrCreate(ForcedSyncDateCacheKey, e =>
|
||||
{
|
||||
e.SetAbsoluteExpiration(TimeSpan.FromSeconds(Options.Value.ForcedSyncIntervalSeconds));
|
||||
_syncTrigger.TrySetResult(true);
|
||||
return DateTime.UtcNow;
|
||||
});
|
||||
}
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
@@ -98,7 +109,7 @@ public class EmailSyncWorker(IOptions<EmailAccountsOptions> Options, IServicePro
|
||||
}
|
||||
}
|
||||
|
||||
public async Task UpsertSeedEmailAccount(CancellationToken stoppingToken)
|
||||
private async Task UpsertSeedEmailAccount(CancellationToken stoppingToken)
|
||||
{
|
||||
await using var scope = Provider.CreateAsyncScope();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user