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.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
|
||||||
namespace DigitalData.MessagingService.Infrastructure;
|
namespace DigitalData.MessagingService.Infrastructure;
|
||||||
|
|
||||||
@@ -71,6 +72,13 @@ public static class DependencyInjection
|
|||||||
services.AddHostedService<AsyncInitWorker>();
|
services.AddHostedService<AsyncInitWorker>();
|
||||||
services.AddHostedService<EmailSyncWorker>();
|
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();
|
services.AddMemoryCache();
|
||||||
|
|
||||||
// --- Database (InMemory) ---
|
// --- Database (InMemory) ---
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ 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 DigitalData.MessagingService.Domain.Enums;
|
||||||
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
@@ -10,8 +11,10 @@ using Microsoft.Extensions.Options;
|
|||||||
|
|
||||||
namespace DigitalData.MessagingService.Infrastructure.Services.Background;
|
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";
|
private readonly string DefaultFolder = "INBOX";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -26,7 +29,15 @@ public class EmailSyncWorker(IOptions<EmailAccountsOptions> Options, IServicePro
|
|||||||
/// Safe to call from any thread or HTTP request at any time.
|
/// 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.
|
/// If a sync is already running, the trigger is ignored — the next cycle starts normally.
|
||||||
/// </summary>
|
/// </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)
|
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();
|
await using var scope = Provider.CreateAsyncScope();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user