Feat: Edición y Manejo de Titulares, entre otros.
This commit is contained in:
@@ -9,17 +9,27 @@ using Titulares.Api.Models;
|
||||
|
||||
namespace Titulares.Api.Workers;
|
||||
|
||||
public class ProcesoScrapingWorker : BackgroundService
|
||||
public class ProcesoScrapingWorker : BackgroundService, IDisposable
|
||||
{
|
||||
private readonly ILogger<ProcesoScrapingWorker> _logger;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly IOptionsMonitor<ConfiguracionApp> _configuracion;
|
||||
private readonly IDisposable? _optionsReloadToken;
|
||||
|
||||
private CancellationTokenSource? _delayCts;
|
||||
|
||||
public ProcesoScrapingWorker(ILogger<ProcesoScrapingWorker> logger, IServiceProvider serviceProvider, IOptionsMonitor<ConfiguracionApp> configuracion)
|
||||
{
|
||||
_logger = logger;
|
||||
_serviceProvider = serviceProvider;
|
||||
_configuracion = configuracion;
|
||||
_optionsReloadToken = _configuracion.OnChange(OnConfigurationChanged);
|
||||
}
|
||||
|
||||
private void OnConfigurationChanged(ConfiguracionApp newConfig)
|
||||
{
|
||||
_logger.LogInformation("La configuración ha cambiado. Interrumpiendo la espera actual para aplicar los nuevos ajustes.");
|
||||
_delayCts?.Cancel();
|
||||
}
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
@@ -27,42 +37,26 @@ public class ProcesoScrapingWorker : BackgroundService
|
||||
while (!stoppingToken.IsCancellationRequested)
|
||||
{
|
||||
var configActual = _configuracion.CurrentValue;
|
||||
|
||||
_logger.LogInformation("Iniciando ciclo de scraping con cantidad: {cantidad}", configActual.CantidadTitularesAScrapear);
|
||||
|
||||
try
|
||||
{
|
||||
// Creamos un 'scope' para obtener instancias 'scoped' de nuestros servicios.
|
||||
// Es la práctica correcta en servicios de larga duración.
|
||||
using (var scope = _serviceProvider.CreateScope())
|
||||
{
|
||||
var repositorio = scope.ServiceProvider.GetRequiredService<TitularRepositorio>();
|
||||
var scrapingService = scope.ServiceProvider.GetRequiredService<ScrapingService>();
|
||||
var hubContext = scope.ServiceProvider.GetRequiredService<IHubContext<TitularesHub>>();
|
||||
var csvService = scope.ServiceProvider.GetRequiredService<CsvService>();
|
||||
int cantidadTitulares = configActual.CantidadTitularesAScrapear;
|
||||
var articulosScrapeados = await scrapingService.ObtenerUltimosTitulares(cantidadTitulares);
|
||||
|
||||
// Obtener estos valores desde la configuración
|
||||
int cantidadAObtener = configActual.CantidadTitularesAScrapear;
|
||||
int limiteTotalEnDb = configActual.LimiteTotalEnDb;
|
||||
await repositorio.SincronizarDesdeScraping(articulosScrapeados, cantidadTitulares);
|
||||
_logger.LogInformation("Sincronización con la base de datos completada.");
|
||||
|
||||
// 1. Obtener los últimos titulares de la web
|
||||
var articulosScrapeados = await scrapingService.ObtenerUltimosTitulares(cantidadAObtener);
|
||||
|
||||
if (articulosScrapeados.Any())
|
||||
{
|
||||
await repositorio.SincronizarDesdeScraping(articulosScrapeados, limiteTotalEnDb);
|
||||
_logger.LogInformation("Sincronización con la base de datos completada.");
|
||||
|
||||
var titularesActualizados = await repositorio.ObtenerTodosAsync();
|
||||
await hubContext.Clients.All.SendAsync("TitularesActualizados", titularesActualizados, stoppingToken);
|
||||
_logger.LogInformation("Notificación enviada a los clientes.");
|
||||
|
||||
await csvService.GenerarCsvAsync(titularesActualizados);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogWarning("No se encontraron artículos en el scraping.");
|
||||
}
|
||||
var titularesActualizados = await repositorio.ObtenerTodosAsync();
|
||||
await hubContext.Clients.All.SendAsync("TitularesActualizados", titularesActualizados, stoppingToken);
|
||||
_logger.LogInformation("Notificación enviada a los clientes.");
|
||||
await csvService.GenerarCsvAsync(titularesActualizados);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -72,7 +66,29 @@ public class ProcesoScrapingWorker : BackgroundService
|
||||
|
||||
var intervaloEnMinutos = configActual.IntervaloMinutos;
|
||||
_logger.LogInformation("Proceso en espera por {minutos} minutos.", intervaloEnMinutos);
|
||||
await Task.Delay(TimeSpan.FromMinutes(intervaloEnMinutos), stoppingToken);
|
||||
|
||||
try
|
||||
{
|
||||
_delayCts = new CancellationTokenSource();
|
||||
using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(stoppingToken, _delayCts.Token);
|
||||
await Task.Delay(TimeSpan.FromMinutes(intervaloEnMinutos), linkedCts.Token);
|
||||
}
|
||||
catch (TaskCanceledException)
|
||||
{
|
||||
_logger.LogInformation("La espera fue interrumpida. Reiniciando el ciclo.");
|
||||
}
|
||||
finally
|
||||
{
|
||||
_delayCts?.Dispose();
|
||||
_delayCts = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
_optionsReloadToken?.Dispose();
|
||||
_delayCts?.Dispose();
|
||||
base.Dispose();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user